Browse Source

ai 图片开发完毕

100Years 1 month ago
parent
commit
c63073bfb3
96 changed files with 3280 additions and 171 deletions
  1. 168 2
      AIRingtone.xcodeproj/project.pbxproj
  2. 1 1
      AIRingtone.xcodeproj/xcuserdata/100years.xcuserdatad/xcschemes/xcschememanagement.plist
  3. 6 0
      AIRingtone/Assets.xcassets/AIPhoto/Contents.json
  4. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/Contents.json
  5. BIN
      AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/bottom_alert_bg@2x.png
  6. BIN
      AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/bottom_alert_bg@3x.png
  7. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/Contents.json
  8. BIN
      AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/generation_failed@2x.png
  9. BIN
      AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/generation_failed@3x.png
  10. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/Contents.json
  11. BIN
      AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@2x.png
  12. BIN
      AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@3x.png
  13. 6 0
      AIRingtone/Assets.xcassets/AIPhoto/style/Contents.json
  14. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/Contents.json
  15. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/ptp_selected_border@2x.png
  16. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/ptp_selected_border@3x.png
  17. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/Contents.json
  18. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/ptp_style_0@2x.png
  19. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/ptp_style_0@3x.png
  20. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/Contents.json
  21. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/ptp_style_1@2x.png
  22. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/ptp_style_1@3x.png
  23. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/Contents.json
  24. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/ptp_style_2@2x.png
  25. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/ptp_style_2@3x.png
  26. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/Contents.json
  27. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/ptp_style_3@2x.png
  28. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/ptp_style_3@3x.png
  29. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/Contents.json
  30. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/ptp_style_4@2x.png
  31. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/ptp_style_4@3x.png
  32. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/Contents.json
  33. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/ptp_style_5@2x.png
  34. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/ptp_style_5@3x.png
  35. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/Contents.json
  36. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/ptp_style_6@2x.png
  37. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/ptp_style_6@3x.png
  38. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/Contents.json
  39. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/ptp_style_7@2x.png
  40. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/ptp_style_7@3x.png
  41. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/Contents.json
  42. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/ptp_style_8@2x.png
  43. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/ptp_style_8@3x.png
  44. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/Contents.json
  45. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@2x.png
  46. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@3x.png
  47. BIN
      AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@2x.png
  48. BIN
      AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@3x.png
  49. 6 0
      AIRingtone/Assets.xcassets/Common/TextView/Contents.json
  50. 22 0
      AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/Contents.json
  51. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@2x.png
  52. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@3x.png
  53. 22 0
      AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/Contents.json
  54. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/hint@2x.png
  55. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/hint@3x.png
  56. 22 0
      AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/Contents.json
  57. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/textView_lb@2x.png
  58. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/textView_lb@3x.png
  59. 22 0
      AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/Contents.json
  60. BIN
      AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/refresh_gary@2x.png
  61. BIN
      AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/refresh_gary@3x.png
  62. 46 0
      AIRingtone/Business/Data/TSUserDefaultData.swift
  63. 126 0
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift
  64. 55 0
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVM.swift
  65. 43 0
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/View/TSAIPhotoImageCell.swift
  66. 153 2
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift
  67. 335 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicBrowseVC/TSGeneralPicBrowseVC.swift
  68. 78 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSGeneralPicModel.swift
  69. 95 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSProgressState.swift
  70. 124 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC+Event.swift
  71. 104 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift
  72. 134 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift
  73. 22 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/Model/TSPTPStyleModel.swift
  74. 62 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/Model/photo_to_photo_style.json
  75. 169 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/TSTextGeneralPicVC.swift
  76. 87 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/VM/TSTextGeneralPicVM.swift
  77. 168 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptStyleView.swift
  78. 228 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift
  79. 28 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSTGPTitleView.swift
  80. 52 0
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TsTGPPhotoStyleView.swift
  81. 27 0
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC.swift
  82. 87 0
      AIRingtone/Business/TSCollectionViewVM/TSCollectionViewVM+Config.swift
  83. 7 0
      AIRingtone/Business/TSCollectionViewVM/TSCollectionViewVM.swift
  84. 2 1
      AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetVC.swift
  85. 5 0
      AIRingtone/Business/TSThemeVC/TSThemeVC/Model/TSThemeModel.swift
  86. 0 14
      AIRingtone/Business/TSThemeVC/TSThemeVC/View/TSThemeContentCell.swift
  87. 288 0
      AIRingtone/Business/VIewTool/TSBottomAlertVC.swift
  88. 24 36
      AIRingtone/Business/VIewTool/TSCommonloadingView.swift
  89. 109 0
      AIRingtone/Business/VIewTool/TSSavePhotoSuccessTool.swift
  90. 11 112
      AIRingtone/Business/VIewTool/TSViewTool.swift
  91. 2 2
      AIRingtone/Common/Config/TSConfig.swift
  92. 14 0
      AIRingtone/Common/Ex/Notification+TSEx.swift
  93. BIN
      AIRingtone/Common/Res/rotatingAnimation.gif
  94. 6 0
      AIRingtone/Common/View/UIStackView/TSCustomStackView.swift
  95. 1 0
      Podfile
  96. 5 1
      Podfile.lock

+ 168 - 2
AIRingtone.xcodeproj/project.pbxproj

@@ -42,6 +42,10 @@
 		A80EDF272D71C13D003CD332 /* TSColVVMHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF262D71C13C003CD332 /* TSColVVMHeaderModel.swift */; };
 		A80EDF272D71C13D003CD332 /* TSColVVMHeaderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF262D71C13C003CD332 /* TSColVVMHeaderModel.swift */; };
 		A80EDF2A2D71C215003CD332 /* TSThemeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF292D71C211003CD332 /* TSThemeVM.swift */; };
 		A80EDF2A2D71C215003CD332 /* TSThemeVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF292D71C211003CD332 /* TSThemeVM.swift */; };
 		A80EDF2D2D71C2CA003CD332 /* TSThemeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF2C2D71C2BF003CD332 /* TSThemeModel.swift */; };
 		A80EDF2D2D71C2CA003CD332 /* TSThemeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDF2C2D71C2BF003CD332 /* TSThemeModel.swift */; };
+		A83F871D2D79409B00D29B1B /* TSUserDefaultData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F871C2D79409300D29B1B /* TSUserDefaultData.swift */; };
+		A83F87202D794FF000D29B1B /* TSAIPhotoImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F871F2D794FE600D29B1B /* TSAIPhotoImageCell.swift */; };
+		A83F87222D7953C000D29B1B /* Notification+TSEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F87212D7953BA00D29B1B /* Notification+TSEx.swift */; };
+		A83F87242D7954BB00D29B1B /* TSAIPhotoChildVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F87232D7954B800D29B1B /* TSAIPhotoChildVM.swift */; };
 		A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */; };
 		A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */; };
 		A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */; };
 		A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */; };
 		A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89D2D7560B900F6D884 /* TSPageNullView.swift */; };
 		A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89D2D7560B900F6D884 /* TSPageNullView.swift */; };
@@ -72,6 +76,24 @@
 		A868A8EF2D77041400F6D884 /* TSLoadingAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8EE2D77040F00F6D884 /* TSLoadingAnimation.swift */; };
 		A868A8EF2D77041400F6D884 /* TSLoadingAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8EE2D77040F00F6D884 /* TSLoadingAnimation.swift */; };
 		A868A8F12D77081C00F6D884 /* TSContactsTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8F02D77081B00F6D884 /* TSContactsTool.swift */; };
 		A868A8F12D77081C00F6D884 /* TSContactsTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8F02D77081B00F6D884 /* TSContactsTool.swift */; };
 		A868A8F22D770A9200F6D884 /* libmp3lame.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A868A8E42D76FA4200F6D884 /* libmp3lame.a */; };
 		A868A8F22D770A9200F6D884 /* libmp3lame.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A868A8E42D76FA4200F6D884 /* libmp3lame.a */; };
+		A868A8F52D77179D00F6D884 /* TSAIPhotoChildVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8F42D77179C00F6D884 /* TSAIPhotoChildVC.swift */; };
+		A868A8F82D77E2BC00F6D884 /* TSTextGeneralPicVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8F72D77E2B900F6D884 /* TSTextGeneralPicVC.swift */; };
+		A868A8FA2D77E35E00F6D884 /* TSPromptTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8F92D77E34D00F6D884 /* TSPromptTextView.swift */; };
+		A868A9002D77E55800F6D884 /* TSPromptStyleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8FF2D77E54A00F6D884 /* TSPromptStyleView.swift */; };
+		A868A9032D77E5A500F6D884 /* TSPTPStyleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9022D77E5A400F6D884 /* TSPTPStyleModel.swift */; };
+		A868A9052D77E5AB00F6D884 /* photo_to_photo_style.json in Resources */ = {isa = PBXBuildFile; fileRef = A868A9042D77E5AB00F6D884 /* photo_to_photo_style.json */; };
+		A868A9072D77EED800F6D884 /* TSTGPTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9062D77EECC00F6D884 /* TSTGPTitleView.swift */; };
+		A868A9092D7828EC00F6D884 /* TsTGPPhotoStyleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9082D7828DF00F6D884 /* TsTGPPhotoStyleView.swift */; };
+		A868A90C2D78311A00F6D884 /* TSTextGeneralPicVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A90B2D78311400F6D884 /* TSTextGeneralPicVM.swift */; };
+		A868A90E2D7846D600F6D884 /* TSSavePhotoSuccessTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A90D2D7846D400F6D884 /* TSSavePhotoSuccessTool.swift */; };
+		A868A9112D784CFB00F6D884 /* TSGeneralPicVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9102D784CFA00F6D884 /* TSGeneralPicVC.swift */; };
+		A868A9142D784D4D00F6D884 /* TSGeneralPicModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9132D784D2700F6D884 /* TSGeneralPicModel.swift */; };
+		A868A9162D784E6500F6D884 /* TSBottomAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9152D784E6500F6D884 /* TSBottomAlertVC.swift */; };
+		A868A9182D78555200F6D884 /* TSGenneralPicVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9172D78554800F6D884 /* TSGenneralPicVM.swift */; };
+		A868A91A2D78559800F6D884 /* TSProgressState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A9192D78559600F6D884 /* TSProgressState.swift */; };
+		A868A91C2D78592600F6D884 /* rotatingAnimation.gif in Resources */ = {isa = PBXBuildFile; fileRef = A868A91B2D78592600F6D884 /* rotatingAnimation.gif */; };
+		A868A91E2D785CEA00F6D884 /* TSGeneralPicVC+Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A91D2D785CE600F6D884 /* TSGeneralPicVC+Event.swift */; };
+		A8CC55822D797720002E0CAA /* TSGeneralPicBrowseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CC55812D79771F002E0CAA /* TSGeneralPicBrowseVC.swift */; };
 		F5FF0EC10B0056B65FDB9C78 /* Pods_AIRingtone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39C823AB7F3D49E8B2356E07 /* Pods_AIRingtone.framework */; };
 		F5FF0EC10B0056B65FDB9C78 /* Pods_AIRingtone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39C823AB7F3D49E8B2356E07 /* Pods_AIRingtone.framework */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
@@ -116,6 +138,10 @@
 		A80EDF262D71C13C003CD332 /* TSColVVMHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSColVVMHeaderModel.swift; sourceTree = "<group>"; };
 		A80EDF262D71C13C003CD332 /* TSColVVMHeaderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSColVVMHeaderModel.swift; sourceTree = "<group>"; };
 		A80EDF292D71C211003CD332 /* TSThemeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeVM.swift; sourceTree = "<group>"; };
 		A80EDF292D71C211003CD332 /* TSThemeVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeVM.swift; sourceTree = "<group>"; };
 		A80EDF2C2D71C2BF003CD332 /* TSThemeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeModel.swift; sourceTree = "<group>"; };
 		A80EDF2C2D71C2BF003CD332 /* TSThemeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeModel.swift; sourceTree = "<group>"; };
+		A83F871C2D79409300D29B1B /* TSUserDefaultData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSUserDefaultData.swift; sourceTree = "<group>"; };
+		A83F871F2D794FE600D29B1B /* TSAIPhotoImageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIPhotoImageCell.swift; sourceTree = "<group>"; };
+		A83F87212D7953BA00D29B1B /* Notification+TSEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+TSEx.swift"; sourceTree = "<group>"; };
+		A83F87232D7954B800D29B1B /* TSAIPhotoChildVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIPhotoChildVM.swift; sourceTree = "<group>"; };
 		A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeBannerCell.swift; sourceTree = "<group>"; };
 		A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeBannerCell.swift; sourceTree = "<group>"; };
 		A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeContentCell.swift; sourceTree = "<group>"; };
 		A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeContentCell.swift; sourceTree = "<group>"; };
 		A868A89D2D7560B900F6D884 /* TSPageNullView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPageNullView.swift; sourceTree = "<group>"; };
 		A868A89D2D7560B900F6D884 /* TSPageNullView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPageNullView.swift; sourceTree = "<group>"; };
@@ -150,6 +176,24 @@
 		A868A8EC2D76FE5D00F6D884 /* tutorial-ring.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "tutorial-ring.mp4"; sourceTree = "<group>"; };
 		A868A8EC2D76FE5D00F6D884 /* tutorial-ring.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "tutorial-ring.mp4"; sourceTree = "<group>"; };
 		A868A8EE2D77040F00F6D884 /* TSLoadingAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSLoadingAnimation.swift; sourceTree = "<group>"; };
 		A868A8EE2D77040F00F6D884 /* TSLoadingAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSLoadingAnimation.swift; sourceTree = "<group>"; };
 		A868A8F02D77081B00F6D884 /* TSContactsTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSContactsTool.swift; sourceTree = "<group>"; };
 		A868A8F02D77081B00F6D884 /* TSContactsTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSContactsTool.swift; sourceTree = "<group>"; };
+		A868A8F42D77179C00F6D884 /* TSAIPhotoChildVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIPhotoChildVC.swift; sourceTree = "<group>"; };
+		A868A8F72D77E2B900F6D884 /* TSTextGeneralPicVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPicVC.swift; sourceTree = "<group>"; };
+		A868A8F92D77E34D00F6D884 /* TSPromptTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPromptTextView.swift; sourceTree = "<group>"; };
+		A868A8FF2D77E54A00F6D884 /* TSPromptStyleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPromptStyleView.swift; sourceTree = "<group>"; };
+		A868A9022D77E5A400F6D884 /* TSPTPStyleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPTPStyleModel.swift; sourceTree = "<group>"; };
+		A868A9042D77E5AB00F6D884 /* photo_to_photo_style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = photo_to_photo_style.json; sourceTree = "<group>"; };
+		A868A9062D77EECC00F6D884 /* TSTGPTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTGPTitleView.swift; sourceTree = "<group>"; };
+		A868A9082D7828DF00F6D884 /* TsTGPPhotoStyleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TsTGPPhotoStyleView.swift; sourceTree = "<group>"; };
+		A868A90B2D78311400F6D884 /* TSTextGeneralPicVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPicVM.swift; sourceTree = "<group>"; };
+		A868A90D2D7846D400F6D884 /* TSSavePhotoSuccessTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSSavePhotoSuccessTool.swift; sourceTree = "<group>"; };
+		A868A9102D784CFA00F6D884 /* TSGeneralPicVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGeneralPicVC.swift; sourceTree = "<group>"; };
+		A868A9132D784D2700F6D884 /* TSGeneralPicModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGeneralPicModel.swift; sourceTree = "<group>"; };
+		A868A9152D784E6500F6D884 /* TSBottomAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBottomAlertVC.swift; sourceTree = "<group>"; };
+		A868A9172D78554800F6D884 /* TSGenneralPicVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGenneralPicVM.swift; sourceTree = "<group>"; };
+		A868A9192D78559600F6D884 /* TSProgressState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSProgressState.swift; sourceTree = "<group>"; };
+		A868A91B2D78592600F6D884 /* rotatingAnimation.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = rotatingAnimation.gif; sourceTree = "<group>"; };
+		A868A91D2D785CE600F6D884 /* TSGeneralPicVC+Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSGeneralPicVC+Event.swift"; sourceTree = "<group>"; };
+		A8CC55812D79771F002E0CAA /* TSGeneralPicBrowseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGeneralPicBrowseVC.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -226,6 +270,7 @@
 		A80EDE622D718B0F003CD332 /* Res */ = {
 		A80EDE622D718B0F003CD332 /* Res */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A868A91B2D78592600F6D884 /* rotatingAnimation.gif */,
 				A868A8BE2D76A17E00F6D884 /* Poppins-BlackItalic.ttf */,
 				A868A8BE2D76A17E00F6D884 /* Poppins-BlackItalic.ttf */,
 			);
 			);
 			path = Res;
 			path = Res;
@@ -234,6 +279,7 @@
 		A80EDE632D718B19003CD332 /* Business */ = {
 		A80EDE632D718B19003CD332 /* Business */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A83F871B2D79408300D29B1B /* Data */,
 				A868A8A12D7560B900F6D884 /* VIewTool */,
 				A868A8A12D7560B900F6D884 /* VIewTool */,
 				A80EDF192D71AC2F003CD332 /* TSCollectionViewVM */,
 				A80EDF192D71AC2F003CD332 /* TSCollectionViewVM */,
 				A80EDF162D7193E4003CD332 /* TSTutorialsVC */,
 				A80EDF162D7193E4003CD332 /* TSTutorialsVC */,
@@ -404,6 +450,10 @@
 		A80EDF0F2D718E8E003CD332 /* TSAIPhotoVC */ = {
 		A80EDF0F2D718E8E003CD332 /* TSAIPhotoVC */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A8CC55802D7976E7002E0CAA /* TSGeneralPicBrowseVC */,
+				A868A90F2D784CF100F6D884 /* TSGeneralPicVC */,
+				A868A8F62D77E2A900F6D884 /* TSTextGeneralPicVC */,
+				A868A8F32D77179000F6D884 /* TSAIPhotoChildVC */,
 				A80EDF122D718EF6003CD332 /* TSAIPhotoVC.swift */,
 				A80EDF122D718EF6003CD332 /* TSAIPhotoVC.swift */,
 			);
 			);
 			path = TSAIPhotoVC;
 			path = TSAIPhotoVC;
@@ -461,6 +511,22 @@
 			path = Model;
 			path = Model;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		A83F871B2D79408300D29B1B /* Data */ = {
+			isa = PBXGroup;
+			children = (
+				A83F871C2D79409300D29B1B /* TSUserDefaultData.swift */,
+			);
+			path = Data;
+			sourceTree = "<group>";
+		};
+		A83F871E2D794FDF00D29B1B /* View */ = {
+			isa = PBXGroup;
+			children = (
+				A83F871F2D794FE600D29B1B /* TSAIPhotoImageCell.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		A868A8982D75505100F6D884 /* View */ = {
 		A868A8982D75505100F6D884 /* View */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
@@ -480,6 +546,8 @@
 		A868A8A12D7560B900F6D884 /* VIewTool */ = {
 		A868A8A12D7560B900F6D884 /* VIewTool */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A868A9152D784E6500F6D884 /* TSBottomAlertVC.swift */,
+				A868A90D2D7846D400F6D884 /* TSSavePhotoSuccessTool.swift */,
 				A868A8CF2D76D02300F6D884 /* TSRingToneCellView.swift */,
 				A868A8CF2D76D02300F6D884 /* TSRingToneCellView.swift */,
 				A868A89D2D7560B900F6D884 /* TSPageNullView.swift */,
 				A868A89D2D7560B900F6D884 /* TSPageNullView.swift */,
 				A868A89E2D7560B900F6D884 /* TSCommonloadingView.swift */,
 				A868A89E2D7560B900F6D884 /* TSCommonloadingView.swift */,
@@ -537,6 +605,7 @@
 		A868A8C02D76A28A00F6D884 /* Ex */ = {
 		A868A8C02D76A28A00F6D884 /* Ex */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A83F87212D7953BA00D29B1B /* Notification+TSEx.swift */,
 				A868A8C12D76A28F00F6D884 /* UIFont+TSEx.swift */,
 				A868A8C12D76A28F00F6D884 /* UIFont+TSEx.swift */,
 			);
 			);
 			path = Ex;
 			path = Ex;
@@ -597,6 +666,83 @@
 			path = libmp3;
 			path = libmp3;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
 		};
 		};
+		A868A8F32D77179000F6D884 /* TSAIPhotoChildVC */ = {
+			isa = PBXGroup;
+			children = (
+				A83F871E2D794FDF00D29B1B /* View */,
+				A868A8F42D77179C00F6D884 /* TSAIPhotoChildVC.swift */,
+				A83F87232D7954B800D29B1B /* TSAIPhotoChildVM.swift */,
+			);
+			path = TSAIPhotoChildVC;
+			sourceTree = "<group>";
+		};
+		A868A8F62D77E2A900F6D884 /* TSTextGeneralPicVC */ = {
+			isa = PBXGroup;
+			children = (
+				A868A90A2D78310800F6D884 /* VM */,
+				A868A9012D77E59100F6D884 /* Model */,
+				A868A8FB2D77E36000F6D884 /* View */,
+				A868A8F72D77E2B900F6D884 /* TSTextGeneralPicVC.swift */,
+			);
+			path = TSTextGeneralPicVC;
+			sourceTree = "<group>";
+		};
+		A868A8FB2D77E36000F6D884 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				A868A9082D7828DF00F6D884 /* TsTGPPhotoStyleView.swift */,
+				A868A9062D77EECC00F6D884 /* TSTGPTitleView.swift */,
+				A868A8FF2D77E54A00F6D884 /* TSPromptStyleView.swift */,
+				A868A8F92D77E34D00F6D884 /* TSPromptTextView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		A868A9012D77E59100F6D884 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				A868A9042D77E5AB00F6D884 /* photo_to_photo_style.json */,
+				A868A9022D77E5A400F6D884 /* TSPTPStyleModel.swift */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		A868A90A2D78310800F6D884 /* VM */ = {
+			isa = PBXGroup;
+			children = (
+				A868A90B2D78311400F6D884 /* TSTextGeneralPicVM.swift */,
+			);
+			path = VM;
+			sourceTree = "<group>";
+		};
+		A868A90F2D784CF100F6D884 /* TSGeneralPicVC */ = {
+			isa = PBXGroup;
+			children = (
+				A868A9172D78554800F6D884 /* TSGenneralPicVM.swift */,
+				A868A9122D784D2200F6D884 /* Model */,
+				A868A9102D784CFA00F6D884 /* TSGeneralPicVC.swift */,
+				A868A91D2D785CE600F6D884 /* TSGeneralPicVC+Event.swift */,
+			);
+			path = TSGeneralPicVC;
+			sourceTree = "<group>";
+		};
+		A868A9122D784D2200F6D884 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				A868A9132D784D2700F6D884 /* TSGeneralPicModel.swift */,
+				A868A9192D78559600F6D884 /* TSProgressState.swift */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		A8CC55802D7976E7002E0CAA /* TSGeneralPicBrowseVC */ = {
+			isa = PBXGroup;
+			children = (
+				A8CC55812D79771F002E0CAA /* TSGeneralPicBrowseVC.swift */,
+			);
+			path = TSGeneralPicBrowseVC;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 /* End PBXGroup section */
 
 
 /* Begin PBXNativeTarget section */
 /* Begin PBXNativeTarget section */
@@ -659,6 +805,8 @@
 			isa = PBXResourcesBuildPhase;
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				A868A91C2D78592600F6D884 /* rotatingAnimation.gif in Resources */,
+				A868A9052D77E5AB00F6D884 /* photo_to_photo_style.json in Resources */,
 				A80EDE5B2D718623003CD332 /* Assets.xcassets in Resources */,
 				A80EDE5B2D718623003CD332 /* Assets.xcassets in Resources */,
 				A868A8ED2D76FE5D00F6D884 /* tutorial-ring.mp4 in Resources */,
 				A868A8ED2D76FE5D00F6D884 /* tutorial-ring.mp4 in Resources */,
 				A868A8BF2D76A17E00F6D884 /* Poppins-BlackItalic.ttf in Resources */,
 				A868A8BF2D76A17E00F6D884 /* Poppins-BlackItalic.ttf in Resources */,
@@ -716,43 +864,59 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				A868A9072D77EED800F6D884 /* TSTGPTitleView.swift in Sources */,
 				A868A8C22D76A2A700F6D884 /* UIFont+TSEx.swift in Sources */,
 				A868A8C22D76A2A700F6D884 /* UIFont+TSEx.swift in Sources */,
+				A868A91A2D78559800F6D884 /* TSProgressState.swift in Sources */,
 				A868A8C92D76A45900F6D884 /* TSThemeSetItemView.swift in Sources */,
 				A868A8C92D76A45900F6D884 /* TSThemeSetItemView.swift in Sources */,
+				A868A9002D77E55800F6D884 /* TSPromptStyleView.swift in Sources */,
+				A83F87202D794FF000D29B1B /* TSAIPhotoImageCell.swift in Sources */,
 				A868A8DB2D76F00C00F6D884 /* TSBandRingTool.swift in Sources */,
 				A868A8DB2D76F00C00F6D884 /* TSBandRingTool.swift in Sources */,
 				A868A8F12D77081C00F6D884 /* TSContactsTool.swift in Sources */,
 				A868A8F12D77081C00F6D884 /* TSContactsTool.swift in Sources */,
 				A80EDF2D2D71C2CA003CD332 /* TSThemeModel.swift in Sources */,
 				A80EDF2D2D71C2CA003CD332 /* TSThemeModel.swift in Sources */,
 				A80EDE582D718623003CD332 /* AppDelegate.swift in Sources */,
 				A80EDE582D718623003CD332 /* AppDelegate.swift in Sources */,
 				A868A8EF2D77041400F6D884 /* TSLoadingAnimation.swift in Sources */,
 				A868A8EF2D77041400F6D884 /* TSLoadingAnimation.swift in Sources */,
 				A80EDE652D718CAF003CD332 /* GlobalImports.swift in Sources */,
 				A80EDE652D718CAF003CD332 /* GlobalImports.swift in Sources */,
+				A868A9092D7828EC00F6D884 /* TsTGPPhotoStyleView.swift in Sources */,
 				A80EDF112D718ED1003CD332 /* TSAIRintoneVC.swift in Sources */,
 				A80EDF112D718ED1003CD332 /* TSAIRintoneVC.swift in Sources */,
 				A80EDF1B2D71AC90003CD332 /* TSCollectionViewVM.swift in Sources */,
 				A80EDF1B2D71AC90003CD332 /* TSCollectionViewVM.swift in Sources */,
 				A80EDE612D718AF4003CD332 /* TSConfig.swift in Sources */,
 				A80EDE612D718AF4003CD332 /* TSConfig.swift in Sources */,
 				A80EDF152D718F13003CD332 /* TSThemeVC.swift in Sources */,
 				A80EDF152D718F13003CD332 /* TSThemeVC.swift in Sources */,
+				A868A9032D77E5A500F6D884 /* TSPTPStyleModel.swift in Sources */,
 				A80EDEC62D718CEA003CD332 /* TSRandomTextPicker.swift in Sources */,
 				A80EDEC62D718CEA003CD332 /* TSRandomTextPicker.swift in Sources */,
 				A80EDEC82D718CEA003CD332 /* TSNetworkManager+Loading.swift in Sources */,
 				A80EDEC82D718CEA003CD332 /* TSNetworkManager+Loading.swift in Sources */,
+				A868A9182D78555200F6D884 /* TSGenneralPicVM.swift in Sources */,
 				A80EDECB2D718CEA003CD332 /* TSNetWork+Business.swift in Sources */,
 				A80EDECB2D718CEA003CD332 /* TSNetWork+Business.swift in Sources */,
 				A80EDF0B2D718DF7003CD332 /* TSBootPageVC.swift in Sources */,
 				A80EDF0B2D718DF7003CD332 /* TSBootPageVC.swift in Sources */,
 				A80EDF0C2D718DF7003CD332 /* TSLaunchVC.swift in Sources */,
 				A80EDF0C2D718DF7003CD332 /* TSLaunchVC.swift in Sources */,
 				A80EDEDB2D718CEA003CD332 /* TSPhotoPickerManager.swift in Sources */,
 				A80EDEDB2D718CEA003CD332 /* TSPhotoPickerManager.swift in Sources */,
 				A868A8BD2D75C68300F6D884 /* TSAudioPlayer.swift in Sources */,
 				A868A8BD2D75C68300F6D884 /* TSAudioPlayer.swift in Sources */,
+				A8CC55822D797720002E0CAA /* TSGeneralPicBrowseVC.swift in Sources */,
 				A80EDEE32D718CEA003CD332 /* TSNetworkManager.swift in Sources */,
 				A80EDEE32D718CEA003CD332 /* TSNetworkManager.swift in Sources */,
 				A868A8AF2D758BBC00F6D884 /* TSTBDesktopPreviewView.swift in Sources */,
 				A868A8AF2D758BBC00F6D884 /* TSTBDesktopPreviewView.swift in Sources */,
 				A80EDEF52D718DEA003CD332 /* TSTabBarController.swift in Sources */,
 				A80EDEF52D718DEA003CD332 /* TSTabBarController.swift in Sources */,
 				A868A8B52D7598C000F6D884 /* TSTSIslandView.swift in Sources */,
 				A868A8B52D7598C000F6D884 /* TSTSIslandView.swift in Sources */,
 				A80EDEE72D718CEA003CD332 /* TSCustomStackView.swift in Sources */,
 				A80EDEE72D718CEA003CD332 /* TSCustomStackView.swift in Sources */,
+				A868A9142D784D4D00F6D884 /* TSGeneralPicModel.swift in Sources */,
 				A868A8D52D76E41800F6D884 /* TSSetContactAvatar.swift in Sources */,
 				A868A8D52D76E41800F6D884 /* TSSetContactAvatar.swift in Sources */,
+				A868A8F52D77179D00F6D884 /* TSAIPhotoChildVC.swift in Sources */,
 				A868A8E82D76FA4200F6D884 /* ExtAudioConverter.m in Sources */,
 				A868A8E82D76FA4200F6D884 /* ExtAudioConverter.m in Sources */,
 				A80EDF132D718EF7003CD332 /* TSAIPhotoVC.swift in Sources */,
 				A80EDF132D718EF7003CD332 /* TSAIPhotoVC.swift in Sources */,
+				A83F87242D7954BB00D29B1B /* TSAIPhotoChildVM.swift in Sources */,
 				A868A8DE2D76F91500F6D884 /* AudioTool.swift in Sources */,
 				A868A8DE2D76F91500F6D884 /* AudioTool.swift in Sources */,
 				A80EDF242D71C0AA003CD332 /* TSColVVMSectionHeaderView.swift in Sources */,
 				A80EDF242D71C0AA003CD332 /* TSColVVMSectionHeaderView.swift in Sources */,
+				A868A90C2D78311A00F6D884 /* TSTextGeneralPicVM.swift in Sources */,
 				A80EDF1D2D71BE15003CD332 /* TSCollectionViewVM+Config.swift in Sources */,
 				A80EDF1D2D71BE15003CD332 /* TSCollectionViewVM+Config.swift in Sources */,
 				A868A8E12D76F9BB00F6D884 /* AudioConverter.m in Sources */,
 				A868A8E12D76F9BB00F6D884 /* AudioConverter.m in Sources */,
 				A868A8BA2D75C22300F6D884 /* TSThemeBrowseVM.swift in Sources */,
 				A868A8BA2D75C22300F6D884 /* TSThemeBrowseVM.swift in Sources */,
 				A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */,
 				A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */,
+				A868A91E2D785CEA00F6D884 /* TSGeneralPicVC+Event.swift in Sources */,
 				A80EDEE92D718CEA003CD332 /* TSFileManagerTool.swift in Sources */,
 				A80EDEE92D718CEA003CD332 /* TSFileManagerTool.swift in Sources */,
 				A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */,
 				A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */,
 				A868A8CE2D76AAC600F6D884 /* TSThemeSetRingToneView.swift in Sources */,
 				A868A8CE2D76AAC600F6D884 /* TSThemeSetRingToneView.swift in Sources */,
+				A868A90E2D7846D600F6D884 /* TSSavePhotoSuccessTool.swift in Sources */,
 				A868A8A32D7560B900F6D884 /* TSViewTool.swift in Sources */,
 				A868A8A32D7560B900F6D884 /* TSViewTool.swift in Sources */,
+				A83F871D2D79409B00D29B1B /* TSUserDefaultData.swift in Sources */,
+				A868A9112D784CFB00F6D884 /* TSGeneralPicVC.swift in Sources */,
 				A868A8A42D7560B900F6D884 /* TSCommonloadingView.swift in Sources */,
 				A868A8A42D7560B900F6D884 /* TSCommonloadingView.swift in Sources */,
 				A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */,
 				A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */,
 				A80EDF182D7193EE003CD332 /* TSTutorialsVC.swift in Sources */,
 				A80EDF182D7193EE003CD332 /* TSTutorialsVC.swift in Sources */,
@@ -763,13 +927,17 @@
 				A868A8B12D758CA400F6D884 /* TSTBBtnView.swift in Sources */,
 				A868A8B12D758CA400F6D884 /* TSTBBtnView.swift in Sources */,
 				A868A8D32D76DE7600F6D884 /* TSThemeSetVM.swift in Sources */,
 				A868A8D32D76DE7600F6D884 /* TSThemeSetVM.swift in Sources */,
 				A80EDF272D71C13D003CD332 /* TSColVVMHeaderModel.swift in Sources */,
 				A80EDF272D71C13D003CD332 /* TSColVVMHeaderModel.swift in Sources */,
+				A83F87222D7953C000D29B1B /* Notification+TSEx.swift in Sources */,
 				A868A8AD2D758B6B00F6D884 /* TSTBCallPreviewView.swift in Sources */,
 				A868A8AD2D758B6B00F6D884 /* TSTBCallPreviewView.swift in Sources */,
+				A868A9162D784E6500F6D884 /* TSBottomAlertVC.swift in Sources */,
 				A80EDF012D718DF1003CD332 /* TSBusinessWebVC.swift in Sources */,
 				A80EDF012D718DF1003CD332 /* TSBusinessWebVC.swift in Sources */,
 				A868A8A72D757DD600F6D884 /* UICollectionView+Refresh.swift in Sources */,
 				A868A8A72D757DD600F6D884 /* UICollectionView+Refresh.swift in Sources */,
+				A868A8F82D77E2BC00F6D884 /* TSTextGeneralPicVC.swift in Sources */,
 				A80EDF022D718DF1003CD332 /* TSSettingListView.swift in Sources */,
 				A80EDF022D718DF1003CD332 /* TSSettingListView.swift in Sources */,
 				A80EDF032D718DF1003CD332 /* ShareActivityItemProvider.swift in Sources */,
 				A80EDF032D718DF1003CD332 /* ShareActivityItemProvider.swift in Sources */,
 				A80EDF042D718DF1003CD332 /* TSSetingModel.swift in Sources */,
 				A80EDF042D718DF1003CD332 /* TSSetingModel.swift in Sources */,
 				A80EDF052D718DF1003CD332 /* TSSetingVC.swift in Sources */,
 				A80EDF052D718DF1003CD332 /* TSSetingVC.swift in Sources */,
+				A868A8FA2D77E35E00F6D884 /* TSPromptTextView.swift in Sources */,
 				A80EDF062D718DF1003CD332 /* SettingPurchaseTopView.swift in Sources */,
 				A80EDF062D718DF1003CD332 /* SettingPurchaseTopView.swift in Sources */,
 				A80EDF072D718DF1003CD332 /* TSSetingViewModel.swift in Sources */,
 				A80EDF072D718DF1003CD332 /* TSSetingViewModel.swift in Sources */,
 				A868A8C72D76A44500F6D884 /* TSThemeSetVC.swift in Sources */,
 				A868A8C72D76A44500F6D884 /* TSThemeSetVC.swift in Sources */,
@@ -816,7 +984,6 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"$(PROJECT_DIR)/AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				);
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;
@@ -858,7 +1025,6 @@
 				);
 				);
 				LIBRARY_SEARCH_PATHS = (
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
-					"$(PROJECT_DIR)/AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				);
 				MARKETING_VERSION = 1.0;
 				MARKETING_VERSION = 1.0;

+ 1 - 1
AIRingtone.xcodeproj/xcuserdata/100years.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -7,7 +7,7 @@
 		<key>AIRingtone.xcscheme_^#shared#^_</key>
 		<key>AIRingtone.xcscheme_^#shared#^_</key>
 		<dict>
 		<dict>
 			<key>orderHint</key>
 			<key>orderHint</key>
-			<integer>35</integer>
+			<integer>36</integer>
 		</dict>
 		</dict>
 	</dict>
 	</dict>
 </dict>
 </dict>

+ 6 - 0
AIRingtone/Assets.xcassets/AIPhoto/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "bottom_alert_bg@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "bottom_alert_bg@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/bottom_alert_bg@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/bottom_alert_bg.imageset/bottom_alert_bg@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "generation_failed@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "generation_failed@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/generation_failed@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/generation_failed.imageset/generation_failed@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "nav_title_aiAvatar@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "nav_title_aiAvatar@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@3x.png


+ 6 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_selected_border@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_selected_border@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/ptp_selected_border@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_selected_border.imageset/ptp_selected_border@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_0@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_0@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/ptp_style_0@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_0.imageset/ptp_style_0@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_1@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_1@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/ptp_style_1@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_1.imageset/ptp_style_1@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_2@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_2@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/ptp_style_2@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_2.imageset/ptp_style_2@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_3@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_3@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/ptp_style_3@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_3.imageset/ptp_style_3@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_4@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_4@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/ptp_style_4@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_4.imageset/ptp_style_4@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_5@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_5@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/ptp_style_5@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_5.imageset/ptp_style_5@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_6@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_6@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/ptp_style_6@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_6.imageset/ptp_style_6@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_7@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_7@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/ptp_style_7@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_7.imageset/ptp_style_7@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_8@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_8@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/ptp_style_8@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_8.imageset/ptp_style_8@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ptp_style_9@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ptp_style_9@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@3x.png


BIN
AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@2x.png


BIN
AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@3x.png


+ 6 - 0
AIRingtone/Assets.xcassets/Common/TextView/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "textView_bg@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "textView_bg@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@2x.png


BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "hint@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "hint@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/hint@2x.png


BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_hint.imageset/hint@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "textView_lb@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "textView_lb@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/textView_lb@2x.png


BIN
AIRingtone/Assets.xcassets/Common/TextView/textView_lb.imageset/textView_lb@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "refresh_gary@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "refresh_gary@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/refresh_gary@2x.png


BIN
AIRingtone/Assets.xcassets/Common/refresh_gary.imageset/refresh_gary@3x.png


+ 46 - 0
AIRingtone/Business/Data/TSUserDefaultData.swift

@@ -0,0 +1,46 @@
+//
+//  TSUserDefaultData.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+import ObjectMapper
+
+
+//海报历史记录
+class TSPosterHistory{
+    @UserDefault(key: "kPosterTextPicHistoryListString", defaultValue: "")
+    static private var historyString: String
+    static var listModelArray: [TSGeneralPicModel] = {
+        if let listModelArray = Mapper<TSGeneralPicModel>().mapArray(JSONString: historyString){
+            return listModelArray
+        }
+        return []
+    }()
+    
+    static func saveModel(model:TSGeneralPicModel){
+        listModelArray.insert(model, at: 0)
+        if let jsonString = listModelArray.toJSONString() {
+            historyString = jsonString
+        }
+    }
+}
+
+//头像历史记录
+class TSPhotoHistory{
+    @UserDefault(key: "kPhotoTextPicHistoryListString", defaultValue: "")
+    static private var historyString: String
+    static var listModelArray: [TSGeneralPicModel] = {
+        if let listModelArray = Mapper<TSGeneralPicModel>().mapArray(JSONString: historyString){
+            return listModelArray
+        }
+        return []
+    }()
+    
+    static func saveModel(model:TSGeneralPicModel){
+        listModelArray.insert(model, at: 0)
+        if let jsonString = listModelArray.toJSONString() {
+            historyString = jsonString
+        }
+    }
+}

+ 126 - 0
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift

@@ -0,0 +1,126 @@
+//
+//  TSAIPhotoChildVC.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+import JXSegmentedView
+import JXPagingView
+
+class TSAIPhotoChildVC: TSBaseVC {
+
+    //联动滚动回调
+    var listViewDidScrollCallback: ((UIScrollView) -> ())?
+    var style:TSGennerateType
+    
+    lazy var vm: TSAIPhotoChildVM = {
+        let vm = TSAIPhotoChildVM(style: style)
+        return vm
+    }()
+    
+    init(style: TSGennerateType) {
+        self.style = style
+        super.init()
+    }
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    
+    lazy var collectionComponent: TSCollectionViewComponent = {
+        let layout = UICollectionViewFlowLayout()
+        let cp = TSCollectionViewComponent(frame: CGRect.zero, layout: layout, attributes: [ :])
+        cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+        cp.itemDidSelectedHandler = { [weak self] (object, indexPath) in
+            guard let self = self else { return }
+            
+            if let sections = vm.colDataArray.safeObj(At: indexPath.section) as? TSColVVMSectionModel{
+                var dataModelArray:[TSGeneralPicModel] = []
+                for itemModel in sections.items {
+                    if let model = itemModel.dataModel as? TSGeneralPicModel {
+                        dataModelArray.append(model)
+                    }
+                }
+                
+                let browseVC = TSGeneralPicBrowseVC()
+                browseVC.dataModelArray = dataModelArray
+                browseVC.currentIndex = indexPath.item
+                browseVC.style = style
+                kPresentModalVC(target: self, modelVC: browseVC,transitionStyle: .crossDissolve)
+            }
+        }
+
+        return cp
+    }()
+    
+    override func createView() {
+        edgesForExtendedLayout = []
+        setNavBarViewHidden(true)
+        contentView.addSubview(collectionComponent.collectionView)
+        reloadView()
+    }
+    
+    func reloadView(){
+        collectionComponent.clear()
+        collectionComponent.reloadView(with:vm.colDataArray)
+    }
+
+    override func viewDidLayoutSubviews() {
+        super.viewDidLayoutSubviews()
+//        print("View did layout subviews")
+        self.collectionComponent.collectionView.frame = self.view.bounds
+        self.collectionComponent.collectionView.reloadData()
+    }
+    
+    
+    override func dealThings() {
+    
+        reloadView()
+        
+        NotificationCenter.default.addObserver(forName: .kReloadUIData, object: nil, queue: nil) { notification in
+            if let userInfo = notification.userInfo as? [String: TSGennerateType], let myEnum = userInfo["TSGennerateType"] {
+                if myEnum == self.style {
+                    self.vm.setRecentData()
+                    self.collectionComponent.reloadData()
+                }
+            }
+        }
+    }
+    
+}
+
+
+extension TSAIPhotoChildVC: JXPagingViewListViewDelegate {
+    
+    func listScrollView() -> UIScrollView {
+        collectionComponent.collectionView
+    }
+
+    func listViewDidScrollCallback(callback: @escaping (UIScrollView) -> ()) {
+        listViewDidScrollCallback = callback
+    }
+
+    func listView() -> UIView { view }
+    
+    func listWillAppear() {
+//        print("\(title ?? ""):\(#function)")
+        if collectionComponent.collectionView.visibleCells.count == 0 {
+            debugPrint("遇到空了")
+            reloadView()
+        }
+    }
+
+    func listDidAppear() {
+//        print("\(title ?? ""):\(#function)")
+    }
+
+    func listWillDisappear() {
+//        print("\(title ?? ""):\(#function)")
+    }
+
+    func listDidDisappear() {
+//        print("\(title ?? ""):\(#function)")
+    }
+}

+ 55 - 0
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVM.swift

@@ -0,0 +1,55 @@
+//
+//  TSAIPhotoChildVM.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+class TSAIPhotoChildVM {
+    
+    var style:TSGennerateType
+    init(style: TSGennerateType) {
+        self.style = style
+        setRecentData()
+        colDataArray.append(contentSecitonModel)
+    }
+    
+    var colDataArray:[TSComponent] = [TSComponent]()
+    
+    lazy var contentSecitonModel: TSColVVMSectionModel = {
+        let contentSeciton = TSColVVMSectionModel()
+        contentSeciton.style = colStyle
+        return contentSeciton
+    }()
+    
+    
+    func setRecentData() {
+        contentSecitonModel.items.removeAll()
+        var array = [TSColVVMItemModel]()
+        dataList.forEach { model in
+            let itemModel = TSColVVMItemModel()
+            itemModel.dataModel = model
+            itemModel.style = colStyle
+            array.append(itemModel)
+        }
+        contentSecitonModel.items = array
+    }
+    
+    var dataList:[TSGeneralPicModel]{
+        if style == .photo {
+            return TSPhotoHistory.listModelArray
+        }else{
+            return TSPosterHistory.listModelArray
+        }
+        
+    }
+    
+    var colStyle:TSColVVMStyple{
+        if style == .photo {
+            return .photoHistory
+        }else{
+            return .posterHistory
+        }
+    }
+    
+}

+ 43 - 0
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/View/TSAIPhotoImageCell.swift

@@ -0,0 +1,43 @@
+//
+//  TSAIPhotoImageCell.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+class TSAIPhotoImageCell: TSBaseCollectionCell {
+    
+    lazy var showImageView: UIImageView = {
+        let showImageView = UIImageView.createImageView(imageName:"",contentMode: .scaleAspectFill)
+        showImageView.backgroundColor = .gray
+        
+        return showImageView
+    }()
+    
+    override func creatUI() {
+        contentView.addSubview(showImageView)
+        showImageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.equalTo(0)
+            make.trailing.bottom.equalTo(0)
+        }
+        
+        if self.bounds.size.width == self.bounds.size.height {
+            showImageView.layer.cornerRadius = self.bounds.size.width/2
+        }else{
+            showImageView.layer.cornerRadius = 16
+        }
+        
+    }
+    
+    override func renderView(with object: Any?, component: TSCollectionViewComponent, attributes: [String : Any]?) {
+        super.renderView(with: object, component: component, attributes: attributes)
+        if let itemModel = object as? TSColVVMItemModel{
+            if let generalPicModel = itemModel.dataModel as? TSGeneralPicModel{
+                showImageView.setAsyncImage(urlString: generalPicModel.response.resultUrl,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
+            }
+        }
+    }
+    
+}
+

+ 153 - 2
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift

@@ -5,7 +5,158 @@
 //  Created by 100Years on 2025/2/27.
 //  Created by 100Years on 2025/2/27.
 //
 //
 
 
-class TSAIPhotoVC: TSBaseVC {     override func createView() {
-        view.backgroundColor = .blue
+
+import JXSegmentedView
+import JXPagingView
+class TSAIPhotoVC: TSBaseVC {
+    
+    lazy var navBarView: TSBaseNavContentBarView = {
+        let navBarView = TSBaseNavContentBarView()
+
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_aiAvatar",contentMode: .scaleToFill)
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+
+        return navBarView
+    }()
+    
+    var tableHeaderViewHeight: CGFloat{
+        get{
+            generalPicVC.viewH <= 10 ? 533.0 : generalPicVC.viewH
+        }
+    }
+    var headerInSectionHeight: Int = 44
+
+    let titles:[String] = ["Poster".localized,"Photo".localized]
+    let styles:[TSGennerateType] = [.poster,.photo]
+    
+    lazy var generalPicVC: TSTextGeneralPicVC = {
+        let generalPicVC = TSTextGeneralPicVC()
+        return generalPicVC
+    }()
+    
+    //头 view
+    lazy var headerView: UIView = {
+        let view = generalPicVC.view!
+        view.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(tableHeaderViewHeight))
+//        view.backgroundColor = .yellow
+        return view
+    }()
+    
+    lazy var pagingView: JXPagingView = {
+        //lazy var pagingView: JXPagingView = JXPagingListRefreshView(delegate: self) //整个刷新
+//        let pagingView = JXPagingListRefreshView(delegate: self) //list 刷新
+        let pagingView = JXPagingView(delegate: self)
+        pagingView.mainTableView.backgroundColor = .clear
+        pagingView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: k_ScreenHeight - k_Nav_Height  - k_Height_safeAreaInsetsBottom() - CGFloat(headerInSectionHeight) + 10)
+        pagingView.listContainerView.listCellBackgroundColor = .clear
+        //扣边返回处理,下面的代码要加上
+        pagingView.listContainerView.scrollView.panGestureRecognizer.require(toFail: self.navigationController!.interactivePopGestureRecognizer!)
+        pagingView.mainTableView.panGestureRecognizer.require(toFail: self.navigationController!.interactivePopGestureRecognizer!)
+        pagingView.pinSectionHeaderVerticalOffset = Int(TSTGPTitleView.viewH)
+        return pagingView
+    }()
+
+    
+    lazy var segmentedDataSource: JXSegmentedTitleDataSource = {
+        let dataSource = JXSegmentedTitleDataSource()
+        dataSource.isTitleColorGradientEnabled = true
+        dataSource.itemSpacing = 16
+        dataSource.itemWidthIncrement = 32
+        
+        dataSource.isItemSpacingAverageEnabled = false
+        dataSource.titles = titles
+        dataSource.titleNormalColor = .assist
+        dataSource.titleSelectedColor = .white
+        dataSource.titleNormalFont = .font(size: 14.0)
+        return dataSource
+    }()
+    
+    //配置指示器
+    lazy var indicator: JXSegmentedIndicatorBackgroundView = {
+        let indicator = JXSegmentedIndicatorBackgroundView()
+        indicator.isIndicatorConvertToItemFrameEnabled = true
+        indicator.indicatorHeight = 28
+        indicator.indicatorColor = .themeColor
+        return indicator
+    }()
+    
+
+    lazy var segmentedView: JXSegmentedView = {
+        let segmentedView = JXSegmentedView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(headerInSectionHeight)))
+        segmentedView.delegate = self
+        segmentedView.indicators = [indicator]
+        segmentedView.dataSource = segmentedDataSource
+        segmentedView.backgroundColor = .clear
+        segmentedView.contentEdgeInsetLeft = 26
+        segmentedView.listContainer = pagingView.listContainerView
+        return segmentedView
+    }()
+ 
+    override func createView() {
+        setViewBgImageNamed(named: kViewBJ)
+        edgesForExtendedLayout = []
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        contentView.addSubview(segmentedView)
+        contentView.addSubview(pagingView)
+        
+        kDelayMainShort {
+            self.headerView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat(self.tableHeaderViewHeight))
+            self.pagingView.reloadData()
+        }
+    }
+    
+    
+    @objc func clickBanner() {
+    }
+    
+    
+    override func dealThings() {
+
+    }
+    
+}
+
+
+
+extension TSAIPhotoVC: JXPagingViewDelegate {
+
+    func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int {
+        return Int(tableHeaderViewHeight)
+    }
+
+    func tableHeaderView(in pagingView: JXPagingView) -> UIView {
+        return headerView
+    }
+
+    func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int {
+        return headerInSectionHeight
+    }
+
+    func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView {
+        return segmentedView
+    }
+
+    func numberOfLists(in pagingView: JXPagingView) -> Int {
+        return titles.count
+    }
+
+    func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate {
+        return TSAIPhotoChildVC(style: styles.safeObj(At: index) ?? .poster)
     }
     }
 }
 }
+
+extension TSAIPhotoVC: JXSegmentedViewDelegate {
+    func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
+        self.navigationController?.interactivePopGestureRecognizer?.isEnabled = (index == 0)
+    }
+}
+
+//联动的关键代码
+extension JXPagingListContainerView: @retroactive JXSegmentedViewListContainer {}

+ 335 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicBrowseVC/TSGeneralPicBrowseVC.swift

@@ -0,0 +1,335 @@
+//
+//  TSGeneralPicBrowseVC.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+
+private let cellId = "TSGeneralPicBrowseCell"
+private let pageBtnTop:CGFloat = 176.0
+private let pageBtnH:CGFloat = 40
+
+class TSGeneralPicBrowseVC: TSBottomAlertVC {
+
+    
+    var style:TSGennerateType = .poster
+    
+    var dataModelArray = [TSGeneralPicModel]()
+    var currentImage:UIImage?{
+        let cell = collectionView.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? TSGeneralPicBrowseCell
+        var image = cell?.netWorkImageView.image
+        image = image?.pngImage
+        return image
+    }
+
+    var currentModel:TSGeneralPicModel?{
+        if let model = dataModelArray.safeObj(At: currentIndex){
+            return model
+        }
+        return nil
+    }
+    
+    
+    var currentIndex:Int = 0 {
+        didSet{
+            reloadUI()
+        }
+    }
+    
+    lazy var collectionView: UICollectionView = {
+
+        let layout = UICollectionViewFlowLayout()
+        layout.scrollDirection = .vertical
+        
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.backgroundColor = .clear
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        collectionView.register(TSGeneralPicBrowseCell.self, forCellWithReuseIdentifier: cellId)
+        collectionView.isPagingEnabled = true
+        collectionView.isHidden = true
+        if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
+            flowLayout.minimumInteritemSpacing = 0
+            flowLayout.minimumLineSpacing = 0
+            flowLayout.scrollDirection = .horizontal
+            flowLayout.itemSize = CGSize(width: k_ScreenWidth, height: 490*kDesignScale)
+        }
+        return collectionView
+    }()
+    
+    
+    lazy var leftPageBtn: UIButton = {
+        let leftBtn = UIButton.createButton(image: UIImage(named: "page_left")){ [weak self]  in
+            guard let self = self else { return }
+            self.collectionView.scrollToItem(at:  IndexPath(item: self.currentIndex-1, section: 0), at: .left, animated: true)
+        }
+        return leftBtn
+    }()
+    
+    lazy var rightPageBtn: UIButton = {
+        let rightBtn = UIButton.createButton(image: UIImage(named: "page_right")){ [weak self]  in
+            guard let self = self else { return }
+            self.collectionView.scrollToItem(at: IndexPath(item: self.currentIndex+1, section: 0), at: .left, animated: true)
+        }
+        return rightBtn
+    }()
+        
+    override func createView() {
+        super.createView()
+        
+        saveBtn.isHidden = true
+        againBtn.isHidden = true
+        
+        rightBtn.isHidden = false
+        rightBtn.setTitle("Save".localized, for: .normal)
+        
+        leftBtn.isHidden = false
+        leftBtn.setTitle("Copy Text".localized, for: .normal)
+        
+        bottomViewH = 540
+       
+        diyView.addSubview(collectionView)
+        collectionView.snp.makeConstraints { make in
+            make.leading.trailing.equalTo(0)
+            make.top.equalTo(0)
+            make.bottom.equalTo(0)
+        }
+        
+        diyView.addSubview(leftPageBtn)
+        leftPageBtn.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.top.equalTo(pageBtnTop)
+            make.width.height.equalTo(pageBtnH)
+        }
+        
+        diyView.addSubview(rightPageBtn)
+        rightPageBtn.snp.makeConstraints { make in
+            make.trailing.equalTo(-16)
+            make.top.equalTo(pageBtnTop)
+            make.width.height.equalTo(pageBtnH)
+        }
+        
+        kDelayMainShort {
+            self.collectionView.isHidden = false
+            self.collectionView.reloadData()
+            self.collectionView.setContentOffset(CGPoint(x: CGFloat(self.currentIndex) * self.collectionView.frame.size.width, y: 0), animated: false)
+
+            if let flowLayout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
+                flowLayout.itemSize = self.collectionView.bounds.size
+            }
+        }
+    }
+    
+    
+    override func clickLeftBtn() {
+//        if JudgeVip(){
+//            return
+//        }
+  
+        if let model = currentModel{
+            //拷贝文字到截切板
+            UIPasteboard.general.string = model.request.prompt
+            kSavePhotoSuccesswShared.show(atView: self.view,text: "Copy Successfully".localized,showViewBtn:false)
+        }else{
+            kShowToastDataMissing()
+        }
+    }
+    
+    override func clickRightBtn() {
+
+//        if JudgeVip(){
+//            return
+//        }
+        
+        if let image = currentImage{
+            PhotoManagerShared.saveImageToAlbum(image) { success, error in
+                if success {
+                    kSavePhotoSuccesswShared.show(atView: self.view)
+                }else{
+                    debugPrint(error)
+                }
+            }
+        }else{
+            kShowToastDataMissing()
+        }
+    }
+
+//    func JudgeVip() -> Bool {
+//        return kJudgeVip(externalBool: currentModel?.response.vip ?? false , vc: self, closePageBlock: nil)
+//    }
+}
+
+
+extension TSGeneralPicBrowseVC {
+    
+    func reloadUI() {
+        //判断前后是否还有,以此来确定左右翻页按钮
+        var isHiddenLeft = false
+        var isHiddenRight = false
+        if dataModelArray.count == 1{
+            isHiddenLeft = true
+            isHiddenRight = true
+        }else if currentIndex == 0 {
+            isHiddenLeft = true
+        }else if currentIndex+1 >= dataModelArray.count {
+            isHiddenRight = true
+        }
+        
+        leftPageBtn.isHidden = isHiddenLeft
+        rightPageBtn.isHidden = isHiddenRight
+    }
+    
+    
+    var cellImageSize:CGSize {
+        if style == .photo {
+            return CGSizeMake(140 , 140)
+        }
+        return CGSize(width: 140, height: 272)
+    }
+}
+
+//MARK: UICollectionViewDataSource
+extension TSGeneralPicBrowseVC:UICollectionViewDataSource,UICollectionViewDelegate {
+    
+    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+        resetIndexWithOffset(scrollView)
+    }
+
+    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
+        resetIndexWithOffset(scrollView)
+    }
+
+    private func resetIndexWithOffset(_ scrollView: UIScrollView) {
+        let item = Int((scrollView.contentOffset.x / scrollView.bounds.width).rounded())
+        currentIndex = item
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return dataModelArray.count
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! TSGeneralPicBrowseCell
+        if let model = dataModelArray.safeObj(At: indexPath.item){
+            cell.cellImageSize = cellImageSize
+            cell.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
+            cell.vipImageView.isHidden = !model.response.vip
+            cell.textLabel.isHidden =  model.request.promptSort.count < 0
+            cell.textLabel.text = model.request.promptSort
+        }
+        return cell
+    }
+    
+}
+
+
+class TSGeneralPicBrowseCell : TSBaseCollectionCell{
+
+    lazy var exampleView: UIView = {
+        let exampleView = UIView()
+        exampleView.backgroundColor = "#232323".uiColor.withAlphaComponent(0.3)
+        
+        let textLabel = UILabel.createLabel(
+            text: "Example".localized,
+            font: .font(size: 12),
+            textColor: .white
+        )
+        
+        exampleView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.edges.equalTo(UIEdgeInsets(top: 4, left: 6, bottom: 4, right: 6))
+        }
+        exampleView.isHidden = true
+        return exampleView
+    }()
+    
+    lazy var netWorkImageView : UIImageView = {
+        let netWorkImageView = UIImageView.createImageView(imageName: "",contentMode: .scaleAspectFit,corner: 12.0)
+        return netWorkImageView
+    }()
+
+    lazy var textLabel: UILabel = {
+        let textLabel = UILabel.createLabel(
+            font: .font(size: 12),
+            textColor: .white,
+            numberOfLines: 0
+        )
+        return textLabel
+    }()
+    
+
+    lazy var vipImageView: UIImageView = {
+        let vipImageView = UIImageView.createImageView(imageName:"vip_side_icon")
+        vipImageView.contentMode = .scaleToFill
+        vipImageView.isHidden = true
+        return vipImageView
+    }()
+
+    
+    var cellImageSize:CGSize = CGSizeMake(140, 272) {
+        didSet{
+            netWorkImageView.snp.updateConstraints { make in
+                make.top.equalTo(cellImageTop)
+                make.size.equalTo(cellImageSize)
+            }
+            var corner = 12.0
+            if cellImageSize.width == cellImageSize.height {
+                corner = cellImageSize.height/2.0
+            }
+            netWorkImageView.cornerRadius = corner
+        }
+    }
+    
+    var cellImageTop:CGFloat{
+        get {
+            return (pageBtnH/2.0+pageBtnTop) - (cellImageSize.height/2.0)
+        }
+    }
+    
+    override func creatUI() {
+        bgContentView.addSubview(netWorkImageView)
+        netWorkImageView.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.top.equalTo(cellImageTop)
+            make.size.equalTo(cellImageSize)
+        }
+        
+        let labelBgView = UIView()
+        labelBgView.backgroundColor = "#333333".uiColor
+        labelBgView.cornerRadius = 16.0
+        labelBgView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.leading.equalTo(12)
+            make.trailing.bottom.equalTo(-12)
+        }
+        
+        bgContentView.addSubview(labelBgView)
+        labelBgView.snp.makeConstraints { make in
+            make.top.equalTo(netWorkImageView.snp.bottom).offset(12)
+            make.centerX.equalToSuperview()
+            make.leading.greaterThanOrEqualTo(16)
+            make.trailing.lessThanOrEqualTo(-16)
+            make.bottom.lessThanOrEqualTo(0)
+        }
+        
+        netWorkImageView.addSubview(vipImageView)
+        vipImageView.snp.makeConstraints { make in
+            make.width.height.equalTo(40)
+            make.top.equalTo(-5)
+            make.trailing.equalTo(5)
+        }
+        
+        contentView.addSubview(exampleView)
+        exampleView.snp.makeConstraints { make in
+            make.top.equalTo(8)
+            make.leading.equalTo(8)
+        }
+        
+    }
+}

+ 78 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSGeneralPicModel.swift

@@ -0,0 +1,78 @@
+//
+//  TSGeneralPicModel.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+import ObjectMapper
+class TSGeneralPicModel: TSBaseModel {
+    
+    enum ModelType:Int {
+        case normal
+        case example
+    }
+    
+    enum ActionStatus:String ,Equatable {
+        case success = "success"//成功
+        case pending = "pending"//等待
+        case running = "running"//运行
+        case failed = "failed"//失败
+        
+        static func from(_ string: String) -> ActionStatus {
+            return ActionStatus(rawValue: string) ?? .failed
+        }
+    }
+    var modelType:ModelType = .normal
+    var id:Int = 0
+    var actionType:String = ""
+    var comments:String = ""
+    var request:TSGeneralPicRequestModel = TSGeneralPicRequestModel()
+    var response:TSGeneralPicResponseModel = TSGeneralPicResponseModel()
+    var createdTimestamp:Int = 0
+    var status:String = ""
+    var costTime:Int = 0
+    var percent:Float = 0.0
+    var actionStatus:ActionStatus = .failed
+    
+    
+    override func mapping(map: ObjectMapper.Map) {
+        modelType           <- map["modelType"]
+        id           <- map["id"]
+        actionType   <- map["actionType"]
+        comments     <- map["comments"]
+        request      <- (map["request"],JsonStringTransform<TSGeneralPicRequestModel>())
+        response           <- (map["response"],JsonStringTransform<TSGeneralPicResponseModel>())
+        createdTimestamp   <- map["createdTimestamp"]
+        status     <- map["status"]
+        costTime      <- map["costTime"]
+        percent     <- map["percent"]
+        actionStatus      <- map["actionStatus"]
+        actionStatus = ActionStatus.from(status)
+    }
+}
+
+class TSGeneralPicRequestModel : TSBaseModel {
+    var prompt:String = ""
+    var promptSort:String = ""
+    var width:Int = 0
+    var height:Int = 0
+    override func mapping(map: ObjectMapper.Map) {
+        prompt              <- map["prompt"]
+        promptSort          <- map["promptSort"]
+        width               <- map["width"]
+        height              <- map["height"]
+    }
+}
+
+class TSGeneralPicResponseModel : TSBaseModel {
+    var resultUrl:String = ""
+    var vip:Bool = false
+    override func mapping(map: ObjectMapper.Map) {
+        resultUrl           <- map["resultUrl"]
+        vip                  <- map["vip"]
+    }
+}
+
+
+

+ 95 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSProgressState.swift

@@ -0,0 +1,95 @@
+//
+//  TSProgressState.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+
+enum TSProgressState  {
+    case none
+    case start
+    case pending
+    case progress(CGFloat)
+    case progressString(String)
+    case success(Any?)
+    case failed(String)
+
+    static func fromKeyValue(key string: String,value:String) -> TSProgressState {
+        if string == "none" {
+            return .none
+        } else if string == "start" {
+            return .start
+        } else if string == "pending" {
+            return .pending
+        }else if string == "progress" {
+            var progress = 0.0
+            if let doubleValue = Float(value) {
+                progress = CGFloat(doubleValue)
+            }
+            return .progress(progress)
+        }else if string == "progressString" {
+            return .progressString(value)
+        }else if string == "success" {
+            return .success(value)
+        }else if string == "failed" {
+            return .failed(value)
+        }else{
+            return .none
+        }
+    }
+    
+    var keyValue:(String,String){
+        switch self {
+        case .none:
+            return ("none","")
+        case .start:
+            return ("start","")
+        case .pending:
+            return ("pending","")
+        case .progress(let float):
+            return ("progress",String(Float(float)))
+        case .progressString(let string):
+            return ("progressString",string)
+        case .success(let string):
+            if let string = string as? String{
+                return ("success",string)
+            }
+            return ("success","")
+        case .failed(let string):
+            return ("failed",string)
+        }
+    }
+    
+    
+    var isResult:Bool{
+        switch self {
+        case .none:
+            return false
+        case .start:
+            return false
+        case .pending:
+            return false
+        case .progress(_):
+            return false
+        case .progressString(_):
+            return false
+        case .success(_):
+            return true
+        case .failed(_):
+            return true
+        }
+    }
+    
+    
+    var reslutSuccess:Bool{
+        switch self {
+        case .success(_):
+            return true
+        case .failed(_):
+            return false
+        default:
+            return false
+        }
+    }
+}

+ 124 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC+Event.swift

@@ -0,0 +1,124 @@
+//
+//  Untitled.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+extension TSGeneralPicVC {
+    
+    var netWorkImageTop:CGFloat{
+        if gennerateType == .photo{
+            return 132
+        }
+        return 98
+    }
+
+    var netWorkImageSize:CGSize{
+        if gennerateType == .photo{
+            return CGSizeMake(200, 200)
+        }
+        return CGSizeMake(140, 272)
+    }
+
+    var resultIcon:UIImage?{
+        if gennerateType == .photo{
+            return UIImage(named: "theme_icon_photo")
+        }
+        return UIImage(named: "theme_icon_poster")
+    }
+    
+    func getSuccessImage()->UIImage?{
+        if let image = netWorkImageView.image {
+            return image.pngImage
+        }
+        return nil
+    }
+    
+}
+extension TSGeneralPicVC {
+    func upDateView(state:TSProgressState,model:TSGeneralPicModel?){
+        switch state {
+            case .failed(let errorStr):
+                showError(text: errorStr)
+            case .success:
+                if let model = model {
+                    showSuccess(model: model)
+                }else{
+                    showError(text: nil)
+                }
+            case .progressString(let string):
+                showProgress(text: string)
+            default:
+                showLoading()
+        }
+    }
+    
+    func showProgress(text:String) {
+        generateInView.isHidden = false
+        generateInView.showLoading(text: text)
+        generateInView.isRotating = true
+        
+        bottomView.isHidden = true
+        
+        isClickTheBlankClosePage = false
+    }
+    
+    func showLoading(){
+        generateInView.isHidden = false
+        generateInView.showLoading(text: "Generating...".localized)
+        generateInView.isRotating = true
+        
+        bottomView.isHidden = true
+        
+        isClickTheBlankClosePage = false
+    }
+    
+    func showError(text:String?){
+        let msg = "Failed to Generate, please try later".localized
+        generateInView.isHidden = true
+        generateInView.isRotating = false
+    
+        bottomView.isHidden = false
+   
+        againBtn.isHidden = false//重试
+        failView.isHidden = false
+        failLabel.text = msg
+        saveBtn.isHidden = true
+        successTopView.isHidden = true
+        
+        netWorkImageView.isHidden = true
+        regenerateBtn.isHidden = true
+        
+        isClickTheBlankClosePage = true
+    }
+    
+    func showSuccess(model:TSGeneralPicModel){
+        generateInView.isHidden = true
+        generateInView.isRotating = false
+        
+        bottomView.isHidden = false
+        
+        againBtn.isHidden = true//重试
+        failView.isHidden = true
+        saveBtn.isHidden = false
+        successTopView.isHidden = false
+
+        imageModel = model
+        isClickTheBlankClosePage = true
+        
+        netWorkImageView.isHidden = false
+        regenerateBtn.isHidden = false
+        self.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:kPlaceholderImage,contentMode: .scaleAspectFill){ [weak self] image in
+            guard let self = self else { return }
+        }
+        
+//        kPurchaseDefault.useOnceForFree(type: .generatePic)
+        
+        if let model = imageModel {
+            complete(model)
+        }
+    }
+}
+
+

+ 104 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift

@@ -0,0 +1,104 @@
+//
+//  TSGeneralPicVC.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+class TSGeneralPicVC: TSBottomAlertVC {
+    
+    
+
+    var imageModel:TSGeneralPicModel?
+    var complete:((TSGeneralPicModel)->Void)
+    
+    var aiText:String
+    var gennerateType:TSGennerateType
+    init(aiText: String,gennerateType:TSGennerateType,complete:@escaping ((TSGeneralPicModel)->Void)) {
+        self.aiText = aiText
+        self.gennerateType = gennerateType
+        self.complete = complete
+        super.init()
+    }
+    
+    lazy var viewModel: TSGenneralPicVM = {
+        let viewModel:TSGenneralPicVM = TSGenneralPicVM()
+        viewModel.aiText = aiText
+        viewModel.gennerateType = gennerateType
+        return viewModel
+    }()
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    
+    lazy var netWorkImageView : UIImageView = {
+        let netWorkImageView = UIImageView.createImageView(imageName: "",corner: 12.0)
+        return netWorkImageView
+    }()
+    
+    //############################## 生成动画 ##############################
+    lazy var generateInView : TSCommonloadingView = {
+        let generateInView = TSCommonloadingView()
+        generateInView.cancelBtn.addTarget(self, action: #selector(closePage), for: .touchUpInside)
+        return generateInView
+    }()
+
+    
+    override func createView() {
+        super.createView()
+        
+        view.addSubview(generateInView)
+        generateInView.snp.makeConstraints { make in
+            make.top.bottom.leading.trailing.equalTo(0)
+        }
+
+        diyView.addSubview(netWorkImageView)
+        netWorkImageView.snp.makeConstraints { make in
+            make.top.equalTo(netWorkImageTop)
+            make.centerX.equalToSuperview()
+            make.size.equalTo(netWorkImageSize)
+        }
+        
+        
+        diyView.addSubview(regenerateBtn)
+        regenerateBtn.snp.makeConstraints { make in
+            make.top.equalTo(netWorkImageView.snp.bottom).offset(16)
+            make.centerX.equalToSuperview()
+        }
+        
+        resultIconImageView.image = resultIcon
+        bottomViewH = 540.0
+    }
+    
+    @objc override func closePage() {
+        viewModel.cancelAllRequest()
+        self.dismiss(animated: true, completion: nil)
+    }
+    
+    override func clickAgainBtn() {
+        viewModel.creatImageEmoji(text:aiText)
+    }
+    
+    @objc override func clickSubmitBtn(){
+        if let image = getSuccessImage() {
+            PhotoManagerShared.saveImageToAlbum(image) { success, error in
+                if success {
+                    kSavePhotoSuccesswShared.show(atView:self.view)
+                }else{
+                    debugPrint(error)
+                }
+            }
+        }
+    }
+
+    override func dealThings() {
+        viewModel.creatImageEmoji(text: self.aiText)
+        viewModel.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
+            guard let self = self else { return }
+            self.upDateView(state: state, model: model)
+        }.store(in: &cancellable)
+    }
+}
+

+ 134 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift

@@ -0,0 +1,134 @@
+//
+//  TSGenneralPicVM.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+import Combine
+import Alamofire
+
+let kTextPicW = 800.0
+let kTextPicH = 1440.0
+//let kTextWHScale = kTextPicW/kTextPicH
+
+
+class TSGenneralPicVM {
+    
+    var creatRequest:Request?
+    var queryRequest:Request?
+    var stopNetwork = false
+   
+    @Published var stateDatauPblished:(TSProgressState,TSGeneralPicModel?) = (TSProgressState.none,nil)
+    var aiText:String = ""
+    var gennerateType:TSGennerateType = .poster
+    var generatingProgress = 0
+    
+    
+    
+//    func creatImageEmoji(text:String) {
+//
+//        stateDatauPblished = (.start,nil)
+//        stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
+//        
+////        kDelayOnMainThread(2.0) {
+////            self.stateDatauPblished = (.failed("error?.localizedDescription" ?? ""),nil)
+////        }
+//
+//        kDelayOnMainThread(2.0) {
+//            self.stateDatauPblished = (.success(nil),TSGeneralPicModel())
+//        }
+//        
+//    }
+    
+    //width 和 height 必须是 32 的倍数
+    func creatImageEmoji(text:String) {
+        generatingProgress = 0
+        aiText = text
+        let postDict:[String : Any] = [
+            "prompt":text,
+            "width":textPicW,
+            "height":textPicH
+        ]
+        stateDatauPblished = (.start,nil)
+        stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
+        creatRequest = TSNetworkShared.post(urlType: .textPicCreate,parameters: postDict) { [weak self] data,error in
+            guard let self = self else { return }
+            if let dataDict = data as? [String:Any] ,
+               dataDict.safeInt(forKey: "code") == 200,
+               let actionId = dataDict["actionId"] as? Int{
+                if stopNetwork == false {
+                    self.getActionInfo(action_id:actionId)
+                }
+            }else{
+                self.stateDatauPblished = (.failed(error?.localizedDescription ?? ""),nil)
+            }
+        }
+    }
+    
+    func getActionInfo(action_id:Int){
+        queryRequest = TSNetworkShared.get(urlType: .actionInfo,parameters: ["action_id":action_id]) { [weak self] data,error in
+            guard let self = self else { return }
+            if let result = kNetWorkResultSuccess(data: data) {
+                if let genmojiModel = TSGeneralPicModel(JSON: result) {
+                    switch genmojiModel.actionStatus {
+                    case .success:
+                        TSToastShared.hideLoading()
+                        self.stateDatauPblished = (.success(nil),genmojiModel)
+                        generatingProgress = 0
+                    case .failed:
+                        self.stateDatauPblished = (.failed(kNetWorkMessage(data: data) ?? ""),nil)
+                        generatingProgress = 0
+                    default:
+                        stateDatauPblished = (.progressString(generating(progress: genmojiModel.percent)),nil)
+                        if stopNetwork == false {
+                            kDelayOnMainThread(1.0) {
+                                self.getActionInfo(action_id: action_id)
+                            }
+                        }
+                    }
+                }
+            }else{
+                self.stateDatauPblished = (.failed(error?.localizedDescription ?? ""),nil)
+            }
+        }
+    }
+    
+    func cancelAllRequest(){
+        creatRequest?.cancel()
+        queryRequest?.cancel()
+        stopNetwork = true
+    }
+    
+    func generating(progress:Float) -> String {
+
+        //Generating 0%-100%
+        var progressInt = Int(progress*100)
+
+        if generatingProgress >= progressInt{
+            return "Generating \(generatingProgress)%"
+        }
+
+        if progressInt > 99 {
+            progressInt = 99
+        }
+        
+        generatingProgress = progressInt
+        return "Generating \(progressInt)%"
+    }
+}
+
+extension TSGenneralPicVM {
+    
+    var textPicW:Int{
+        return 800
+    }
+    
+    var textPicH:Int{
+        if gennerateType == .photo {
+            return 800
+        }
+        return 1440
+    }
+}
+

+ 22 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/Model/TSPTPStyleModel.swift

@@ -0,0 +1,22 @@
+//
+//  TSPTPStyleModel.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+import ObjectMapper
+
+class TSPTPStyleModel: TSBaseModel {
+    var image:UIImage?//给上传图片用的
+    var imageName:String = ""
+    var imageText:String = ""
+    var prompt:String = ""
+    var isVip:Bool = false
+    override func mapping(map: ObjectMapper.Map) {
+        imageName               <- map["imageName"]
+        imageText               <- map["imageText"]
+        prompt                  <- map["prompt"]
+        isVip                   <- map["isVip"]
+    }
+}

+ 62 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/Model/photo_to_photo_style.json

@@ -0,0 +1,62 @@
+[
+    {
+        "imageName": "ptp_style_0",
+        "imageText": "Retro Anime",
+        "prompt":"retro anime cel-shading, 1980s Toei Animation style, bold black outlines, limited color palette (--color 1980s_anime), visible film grain --edge_threshold 0.4 --cel_shading 0.8, Retain the original stone size of the photo",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_1",
+        "imageText": "Cyberpunk",
+        "prompt":"cyberpunk cityscape with neon billboards, retro anime aesthetic like AKIRA, chromatic aberration effect, hand-painted gradient skies --edge_perspective 1.5 --glitch_overlay 0.3",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_2",
+        "imageText": "Retrofuturism",
+        "prompt":"Googie architecture space station, 1950s atomic age aesthetic, curved aluminum panels, starburst patterns, glass dome observatory --edge_threshold 0.5 --atomic_age_style 0.8 --chrome_reflection 1.2",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_3",
+        "imageText": "Vaporwave",
+        "prompt":"Digital sunset over databay, Windows 95 error pop-ups floating on waves, geometric islands with Doric columns --edge_fracture 0.7 --cyberliminal_space 1.2",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_4",
+        "imageText": "Pop Art",
+        "prompt":"Campbell soup can duplication | pantone 185C + process blue | benday dot overlay | consumerism critique | color_saturation=1.8, halftone_density=0.6",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_5",
+        "imageText": "Abstract Expressionism",
+        "prompt":"monochromatic tension fields | ivory black + lead white modulation | washi paper grain | zen emptiness | contrast_ratio=9:1, stroke_minimalism=true",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_6",
+        "imageText": "Classical Painting",
+        "prompt":"Rembrandt chiaroscuro lighting | velvet drapery folds | vermilion + burnt umber | Counter-Reformation pathos | brushstroke_variance=0.85, canvas_texture=0.7",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_7",
+        "imageText": "Fantasy Illustration",
+        "prompt":"bioluminescent flora | crystal architecture | twilight nymphs | celtic knot patterns | foliage_density=8, prism_refraction=0.75",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_8",
+        "imageText": "Photorealism",
+        "prompt":"liquid metal smartphone | cashmere fabric folds | perfume droplet collision | studio_hdr=9 | micro_scratch=0.03mm",
+        "isVip": false
+    },
+    {
+        "imageName": "ptp_style_9",
+        "imageText": "Modern Digital Art",
+        "prompt":"anodized_aluminum | optical_glass | monochrome_gradient | edge_sharpness=9 | ambient_occlusion=0.7",
+        "isVip": false
+    }
+]

+ 169 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/TSTextGeneralPicVC.swift

@@ -0,0 +1,169 @@
+//
+//  TSTextGeneralPicVC.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+class TSTextGeneralPicVC: TSBaseVC {
+    
+    var viewH:CGFloat{
+        get {
+            cusStackView.viewH
+        }
+    }
+    
+    lazy var viewModel: TSTextGeneralPicVM = {
+        let viewModel:TSTextGeneralPicVM = TSTextGeneralPicVM()
+        viewModel.isCanGennerateBlock = { [weak self] enabled in
+            guard let self = self else { return }
+            creatBtn.isEnabled = enabled
+        }
+        return viewModel
+    }()
+    
+    //###################################### cusStackView ######################################
+    lazy var cusStackView: TSCustomStackView = {
+        let cusStackView = TSCustomStackView(axis: .vertical,spacing: 8)
+        return cusStackView
+    }()
+    
+    //###################################### 输入框 ######################################
+    lazy var promptTextView: TSPromptTextView = {
+        let promptTextView = TSPromptTextView()
+        promptTextView.textChangedBlock = { [weak self] text in
+            guard let self = self else { return }
+            viewModel.promptText = text
+        }
+        return promptTextView
+    }()
+    
+    //###################################### 图片类型 ######################################
+    lazy var photoStyleView: TSTGPPhotoStyleView = {
+        let photoStyleView = TSTGPPhotoStyleView()
+        photoStyleView.selectedValueBlock = { [weak self] index in
+            guard let self = self else { return }
+            viewModel.gennerateType = TSGennerateType(rawValue: index) ?? .poster
+        }
+        return photoStyleView
+    }()
+    
+    //###################################### Prompt类型 ######################################
+    lazy var promptStyleView: TSPromptStyleView = {
+        let promptStyleView = TSPromptStyleView()
+        promptStyleView.dataArray = viewModel.ptpStyleModels
+        promptStyleView.selectedValueBlock = { [weak self] model in
+            guard let self = self else { return }
+            viewModel.selectPromptModel = model
+        }
+        return promptStyleView
+    }()
+    
+    
+    //###################################### Button ######################################
+    lazy var creatBtn:UIButton  = {
+        let creatBtn = kCreateNormalSubmitBtn(title: "Create Now") {[weak self] in
+            guard let self = self else { return }
+            generateImage()
+        }
+        creatBtn.isEnabled = false
+        return creatBtn
+    }()
+    
+    //###################################### Generate History ######################################
+    lazy var historyTitleView: TSTGPTitleView = {
+        let historyTitleView = TSTGPTitleView()
+        historyTitleView.titleLab.text = "Generate History".localized
+        return historyTitleView
+    }()
+    
+    lazy var creatBtnView:UIView  = {
+        let creatBtnView = UIView()
+        creatBtnView.addSubview(creatBtn)
+        creatBtn.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+            make.width.equalTo(creatBtn.width)
+            make.height.equalTo(creatBtn.height)
+        }
+        return creatBtnView
+    }()
+
+    override func createView() {
+        view.backgroundColor = .clear
+        setNavBarViewHidden(true)
+        
+        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickView))
+        tapGesture.cancelsTouchesInView = false
+        view.addGestureRecognizer(tapGesture)
+        
+        contentView.addSubview(cusStackView)
+        cusStackView.snp.makeConstraints { make in
+            make.top.leading.bottom.trailing.equalTo(0)
+        }
+
+        cusStackView.addSubviewToStack(promptTextView)
+        
+        cusStackView.addSubviewToStack(photoStyleView)
+        photoStyleView.snp.makeConstraints { make in
+            make.height.equalTo(photoStyleView.viewH)
+        }
+        
+        cusStackView.addSubviewToStack(promptStyleView)
+
+        cusStackView.addSubviewToStack(creatBtnView)
+        creatBtnView.snp.makeConstraints { make in
+            make.height.equalTo(64)
+        }
+        
+        cusStackView.addSubviewToStack(historyTitleView)
+        historyTitleView.snp.makeConstraints { make in
+            make.height.equalTo(photoStyleView.viewH)
+        }
+        
+    }
+    
+    override func dealThings() {
+        
+        promptTextView.customTextView.text = "1234567"
+        viewModel.promptText = "1234567"
+//        NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
+    }
+    
+//    @objc func vipInfoChanged() {
+//        kExecuteOnMainThread {
+//            self.vipBtn.isHidden = PurchaseManager.default.isVip
+//            self.collectionComponent.reloadData()
+//        }
+//    }
+    
+    @objc func clickView() {
+        view.endEditing(true)
+    }
+
+    
+    @objc func clickCollectionView() {
+        view.endEditing(true)
+    }
+}
+
+extension TSTextGeneralPicVC {
+    func generateImage() {
+        
+//        //判断 vip
+//        if kJudgeVip(externalBool: kPurchaseDefault.freeNumAvailable(type: .textGeneratePic) == false, vc: self) {[weak self] in
+//            guard let self = self else { return }
+//        }{ return }
+        
+        let gennerateVC = TSGeneralPicVC(aiText: viewModel.prompt, gennerateType: viewModel.gennerateType)
+        {[weak self] model in
+            guard let self = self else { return }
+            model.request.promptSort = viewModel.promptText
+            viewModel.saveModel(model:model)
+        
+            NotificationCenter.default.post(name: .kReloadUIData, object: nil, userInfo: ["TSGennerateType": viewModel.gennerateType])
+        }
+        
+        kPresentModalVC(target: self, modelVC: gennerateVC,transitionStyle: .crossDissolve)
+    }
+
+}

+ 87 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/VM/TSTextGeneralPicVM.swift

@@ -0,0 +1,87 @@
+//
+//  TSTextGeneralPicVM.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+import Alamofire
+import ObjectMapper
+
+
+enum TSGennerateType:Int,Equatable{
+    case poster = 0     //海报
+    case photo  = 1     //头像
+}
+
+
+class TSTextGeneralPicVM {
+    
+    //选择 prompt 类型组
+    lazy var ptpStyleModels: [TSPTPStyleModel] = {
+        var ptpStyleModels = [TSPTPStyleModel]()
+        if let dataArray = Mapper<TSPTPStyleModel>().mapArray(JSONfile: "photo_to_photo_style.json"){
+            ptpStyleModels = dataArray
+            
+            if let model = dataArray.first {
+                selectPromptModel = model //加上默认的选择
+            }
+        }
+        
+        return ptpStyleModels
+    }()
+    
+    //输入框内容
+    var promptText:String = "" {
+        didSet{
+            isCanGennerateBlock?(isCanGennerate)
+        }
+    }
+    
+    //选择的生成图片的 type
+    var gennerateType:TSGennerateType = .poster{
+        didSet{
+            isCanGennerateBlock?(isCanGennerate)
+        }
+    }
+
+    //选择的 prompt 类型
+    var selectPromptModel:TSPTPStyleModel?{
+        didSet{
+            isCanGennerateBlock?(isCanGennerate)
+        }
+    }
+    
+    //可生成状态变化 block
+    var isCanGennerateBlock:((Bool)->Void)?
+}
+
+
+extension TSTextGeneralPicVM {
+    //是否满足生成条件
+    var isCanGennerate:Bool {
+        if  selectPromptModel != nil ,
+            promptText.replacingOccurrences(of: " ", with: "").count > 0
+        {
+            return true
+        }
+        return false
+    }
+
+
+    var prompt:String{
+        var prompt = promptText
+        if let selectPromptModel = selectPromptModel {
+            prompt+=", \(selectPromptModel.prompt)"
+        }
+        return prompt
+    }
+
+    func saveModel(model:TSGeneralPicModel){
+        if gennerateType == .poster {
+            TSPosterHistory.saveModel(model: model)
+        }else if gennerateType == .photo{
+            TSPhotoHistory.saveModel(model: model)
+        }
+    }
+}

+ 168 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptStyleView.swift

@@ -0,0 +1,168 @@
+//
+//  TSTGPStyleView.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+class TSPromptStyleView:TSBaseView {
+    
+    var selectedValueBlock:((TSPTPStyleModel)->Void)?
+    
+    var dataArray: [TSPTPStyleModel] = [TSPTPStyleModel](){
+        didSet{
+            styleCollectionView.reloadData()
+            if dataArray.count > 0 {
+                kDelayMainShort{
+                    self.styleCollectionView.selectItem(at: self.currentIndexPath, animated: true, scrollPosition: .centeredHorizontally)
+                }
+            }
+        }
+    }
+    
+    lazy var layout: UICollectionViewFlowLayout = {
+        let layout = UICollectionViewFlowLayout()
+        layout.scrollDirection = .horizontal
+        layout.itemSize = CGSize(width: 110, height: 110)
+        layout.minimumInteritemSpacing = 0.0
+        layout.minimumLineSpacing = 12.0
+        layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
+        return layout
+    }()
+    
+    
+    lazy var styleCollectionView: UICollectionView = {
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.backgroundColor = .clear
+        collectionView.register(TSPTPSelectStyleCCell.self, forCellWithReuseIdentifier: TSPTPSelectStyleCCell.cellID)
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        return collectionView
+    }()
+
+    var currentIndexPath:IndexPath = IndexPath(item: 0, section: 0)
+    
+    
+    lazy var titleView: TSTGPTitleView = {
+        let titleView = TSTGPTitleView()
+        titleView.titleLab.text = "Genre".localized
+        return titleView
+    }()
+    
+    
+    override func creatUI() {
+        
+        let titleViewH = titleView.viewH
+        
+        addSubview(titleView)
+        titleView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.trailing.equalTo(0)
+            make.height.equalTo(titleViewH)
+        }
+        
+        contentView.snp.updateConstraints { make in
+            make.top.equalTo(titleViewH)
+        }
+        
+        currentIndexPath = IndexPath(item: 0, section: 0)
+        contentView.addSubview(styleCollectionView)
+        styleCollectionView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+            make.height.equalTo(110)
+        }
+    }
+    
+    func unCheck(){
+        styleCollectionView.deselectItem(at: currentIndexPath, animated: true)
+    }
+    
+}
+
+extension TSPromptStyleView: UICollectionViewDataSource ,UICollectionViewDelegate {
+    
+    public func numberOfSections(in collectionView: UICollectionView) -> Int {
+        return 1
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return dataArray.count
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TSPTPSelectStyleCCell.cellID, for: indexPath)
+        if let cell = cell as? TSPTPSelectStyleCCell,let itemModel = dataArray.safeObj(At: indexPath.item){
+            cell.itemModel = itemModel
+        }
+        return cell
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        if let model = dataArray.safeObj(At: indexPath.item){
+            currentIndexPath = indexPath
+            selectedValueBlock?(model)
+        }
+    }
+}
+
+class TSPTPSelectStyleCCell: TSBaseCollectionCell {
+    
+    static let cellID = "TSPTPSelectStyleCCell"
+
+    override var isSelected: Bool{
+        didSet{
+            boardImageView.isHidden = isSelected ? false : true
+        }
+    }
+    
+    var itemModel:TSPTPStyleModel = TSPTPStyleModel(){
+        didSet{
+            imageView.image = UIImage(named: itemModel.imageName)
+            textLabel.text = itemModel.imageText
+        }
+    }
+    
+    lazy var imageView: UIImageView = {
+        let imageView = UIImageView()
+        return imageView
+    }()
+    
+    lazy var boardImageView: UIImageView = {
+        let boardImageView = UIImageView.createImageView(imageName: "ptp_selected_border")
+        boardImageView.isHidden = true
+        return boardImageView
+    }()
+
+    lazy var textLabel: UILabel = {
+        let textLabel = UILabel.createLabel(font: .font(size: 14),textColor: .white,textAlignment: .center,numberOfLines: 0)
+        return textLabel
+    }()
+    
+    override func creatUI() {
+        
+        bgContentView.addSubview(imageView)
+        imageView.snp.makeConstraints { make in
+            make.top.bottom.leading.trailing.equalTo(0)
+        }
+        
+        bgContentView.addSubview(boardImageView)
+        boardImageView.snp.makeConstraints { make in
+            make.top.bottom.leading.trailing.equalTo(0)
+        }
+ 
+        bgContentView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.leading.trailing.equalTo(0)
+            make.bottom.equalTo(-4)
+            make.height.equalTo(37)
+        }
+    }
+    
+}
+

+ 228 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift

@@ -0,0 +1,228 @@
+//
+//  TSTGPTextView.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+
+let kRandomTextArray:[String] = [
+    "Ultra-detailed northern lights over a glacial lake, mirrored reflections with vibrant turquoise and magenta hues, surreal celestial atmosphere, digital painting style with soft glow effects.",
+    "Neon-lit cyberpunk night market in a rainy Asian metropolis, holographic food stalls and floating drones, teal-orange color grading, retro-futuristic architecture with glowing Kanji signs",
+    "Macro photography of rainbow candy landscape with gummy bear mountains, chocolate river and lollipop trees, hyper-realistic textures under golden hour lighting",
+    "Traditional Chinese ink painting style phoenix soaring through misty mountain peaks, dynamic black brushstrokes with crimson accents on rice paper texture",
+    "Bioluminescent underwater metropolis with glass dome structures, schools of glowing fish weaving through coral skyscrapers, deep-sea blue palette with neon coral highlights",
+    "1950s retro sci-fi movie poster style wallpaper featuring a rocket orbiting Saturn, vintage orange-teal color scheme with halftone textures and hand-drawn typography",
+    "Minimalist wallpaper with overlapping translucent 3D geometric shapes in gradient pastel colors, clean negative space, soft shadows and metallic accents, 4K abstract design.",
+    "Steampunk floating library with brass gears and clockwork mechanisms, leather-bound books flying through amber-lit fog, Victorian-era architecture blended with retro-futurism",
+    "Zen rock garden transformed into cosmic landscape, black sand waves surrounding cratered moon-like stones, starry galaxy reflected in miniature, monochromatic with silver foil accents",
+    "Futuristic AI core visualization with flowing golden data streams through transparent quantum circuits, dark background with floating holographic equations, cybernetic glow effect"
+]
+
+
+class TSPromptTextView : TSBaseView{
+    
+
+    var textChangedBlock:((String)->Void)?
+    
+    lazy var titleView: TSTGPTitleView = {
+        let titleView = TSTGPTitleView()
+        titleView.titleLab.text = "Enter A Prompt".localized
+        return titleView
+    }()
+  
+    lazy var randomTextPicker: TSRandomTextPicker = {
+        let textPicker = TSRandomTextPicker(texts: kRandomTextArray)
+        return textPicker
+    }()
+    
+    lazy var textBgView: UIView = {
+        let textBgView = UIView()
+
+        let bgImageView = UIImageView.createImageView(imageName: "textView_bg",contentMode: .scaleToFill)
+        let lbImageView = UIImageView.createImageView(imageName: "textView_lb",contentMode: .scaleToFill)
+        
+        textBgView.addSubview(bgImageView)
+        textBgView.addSubview(lbImageView)
+        
+        bgImageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(343*kDesignScale)
+            make.height.equalTo(160*kDesignScale)
+        }
+        
+        lbImageView.snp.makeConstraints { make in
+            make.bottom.equalTo(0)
+            make.leading.equalTo(0)
+            make.width.equalTo(206*kDesignScale)
+            make.height.equalTo(32*kDesignScale)
+        }
+        
+        return textBgView
+    }()
+    
+    lazy var customTextView: TSPlaceholderTextView = {
+        let customTextView = TSPlaceholderTextView(
+            placeholder: "Type your idea here.",
+            text: "",
+            font: .font(size: 16),
+            textColor: .white,
+            backgroundColor: .clear
+        )
+        customTextView.delegate = self
+        return customTextView
+    }()
+    
+ 
+    lazy var inspirationBtn: UIButton = {
+        let inspirationBtn = UIButton.createButton(
+            title: "Hint Inspiration".localized,
+            image: UIImage(named: "textView_hint"),
+            font: .font(size: 14),
+            titleColor: .themeColor
+        )
+        { [weak self]  in
+            guard let self = self else { return }
+            customTextView.text = randomTextPicker.getRandomText()
+            textViewDidChange(customTextView)
+        }
+        inspirationBtn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 24, bottom: 4, right: 50)
+        inspirationBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 0)
+        return inspirationBtn
+    }()
+    
+    
+    lazy var clearBtn: TSUIExpandedTouchButton = {
+        let clearBtn = TSUIExpandedTouchButton()
+        clearBtn.setUpButton(image: UIImage(named: "clear_text"))
+//        let clearBtn = UIButton.createButton(
+//            image: UIImage(named: "clear_text")
+//        )
+        { [weak self]  in
+            guard let self = self else { return }
+            customTextView.text = ""
+            textViewDidChange(customTextView)
+        }
+        return clearBtn
+    }()
+    
+    let maxNum:Int = 1000
+    var currenMun:Int = 0 {
+        didSet{
+            currenMunLab.text = "\(currenMun)"
+        }
+    }
+    lazy var currenMunLab: UILabel = {
+        let numLab = UILabel.createLabel(text: "\(currenMun)",font: .font(name: .PingFangSC,size: 12),textColor: .white)
+        return numLab
+    }()
+    
+    lazy var numView: UIView = {
+        let numView = UIView()
+        
+        numView.addSubview(currenMunLab)
+        
+        let numLab = UILabel.createLabel(text: "/\(maxNum))",font: .font(name: .PingFangSC,size: 12),textColor: .white.withAlphaComponent(0.4))
+        numView.addSubview(numLab)
+        
+        let lineView = UIView()
+        lineView.cornerRadius = 0.5
+        lineView.backgroundColor = .white
+        numView.addSubview(lineView)
+        
+        currenMunLab.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.leading.equalTo(0)
+        }
+        
+        numLab.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.leading.equalTo(currenMunLab.snp.trailing)
+        }
+        
+        lineView.snp.makeConstraints { make in
+            make.top.trailing.bottom.equalToSuperview()
+            make.leading.equalTo(numLab.snp.trailing).offset(8)
+            make.width.equalTo(1)
+            make.height.equalTo(12)
+        }
+        
+        return numView
+    }()
+    
+    override func creatUI() {
+        let titleViewH = titleView.viewH
+        
+        addSubview(titleView)
+        titleView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.trailing.equalTo(0)
+            make.height.equalTo(titleViewH)
+        }
+        
+        contentView.snp.updateConstraints { make in
+            make.top.equalTo(titleViewH)
+        }
+    
+        contentView.addSubview(textBgView)
+        textBgView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.height.equalTo(160.0*kDesignScale)
+            make.bottom.equalTo(0)
+        }
+   
+        textBgView.addSubview(customTextView)
+        customTextView.snp.makeConstraints { make in
+            make.top.equalTo(16)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.bottom.equalTo(-48)
+        }
+        
+        textBgView.addSubview(inspirationBtn)
+
+        inspirationBtn.snp.makeConstraints { make in
+            make.height.equalTo(32)
+            make.bottom.equalTo(0)
+            make.leading.equalTo(0)
+        }
+        
+        textBgView.addSubview(clearBtn)
+        clearBtn.snp.makeConstraints { make in
+            make.width.height.equalTo(14)
+            make.bottom.equalTo(-14)
+            make.trailing.equalTo(-14)
+        }
+        
+        textBgView.addSubview(numView)
+        numView.snp.makeConstraints { make in
+            make.centerY.equalTo(clearBtn)
+            make.trailing.equalTo(clearBtn.snp.leading).offset(-8)
+        }
+    
+    }
+
+//    func getVipText()->String{
+//        if kPurchaseDefault.isVip {
+//            return "Generate"
+//        }
+//        return "Generate (\(kPurchaseDefault.freeNum(type: .generatePic)))"
+//    }
+    
+}
+
+extension TSPromptTextView: UITextViewDelegate{
+    
+    func textViewDidBeginEditing(_ textView: UITextView) {
+//        self.colComponent?.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredVertically, animated: true)
+    }
+    
+    func textViewDidChange(_ textView: UITextView) {
+        currenMun = textView.text.count
+        textChangedBlock?(textView.text)
+    }
+    
+}

+ 28 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSTGPTitleView.swift

@@ -0,0 +1,28 @@
+//
+//  TSTGPTitleView.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+class TSTGPTitleView: TSBaseView {
+    
+    static let viewH:Float = 40.0
+    let viewH:Float = TSTGPTitleView.viewH
+    
+    lazy var titleLab: UILabel = {
+        let titleLab = UILabel.createLabel(font: .font(name: .PoppinsBlackItalic,size: 18),textColor: .white)
+        return titleLab
+    }()
+    
+    override func creatUI() {
+        
+        contentView.addSubview(titleLab)
+        titleLab.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.centerY.equalToSuperview()
+        }
+        
+        
+    }
+}

+ 52 - 0
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TsTGPPhotoStyleView.swift

@@ -0,0 +1,52 @@
+//
+//  TsTGPPhotoStyleView.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+
+import BetterSegmentedControl
+
+class TSTGPPhotoStyleView: TSTGPTitleView {
+    
+    var selectedValueBlock:((Int)->Void)?
+    
+    let titles = ["Poster".localized,"Photo".localized]
+    lazy var segmentedView: BetterSegmentedControl = {
+        let segmentedView = BetterSegmentedControl(
+            frame: .zero,
+            segments:
+                LabelSegment.segments(
+                    withTitles: titles,
+                    normalFont: .font(size: 14.0),
+                    normalTextColor: .textDisable,
+                    selectedFont: .font(size: 14.0),
+                    selectedTextColor: .white),
+            options:[.backgroundColor(.cardColor),
+                     .indicatorViewBackgroundColor(.themeColor),
+                     .indicatorViewInset(0),
+                     .cornerRadius(8.0),
+                     .animationSpringDamping(1.0)]
+        )
+        segmentedView.addTarget(self,action: #selector(segmentedControlValueChanged(_:)),for: .valueChanged)
+        return segmentedView
+    }()
+    
+    override func creatUI() {
+        super.creatUI()
+        titleLab.text = "Select type".localized
+        
+        contentView.addSubview(segmentedView)
+        segmentedView.snp.makeConstraints { make in
+            make.width.equalTo(144)
+            make.height.equalTo(32)
+            make.trailing.equalTo(-16)
+            make.centerY.equalToSuperview()
+        }
+    }
+    
+    // MARK: - Action handlers
+    @objc func segmentedControlValueChanged(_ sender: BetterSegmentedControl) {
+        selectedValueBlock?(sender.index)
+    }
+}

+ 27 - 0
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC.swift

@@ -20,6 +20,12 @@ class TSAIRintoneVC: TSBaseVC {
     }()
     }()
     
     
     
     
+    
+    lazy var promptTextView: TSPromptTextView = {
+        let promptTextView = TSPromptTextView()
+        return promptTextView
+    }()
+    
     override func createView() {
     override func createView() {
         
         
         setViewBgImageNamed(named: kViewBJ)
         setViewBgImageNamed(named: kViewBJ)
@@ -29,5 +35,26 @@ class TSAIRintoneVC: TSBaseVC {
         navBarView.snp.makeConstraints { make in
         navBarView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
             make.edges.equalToSuperview()
         }
         }
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        contentView.addSubview(promptTextView)
+        promptTextView.snp.makeConstraints { make in
+            make.leading.top.trailing.equalTo(0)
+//            make.bottom.equalTo(0)
+        }
+        
+        
+        
+        
+        
     }
     }
 }
 }

+ 87 - 0
AIRingtone/Business/TSCollectionViewVM/TSCollectionViewVM+Config.swift

@@ -114,3 +114,90 @@ let themeContentConfig:TSColVVMSizeConfig = {
     
     
     return config
     return config
 }()
 }()
+
+
+//MARK: 海报内容
+let posterHistoryConfig:TSColVVMSizeConfig = {
+
+    let sectionInset = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
+    let lineSpacing = 8.0
+    let itemSpacing = 8.0
+    
+    let originalSize = CGSizeMake(109.0, 194.0)
+    
+    let cellRowNum = 3
+    
+    let originalScale = originalSize.width/originalSize.height
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    w = w - lineSpacing * CGFloat((cellRowNum-1))
+    w = w/CGFloat(cellRowNum)
+    let h = w/originalScale
+    
+    let cellSize = CGSizeMake(w, h)
+    let cellClass = TSAIPhotoImageCell.self
+    
+    let headerViewSize = CGSizeMake(k_ScreenWidth, 0)
+    let headerView = TSColVVMSectionHeaderView.self
+
+    let footerViewSize = CGSizeMake(k_ScreenWidth, 0)
+    let footerView = UICollectionReusableView.self
+    
+    var config = TSColVVMSizeConfig(
+        sectionInset: sectionInset,
+        lineSpacing: lineSpacing,
+        itemSpacing: itemSpacing,
+        originalSize: originalSize,
+        cellRowNum: cellRowNum,
+        cellSize: cellSize,
+        cellClass: cellClass,
+        headerViewSize: headerViewSize,
+        headerView: headerView,
+        footerViewSize: footerViewSize,
+        footerView: footerView
+    )
+    
+    return config
+}()
+
+//MARK: 头像内容
+let photoHistoryConfig:TSColVVMSizeConfig = {
+
+    let sectionInset = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16)
+    let lineSpacing = 8.0
+    let itemSpacing = 8.0
+    
+    let originalSize = CGSizeMake(109.0, 109.0)
+    
+    let cellRowNum = 3
+    
+    let originalScale = originalSize.width/originalSize.height
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    w = w - lineSpacing * CGFloat((cellRowNum-1))
+    w = w/CGFloat(cellRowNum)
+    let h = w/originalScale
+    
+    let cellSize = CGSizeMake(w, h)
+    let cellClass = TSAIPhotoImageCell.self
+    
+    let headerViewSize = CGSizeMake(k_ScreenWidth, 0)
+    let headerView = TSColVVMSectionHeaderView.self
+
+    let footerViewSize = CGSizeMake(k_ScreenWidth, 0)
+    let footerView = UICollectionReusableView.self
+    
+    var config = TSColVVMSizeConfig(
+        sectionInset: sectionInset,
+        lineSpacing: lineSpacing,
+        itemSpacing: itemSpacing,
+        originalSize: originalSize,
+        cellRowNum: cellRowNum,
+        cellSize: cellSize,
+        cellClass: cellClass,
+        headerViewSize: headerViewSize,
+        headerView: headerView,
+        footerViewSize: footerViewSize,
+        footerView: footerView
+    )
+    
+    return config
+}()

+ 7 - 0
AIRingtone/Business/TSCollectionViewVM/TSCollectionViewVM.swift

@@ -12,6 +12,9 @@ import ObjectMapper
 enum TSColVVMStyple : Int {
 enum TSColVVMStyple : Int {
     case themeGuide     //主题引导
     case themeGuide     //主题引导
     case themeContent   //主题内容
     case themeContent   //主题内容
+    
+    case posterHistory   //生成海报的历史记录
+    case photoHistory    //生成头像的历史记录
 
 
     var config:TSColVVMSizeConfig {
     var config:TSColVVMSizeConfig {
         switch self {
         switch self {
@@ -19,6 +22,10 @@ enum TSColVVMStyple : Int {
             return themeGuideConfig
             return themeGuideConfig
         case .themeContent:
         case .themeContent:
             return themeContentConfig
             return themeContentConfig
+        case .posterHistory:
+            return posterHistoryConfig
+        case .photoHistory:
+            return photoHistoryConfig
         }
         }
     }
     }
     
     

+ 2 - 1
AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetVC.swift

@@ -86,7 +86,8 @@ class TSThemeSetVC: TSBaseVC {
     }
     }
     
     
     override func dealThings() {
     override func dealThings() {
-        ringView.cellView.nameLab.text = model.name
+        ringView.cellView.nameLab.text = model.ringtoneName
+        ringView.cellView.coverImageView.setAsyncImage(urlString: model.ringtoneCover,contentMode: .scaleAspectFill)
         ringView.cellView.timeLab.text = vm.floatToMinuteSecond(duration)
         ringView.cellView.timeLab.text = vm.floatToMinuteSecond(duration)
         posterView.netWorkImageView.setAsyncImage(urlString: model.poster,contentMode: .scaleAspectFill)
         posterView.netWorkImageView.setAsyncImage(urlString: model.poster,contentMode: .scaleAspectFill)
         photoView.netWorkImageView.setAsyncImage(urlString: model.photo,contentMode: .scaleAspectFill)
         photoView.netWorkImageView.setAsyncImage(urlString: model.photo,contentMode: .scaleAspectFill)

+ 5 - 0
AIRingtone/Business/TSThemeVC/TSThemeVC/Model/TSThemeModel.swift

@@ -14,6 +14,9 @@ class TSThemeModel: TSBaseModel {
     var poster:String = ""//海报
     var poster:String = ""//海报
     var themeId:String = ""
     var themeId:String = ""
     var ringtone:String = ""//铃声
     var ringtone:String = ""//铃声
+    var ringtoneName:String = ""//铃声名次
+    var ringtoneCover:String = ""//铃声封面
+    
     
     
     override func mapping(map: ObjectMapper.Map) {
     override func mapping(map: ObjectMapper.Map) {
         vip                 <- map["vip"]
         vip                 <- map["vip"]
@@ -22,6 +25,8 @@ class TSThemeModel: TSBaseModel {
         poster                 <- map["poster"]
         poster                 <- map["poster"]
         themeId                 <- map["themeId"]
         themeId                 <- map["themeId"]
         ringtone                 <- map["ringtone"]
         ringtone                 <- map["ringtone"]
+        ringtoneName                 <- map["ringtoneName"]
+        ringtoneCover                 <- map["ringtoneCover"]
     }
     }
     
     
 }
 }

+ 0 - 14
AIRingtone/Business/TSThemeVC/TSThemeVC/View/TSThemeContentCell.swift

@@ -23,11 +23,6 @@ class TSThemeContentCell: TSBaseCollectionCell {
             make.edges.equalToSuperview()
             make.edges.equalToSuperview()
         }
         }
         
         
-//        answerView.addSubview(answerBgImageView)
-//        answerBgImageView.snp.makeConstraints { make in
-//            make.edges.equalToSuperview()
-//        }
-        
         let photoImageView = UIImageView.createImageView(imageName:"theme_answer_phone",contentMode: .scaleAspectFill)
         let photoImageView = UIImageView.createImageView(imageName:"theme_answer_phone",contentMode: .scaleAspectFill)
         answerView.addSubview(photoImageView)
         answerView.addSubview(photoImageView)
         photoImageView.snp.makeConstraints { make in
         photoImageView.snp.makeConstraints { make in
@@ -103,15 +98,6 @@ class TSThemeContentCell: TSBaseCollectionCell {
                 showImageView.setAsyncImage(urlString: themeModel.poster,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
                 showImageView.setAsyncImage(urlString: themeModel.poster,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
                 nameLabel.text = themeModel.name
                 nameLabel.text = themeModel.name
             }
             }
-            
-            
-//            if itemModel.dataModel.modelType == .example {
-//                exampleView.isHidden = false
-//                showImageView.image = UIImage(named: itemModel.dataModel.response.resultUrl)
-//            }else{
-//                exampleView.isHidden = true
-//                showImageView.setAsyncImage(urlString: itemModel.dataModel.response.resultUrl,contentMode: .scaleAspectFill)
-//            }
         }
         }
     }
     }
     
     

+ 288 - 0
AIRingtone/Business/VIewTool/TSBottomAlertVC.swift

@@ -0,0 +1,288 @@
+//
+//  TSBottomAlertVC.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/1/17.
+//
+
+class TSBottomAlertVC: TSBaseVC {
+    
+    lazy var topBgView: UIView = {
+        let topBgView = UIView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight))
+        topBgView.backgroundColor = .black.withAlphaComponent(0.5)
+        topBgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
+        return topBgView
+    }()
+    
+    var bottomViewH:CGFloat = 340{
+        didSet{
+            bottomView.frame = CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH)
+        }
+    }
+    
+    lazy var bottomView: UIView = {
+        let bottomView = UIView(frame: CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH))
+    
+        let bgImageView = UIImageView()
+        bgImageView.image = UIImage(named: "bottom_alert_bg")?.resizableImage(capInsets:UIEdgeInsets(top:40, left: 30, bottom: 30, right: 170))
+        bgImageView.contentMode = .scaleToFill
+        
+        bottomView.addSubview(bgImageView)
+        bgImageView.snp.makeConstraints { make in
+            make.bottom.top.leading.right.equalTo(0)
+        }
+        
+        return bottomView
+    }()
+    
+
+    lazy var xBtn: UIButton = {
+        let xBtn = TSUIExpandedTouchButton()
+        xBtn.setUpButton(image: UIImage(named: "x")) { [weak self]  in
+//        let xBtn = UIButton.createButton(image: UIImage(named: "x")) { [weak self]  in
+            guard let self = self else { return }
+            clickXBtn()
+        }
+        return xBtn
+    }()
+    
+    lazy var againBtn: UIButton = {
+        let againBtn = UIButton.createButton(title:"Try Again".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+        { [weak self]  in
+            guard let self = self else { return }
+            clickAgainBtn()
+        }
+        return againBtn
+    }()
+    
+    lazy var saveBtn: UIButton = {
+        let saveBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+        { [weak self]  in
+            guard let self = self else { return }
+            clickSubmitBtn()
+        }
+        return saveBtn
+    }()
+    
+    
+    lazy var leftBtn: UIButton = {
+        let leftBtn = UIButton.createButton(title:"Copy".localized,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+        { [weak self]  in
+            guard let self = self else { return }
+            clickLeftBtn()
+        }
+        leftBtn.isHidden = true
+        return leftBtn
+    }()
+    
+    lazy var rightBtn: UIButton = {
+        
+        let rightBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+        { [weak self]  in
+            guard let self = self else { return }
+            clickRightBtn()
+        }
+        rightBtn.isHidden = true
+        return rightBtn
+    }()
+    
+
+    lazy var regenerateBtn: UIButton = {
+        let regenerateBtn = UIButton.createButton(
+            title: "regenerate",
+            image: UIImage(named: "refresh_gary"),
+            backgroundColor:.white.withAlphaComponent(0.1),
+            font: .font(size: 12),
+            titleColor: .white.withAlphaComponent(0.6),
+            corner: 8.0)
+        { [weak self]  in
+            guard let self = self else { return }
+            clickAgainBtn()
+        }
+        regenerateBtn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 7, bottom: 4, right: 7)
+        regenerateBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
+        regenerateBtn.isHidden = true
+        return regenerateBtn
+    }()
+    
+    //############################## 失败 View ##############################
+    
+    lazy var failLabel: UILabel = {
+        let failLabel = UILabel.createLabel(text: "Generation Failed".localized,font: .font(size: 14.0),textColor: .white.withAlphaComponent(0.6),textAlignment: .center)
+        return failLabel
+    }()
+    
+    lazy var failView: UIView = {
+        let failView = UIView()
+        let failImageView = UIImageView.createImageView(imageName: "generation_failed")
+    
+        failView.addSubview(failImageView)
+        failImageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(88)
+            make.height.equalTo(88)
+        }
+        
+        failView.addSubview(failLabel)
+        failLabel.snp.makeConstraints { make in
+            make.top.equalTo(failImageView.snp.bottom).offset(16)
+            make.leading.equalTo(10)
+            make.trailing.equalTo(-10)
+            make.width.greaterThanOrEqualTo(88)
+            make.height.equalTo(14)
+            make.bottom.equalTo(0)
+        }
+        failView.isHidden = true
+        return failView
+    }()
+    
+    //############################## 结果 View ##############################
+    lazy var resultIconImageView: UIImageView = {
+        let resultIconImageView = UIImageView.createImageView(imageName: "")
+        return resultIconImageView
+    }()
+    
+    lazy var successTopView: UIView = {
+        let resultView = UIView()
+
+        resultView.addSubview(resultIconImageView)
+        resultIconImageView.snp.makeConstraints { make in
+            make.top.equalTo(-15)
+            make.trailing.equalTo(-28)
+            make.width.equalTo(88)
+            make.height.equalTo(88)
+        }
+        
+        let successLabel = UILabel.createLabel(text: "Successfully Generated".localized,font: .font(size: 18.0),textColor: .themeColor,textAlignment: .left)
+        resultView.addSubview(successLabel)
+        successLabel.snp.makeConstraints { make in
+            make.top.equalTo(30)
+            make.leading.equalTo(20)
+            make.trailing.equalTo(resultIconImageView.snp.leading).offset(-20)
+            make.height.equalTo(18)
+        }
+        
+        resultView.isHidden = true
+        return resultView
+    }()
+    
+    //############################## 自定义 View ##############################
+    lazy var diyView: UIView = {
+        let diyView = UIView()
+ 
+        diyView.addSubview(failView)
+        failView.snp.makeConstraints { make in
+            make.centerY.equalToSuperview().offset(-40)
+            make.centerX.equalToSuperview()
+        }
+        
+        diyView.addSubview(successTopView)
+        successTopView.snp.makeConstraints { make in
+            make.leading.top.trailing.equalTo(0)
+            make.height.equalTo(73)
+        }
+        
+
+        return diyView
+    }()
+    
+    //点击空白,关闭页面
+    var isClickTheBlankClosePage = true
+    
+    override func createView() {
+        view.backgroundColor = .clear
+        setNavBarViewHidden(true)
+
+        contentView.addSubview(topBgView)
+        contentView.addSubview(bottomView)
+    
+        let safeBottom = k_Height_safeAreaInsetsBottom()
+        //重试
+        bottomView.addSubview(againBtn)
+        againBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-16-safeBottom)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(228)
+            make.height.equalTo(48)
+        }
+        
+        //保存
+        bottomView.addSubview(saveBtn)
+        saveBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-16-safeBottom)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(228)
+            make.height.equalTo(48)
+        }
+        
+        
+        //中心点
+        let centerView = UIView()
+        bottomView.addSubview(centerView)
+        centerView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        bottomView.addSubview(leftBtn)
+        leftBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-16-safeBottom)
+            make.trailing.equalTo(centerView.snp.leading).offset(-8)
+            make.width.equalTo(163)
+            make.height.equalTo(48)
+        }
+        
+        bottomView.addSubview(rightBtn)
+        rightBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-16-safeBottom)
+            make.leading.equalTo(centerView.snp.trailing).offset(8)
+            make.width.equalTo(163)
+            make.height.equalTo(48)
+        }
+        
+        bottomView.addSubview(diyView)
+        diyView.snp.makeConstraints { make in
+            make.bottom.equalTo(saveBtn.snp.top).offset(-10)
+            make.top.left.right.equalTo(0)
+        }
+        
+        bottomView.addSubview(xBtn)
+        xBtn.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.trailing.equalTo(-6)
+            make.width.equalTo(24)
+            make.height.equalTo(24)
+        }
+        
+
+    }
+    
+    func closePage() {
+        self.dismiss(animated: true, completion: nil)
+    }
+
+    @objc func clickAgainBtn(){
+        
+    }
+    
+    @objc func clickSubmitBtn(){
+        
+    }
+    
+    @objc func clickLeftBtn(){
+        
+    }
+    
+    @objc func clickRightBtn(){
+        
+    }
+    
+    @objc func clickXBtn(){
+        closePage()
+    }
+    
+    @objc private func dismissKeyboard() {
+        if isClickTheBlankClosePage {
+            closePage()
+        }
+    }
+}

+ 24 - 36
AIRingtone/Business/VIewTool/TSCommonloadingView.swift

@@ -33,32 +33,52 @@ class TSCommonloadingView: TSBaseView {
     }()
     }()
     
     
     lazy var textLabel: UILabel = {
     lazy var textLabel: UILabel = {
-        let textLabel = UILabel.createLabel(font: .font(size: 12),textColor: .fromHex("#FFFFFF",alpha: 0.6))
+        let textLabel = UILabel.createLabel(font: .font(size: 12),textColor: .fromHex("#FFFFFF",alpha: 0.6),textAlignment: .center)
         return textLabel
         return textLabel
     }()
     }()
     
     
+    
+    lazy var cancelBtn: UIButton = {
+        let textColor = UIColor.white.withAlphaComponent(0.4)
+        let cancelBtn = UIButton.createButton(title:"Cancel".localized,backgroundColor: .black,font: UIFont.font(size: 16,weight: .regular),titleColor:textColor,corner: 24)
+        cancelBtn.layer.borderWidth = 1
+        cancelBtn.layer.borderColor = textColor.cgColor
+        return cancelBtn
+    }()
     private var targetView: UIView = UIView()
     private var targetView: UIView = UIView()
     
     
     override func creatUI() {
     override func creatUI() {
+        
+        let blurEffect = createBlurEffectView(style: .dark)
+        contentView.addSubview(blurEffect)
+        
         contentView.addSubview(imageView)
         contentView.addSubview(imageView)
         imageView.snp.makeConstraints { make in
         imageView.snp.makeConstraints { make in
             make.width.height.equalTo(200.0)
             make.width.height.equalTo(200.0)
             make.centerX.equalToSuperview()
             make.centerX.equalToSuperview()
-            make.top.equalToSuperview()
+            make.centerY.equalToSuperview().offset(-60)
         }
         }
         
         
         contentView.addSubview(animatedImageView)
         contentView.addSubview(animatedImageView)
         animatedImageView.snp.makeConstraints { make in
         animatedImageView.snp.makeConstraints { make in
             make.width.height.equalTo(200.0)
             make.width.height.equalTo(200.0)
             make.centerX.equalToSuperview()
             make.centerX.equalToSuperview()
-            make.top.equalToSuperview()
+            make.centerY.equalToSuperview().offset(-60)
         }
         }
   
   
         contentView.addSubview(textLabel)
         contentView.addSubview(textLabel)
         textLabel.snp.makeConstraints { make in
         textLabel.snp.makeConstraints { make in
             make.height.equalTo(18.0)
             make.height.equalTo(18.0)
             make.top.equalTo(imageView.snp.bottom).offset(16)
             make.top.equalTo(imageView.snp.bottom).offset(16)
-            make.leading.bottom.trailing.equalToSuperview()
+            make.leading.trailing.equalToSuperview()
+        }
+        
+        contentView.addSubview(cancelBtn)
+        cancelBtn.snp.makeConstraints { make in
+            make.height.equalTo(48.0)
+            make.top.equalTo(textLabel.snp.bottom).offset(36)
+            make.width.equalTo(200.0)
+            make.centerX.equalToSuperview()
         }
         }
     }
     }
     
     
@@ -120,38 +140,6 @@ class TSCommonloadingView: TSBaseView {
         isRotating = false
         isRotating = false
     }
     }
     
     
-//    /// 开始旋转
-//    func startRotating(view:UIView,duration: Double = 2.0) {
-//        targetView = view
-//        stopRotating(view: view)
-//        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
-//        rotationAnimation.toValue = CGFloat.pi * 2
-//        rotationAnimation.duration = duration
-//        rotationAnimation.isCumulative = true
-//        rotationAnimation.repeatCount = .infinity
-//
-//        view.layer.add(rotationAnimation, forKey: "rotationAnimation")
-//    }
-//
-//    /// 停止旋转
-//    func stopRotating(view:UIView) {
-//        view.layer.removeAnimation(forKey: "rotationAnimation")
-//    }
-//    
-//    func showLoading(text:String){
-//        imageView.image = UIImage(named: "rotating")
-//        textLabel.text = text
-//        isRotating = true
-//    }
-//    
-//    func showError(text:String){
-//        imageView.image = UIImage(named: "failed")
-//        textLabel.text = text
-//        isRotating = false
-//    }
-
-    
-    
     @objc private func handleAppDidEnterBackground() {
     @objc private func handleAppDidEnterBackground() {
         stopRotating(view: targetView)
         stopRotating(view: targetView)
     }
     }

+ 109 - 0
AIRingtone/Business/VIewTool/TSSavePhotoSuccessTool.swift

@@ -0,0 +1,109 @@
+//
+//  TSSavePhotoSuccessTool.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+let kSavePhotoSuccesswShared = TSSavePhotoSuccessTool.shared
+class TSSavePhotoSuccessTool {
+    
+    static let shared = TSSavePhotoSuccessTool()
+    
+    private lazy var textLabel:UILabel = {
+        let textLabel = UILabel()
+        textLabel.textColor = UIColor.white
+        textLabel.text = "Save Successfully".localized
+        textLabel.font = UIFont.font(size: 14)
+        return textLabel
+    }()
+    
+    private lazy var saveSuccessBg: UIView = {
+        return creatSaveSuccessBg()
+    }()
+    
+    
+    private lazy var viewButton:UIView = {
+        let color = "4FEA9D".uiColor
+        let viewButton = UIButton.createButton(title: "View".localized ,backgroundColor: color.withAlphaComponent(0.1),font: UIFont.font(size: 14),titleColor: color,corner: 14) {
+            if let url = URL(string: "photos-redirect://") {
+                if UIApplication.shared.canOpenURL(url) {
+                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
+                    playVibration()
+                }
+            }
+        }
+        return viewButton
+    }()
+    
+    func creatSaveSuccessBg() -> UIView {
+        let view = UIView()
+        view.frame = CGRect(x: 0, y: 0, width: 288, height: 48)
+        // 阴影
+        view.backgroundColor = .clear
+        view.layer.shadowColor = UIColor.black.cgColor
+        view.layer.shadowOffset = CGSize(width: 0, height: 2)
+        view.layer.shadowOpacity = 0.1
+        
+        // 圆角
+        let colorBg = UIView()
+        colorBg.backgroundColor = "#333333".uiColor
+        colorBg.layer.cornerRadius = 8
+        colorBg.layer.masksToBounds = true
+        colorBg.clipsToBounds = true
+        
+        view.addSubview(colorBg)
+        colorBg.snp.makeConstraints { make in
+            make.leading.trailing.top.bottom.equalTo(0)
+        }
+        
+        let image = UIImage(named: "success_icon")
+        let iconView = UIImageView(image: image)
+        view.addSubview(iconView)
+        iconView.snp.makeConstraints { make in
+            make.width.height.equalTo(24)
+            make.centerY.equalToSuperview()
+            make.leading.equalTo(12)
+        }
+    
+        view.addSubview(viewButton)
+        view.addSubview(textLabel)
+        viewButton.snp.makeConstraints { make in
+            make.width.equalTo(65)
+            make.height.equalTo(28)
+            make.trailing.equalTo(-8)
+            make.centerY.equalToSuperview()
+        }
+    
+        textLabel.snp.makeConstraints { make in
+            make.leading.equalTo(iconView.snp.trailing).offset(8)
+            make.trailing.equalTo(viewButton.snp.leading).offset(-4)
+            make.centerY.equalToSuperview()
+        }
+
+        return view
+    }
+
+    
+    
+    func show(atView:UIView,text:String = "Save Successfully".localized,showViewBtn:Bool = true) {
+        
+        kExecuteOnMainThread {
+            self.textLabel.text = text
+            self.viewButton.isHidden = !showViewBtn
+            atView.addSubview(self.saveSuccessBg)
+            self.saveSuccessBg.snp.remakeConstraints { make in
+                make.width.equalTo(288)
+                make.height.equalTo(48)
+                make.centerX.equalToSuperview()
+                make.bottom.equalTo(-112)
+            }
+        }
+
+        DispatchQueue.main.asyncAfter(deadline: .now()+2.0) {
+            self.saveSuccessBg.removeFromSuperview()
+        }
+    }
+    
+    
+}

+ 11 - 112
AIRingtone/Business/VIewTool/TSViewTool.swift

@@ -23,6 +23,7 @@ func createBlurEffectView(style:UIBlurEffect.Style,backgroundColor:UIColor? = ni
     return blurEffectView
     return blurEffectView
 }
 }
 
 
+
 //常用提交按钮
 //常用提交按钮
 func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
 func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
     let btn = UIButton.createButton(title:title,backgroundColor: .black,font: UIFont.font(size: 16,weight: .regular),titleColor:.themeColor,corner: 24,action: action)
     let btn = UIButton.createButton(title:title,backgroundColor: .black,font: UIFont.font(size: 16,weight: .regular),titleColor:.themeColor,corner: 24,action: action)
@@ -31,118 +32,16 @@ func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButt
     btn.frame = CGRectMake(0, 0, 200, 48)
     btn.frame = CGRectMake(0, 0, 200, 48)
     return btn
     return btn
 }
 }
-//常用取消按钮
-func kCreateNormalCancelBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-    let btn = UIButton.createButton(title:title,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
-    return btn
-}
-//常用确定按钮
-func kCreateNormalConfirmBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-    let btn = UIButton.createButton(title:title,backgroundImage:UIImage(named: "submit_btn_small_bg"),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
-    return btn
-}
+////常用取消按钮
+//func kCreateNormalCancelBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
+//    let btn = UIButton.createButton(title:title,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
+//    return btn
+//}
+////常用确定按钮
+//func kCreateNormalConfirmBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
+//    let btn = UIButton.createButton(title:title,backgroundImage:UIImage(named: "submit_btn_small_bg"),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
+//    return btn
+//}
 
 
 let kPlaceholderImage = UIImage(named: "placeholderImage")
 let kPlaceholderImage = UIImage(named: "placeholderImage")
 let kViewBJ = "view_bj"
 let kViewBJ = "view_bj"
-let kSavePhotoSuccesswShared = TSSavePhotoSuccessTool.shared
-class TSSavePhotoSuccessTool {
-    
-    static let shared = TSSavePhotoSuccessTool()
-    
-    private lazy var textLabel:UILabel = {
-        let textLabel = UILabel()
-        textLabel.textColor = UIColor.white
-        textLabel.text = "Save Successfully".localized
-        textLabel.font = UIFont.font(size: 14)
-        return textLabel
-    }()
-    
-    private lazy var saveSuccessBg: UIView = {
-        return creatSaveSuccessBg()
-    }()
-    
-    
-    private lazy var viewButton:UIView = {
-        let color = "4FEA9D".uiColor
-        let viewButton = UIButton.createButton(title: "View".localized ,backgroundColor: color.withAlphaComponent(0.1),font: UIFont.font(size: 14),titleColor: color,corner: 14) {
-            if let url = URL(string: "photos-redirect://") {
-                if UIApplication.shared.canOpenURL(url) {
-                    UIApplication.shared.open(url, options: [:], completionHandler: nil)
-                    playVibration()
-                }
-            }
-        }
-        return viewButton
-    }()
-    
-    func creatSaveSuccessBg() -> UIView {
-        let view = UIView()
-        view.frame = CGRect(x: 0, y: 0, width: 288, height: 48)
-        // 阴影
-        view.backgroundColor = .clear
-        view.layer.shadowColor = UIColor.black.cgColor
-        view.layer.shadowOffset = CGSize(width: 0, height: 2)
-        view.layer.shadowOpacity = 0.1
-        
-        // 圆角
-        let colorBg = UIView()
-        colorBg.backgroundColor = "#333333".uiColor
-        colorBg.layer.cornerRadius = 8
-        colorBg.layer.masksToBounds = true
-        colorBg.clipsToBounds = true
-        
-        view.addSubview(colorBg)
-        colorBg.snp.makeConstraints { make in
-            make.leading.trailing.top.bottom.equalTo(0)
-        }
-        
-        let image = UIImage(named: "success_icon")
-        let iconView = UIImageView(image: image)
-        view.addSubview(iconView)
-        iconView.snp.makeConstraints { make in
-            make.width.height.equalTo(24)
-            make.centerY.equalToSuperview()
-            make.leading.equalTo(12)
-        }
-    
-        view.addSubview(viewButton)
-        view.addSubview(textLabel)
-        viewButton.snp.makeConstraints { make in
-            make.width.equalTo(65)
-            make.height.equalTo(28)
-            make.trailing.equalTo(-8)
-            make.centerY.equalToSuperview()
-        }
-    
-        textLabel.snp.makeConstraints { make in
-            make.leading.equalTo(iconView.snp.trailing).offset(8)
-            make.trailing.equalTo(viewButton.snp.leading).offset(-4)
-            make.centerY.equalToSuperview()
-        }
-
-        return view
-    }
-
-    
-    
-    func show(atView:UIView,text:String = "Save Successfully".localized,showViewBtn:Bool = true) {
-        
-        kExecuteOnMainThread {
-            self.textLabel.text = text
-            self.viewButton.isHidden = !showViewBtn
-            atView.addSubview(self.saveSuccessBg)
-            self.saveSuccessBg.snp.remakeConstraints { make in
-                make.width.equalTo(288)
-                make.height.equalTo(48)
-                make.centerX.equalToSuperview()
-                make.bottom.equalTo(-112)
-            }
-        }
-
-        DispatchQueue.main.asyncAfter(deadline: .now()+2.0) {
-            self.saveSuccessBg.removeFromSuperview()
-        }
-    }
-    
-    
-}

+ 2 - 2
AIRingtone/Common/Config/TSConfig.swift

@@ -33,7 +33,7 @@ extension UIColor {
     static let lesserText = UIColor.fromHex("#FFFFFF", alpha: 0.6)
     static let lesserText = UIColor.fromHex("#FFFFFF", alpha: 0.6)
     
     
     /// 弱文字
     /// 弱文字
-    static let textDisable = "#010101".toColor()!
+    static let textDisable = "#BBC3DA".uiColor
     
     
     /// 辅助文字
     /// 辅助文字
     static let textAssist = UIColor.fromHex("#FFFFFF", alpha: 0.4)
     static let textAssist = UIColor.fromHex("#FFFFFF", alpha: 0.4)
@@ -42,7 +42,7 @@ extension UIColor {
     static let success = UIColor(named: "c_success")!
     static let success = UIColor(named: "c_success")!
     
     
     /// 辅助色
     /// 辅助色
-    static let assist = "#111111".uiColor
+    static let assist = UIColor.white.withAlphaComponent(0.6)
     
     
     /// 按钮色
     /// 按钮色
     static let button = UIColor(named: "c_button")!
     static let button = UIColor(named: "c_button")!

+ 14 - 0
AIRingtone/Common/Ex/Notification+TSEx.swift

@@ -0,0 +1,14 @@
+//
+//  Notification+TSEx.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/5.
+//
+
+// 扩展 Notification.Name
+extension Notification.Name {
+    static let kReloadUIData = Notification.Name("kReloadUIData")   //通知页面刷新数据,具体类型,根据参数来区分
+}
+
+
+

BIN
AIRingtone/Common/Res/rotatingAnimation.gif


+ 6 - 0
AIRingtone/Common/View/UIStackView/TSCustomStackView.swift

@@ -33,6 +33,12 @@ class TSCustomStackView: UIView {
         }
         }
     }
     }
     
     
+    var viewH:CGFloat {
+        get {
+            return scrollView.contentSize.height
+        }
+    }
+    
     // 初始化方法
     // 初始化方法
     init(axis: NSLayoutConstraint.Axis = .vertical, spacing: CGFloat = 0) {
     init(axis: NSLayoutConstraint.Axis = .vertical, spacing: CGFloat = 0) {
         self.scrollView = UIScrollView()
         self.scrollView = UIScrollView()

+ 1 - 0
Podfile

@@ -19,6 +19,7 @@ target 'AIRingtone' do
   pod 'Masonry'
   pod 'Masonry'
   pod 'SwipeCellKit'
   pod 'SwipeCellKit'
   pod 'TSSmalCoacopods', :path => '../TSSmalCoacopods'
   pod 'TSSmalCoacopods', :path => '../TSSmalCoacopods'
+  pod 'BetterSegmentedControl', '~> 2.0'
 end
 end
 
 
 
 

+ 5 - 1
Podfile.lock

@@ -1,5 +1,6 @@
 PODS:
 PODS:
   - Alamofire (5.10.2)
   - Alamofire (5.10.2)
+  - BetterSegmentedControl (2.0.1)
   - IQKeyboardCore (1.0.5)
   - IQKeyboardCore (1.0.5)
   - IQKeyboardManagerSwift (8.0.0):
   - IQKeyboardManagerSwift (8.0.0):
     - IQKeyboardManagerSwift/Appearance (= 8.0.0)
     - IQKeyboardManagerSwift/Appearance (= 8.0.0)
@@ -56,6 +57,7 @@ PODS:
 
 
 DEPENDENCIES:
 DEPENDENCIES:
   - Alamofire
   - Alamofire
+  - BetterSegmentedControl (~> 2.0)
   - IQKeyboardManagerSwift
   - IQKeyboardManagerSwift
   - JXPagingView/Paging
   - JXPagingView/Paging
   - JXSegmentedView
   - JXSegmentedView
@@ -70,6 +72,7 @@ DEPENDENCIES:
 SPEC REPOS:
 SPEC REPOS:
   trunk:
   trunk:
     - Alamofire
     - Alamofire
+    - BetterSegmentedControl
     - IQKeyboardCore
     - IQKeyboardCore
     - IQKeyboardManagerSwift
     - IQKeyboardManagerSwift
     - IQKeyboardNotification
     - IQKeyboardNotification
@@ -93,6 +96,7 @@ EXTERNAL SOURCES:
 
 
 SPEC CHECKSUMS:
 SPEC CHECKSUMS:
   Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
   Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
+  BetterSegmentedControl: 09607b27861d49cbce48b7673b74f9150a3d371a
   IQKeyboardCore: 28c8bf3bcd8ba5aa1570b318cbc4da94b861711e
   IQKeyboardCore: 28c8bf3bcd8ba5aa1570b318cbc4da94b861711e
   IQKeyboardManagerSwift: 0c6fbbaa2e60739e48d7cf59f25661471a7a3a65
   IQKeyboardManagerSwift: 0c6fbbaa2e60739e48d7cf59f25661471a7a3a65
   IQKeyboardNotification: d7382c4466c5a5adef92c7452ebf861b36050088
   IQKeyboardNotification: d7382c4466c5a5adef92c7452ebf861b36050088
@@ -111,6 +115,6 @@ SPEC CHECKSUMS:
   SwipeCellKit: 3972254a826da74609926daf59b08d6c72e619ea
   SwipeCellKit: 3972254a826da74609926daf59b08d6c72e619ea
   TSSmalCoacopods: 9a7d88d8a76e8317722e5247a6b3b89b0fe32982
   TSSmalCoacopods: 9a7d88d8a76e8317722e5247a6b3b89b0fe32982
 
 
-PODFILE CHECKSUM: 63a8513c1abbb1a847178d18faed5c6ba603a2f3
+PODFILE CHECKSUM: 0d445941f585aa08bd08d8aadd1bdfb535c72899
 
 
 COCOAPODS: 1.16.2
 COCOAPODS: 1.16.2