Parcourir la source

基本开发完毕

100Years il y a 1 semaine
Parent
commit
8e3f30b927
70 fichiers modifiés avec 1220 ajouts et 248 suppressions
  1. 36 0
      AIEmoji.xcodeproj/project.pbxproj
  2. 22 0
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/Contents.json
  3. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/ai_emo_changePic@2x.png
  4. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/ai_emo_changePic@3x.png
  5. 22 0
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/Contents.json
  6. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/ai_emo_none@2x.png
  7. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/ai_emo_none@3x.png
  8. 22 0
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/Contents.json
  9. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/ai_emo_style_vip@2x.png
  10. BIN
      AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/ai_emo_style_vip@3x.png
  11. 22 0
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/Contents.json
  12. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/ptp_style_3D@2x.png
  13. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/ptp_style_3D@3x.png
  14. 22 0
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/Contents.json
  15. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/ptp_style_Claymation@2x.png
  16. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/ptp_style_Claymation@3x.png
  17. 22 0
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/Contents.json
  18. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/ptp_style_Pixel@2x.png
  19. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/ptp_style_Pixel@3x.png
  20. 22 0
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/Contents.json
  21. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/ptp_style_Sketch@2x.png
  22. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/ptp_style_Sketch@3x.png
  23. 22 0
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/Contents.json
  24. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/ptp_style_Toy@2x.png
  25. BIN
      AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/ptp_style_Toy@3x.png
  26. 10 11
      AIEmoji/Business/Data/TSUserDefaultData.swift
  27. 2 2
      AIEmoji/Business/General/TSBigIconBrowseVC/TSBigIconBrowseVC.swift
  28. 2 2
      AIEmoji/Business/General/TSSmallIconBrowseVC/TSSmallIconBrowseVC.swift
  29. 10 6
      AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIListHintBaseVC.swift
  30. 258 0
      AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/TSAIChangeEmoteVC.swift
  31. 212 0
      AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/View/TSAIChangeEmoteStyleView.swift
  32. 234 0
      AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/ViewModel/TSAIChangeEmoteVM.swift
  33. 3 3
      AIEmoji/Business/TSAILIstVC/TSAILIstVC/TSAILIstVC.swift
  34. 1 1
      AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVC.swift
  35. 1 1
      AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVM.swift
  36. 8 10
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift
  37. 4 4
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift
  38. 9 5
      AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift
  39. 2 2
      AIEmoji/Business/TSEmojisVC/TSEmojisChildVC/TSEmojisChildVC.swift
  40. 5 5
      AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateVC.swift
  41. 2 2
      AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateViewModel.swift
  42. 2 2
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/Model/TSGenmojiModel.swift
  43. 1 1
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/TSGenmojiVC.swift
  44. 2 2
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift
  45. 5 5
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiViewModel.swift
  46. 3 3
      AIEmoji/Business/TSPTPGeneratorVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoBrowseVC.swift
  47. 2 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPBrowseVC/TSPTPBrowseVC.swift
  48. 5 5
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/TSPTPGeneratorVC.swift
  49. 4 4
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/VM/TSPTPGeneratorVM.swift
  50. 7 29
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/TSPTPInputVC.swift
  51. 13 13
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/VM/TSPTPInputVM.swift
  52. 2 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/View/TSPTPSelectStyleView.swift
  53. 2 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/Cell/TSPTPSelectStyleCell.swift
  54. 8 3
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/M/TSPTPStyleModel.swift
  55. 2 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/TSPhotoToPhotoVC.swift
  56. 14 14
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/VM/TSPhotoToPhotoVM.swift
  57. 1 7
      AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift
  58. 5 5
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/VM/TSTTPInputVM.swift
  59. 3 3
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSTTPStyleView.swift
  60. 1 1
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/TSTextGeneralPictureVC.swift
  61. 2 2
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/View/TSTTPSelectStyleCell.swift
  62. 5 5
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVC.swift
  63. 4 4
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVM.swift
  64. 12 4
      AIEmoji/Business/VIewTool/TSGeneratorloadingView.swift
  65. 1 0
      AIEmoji/Common/NetworkManager/TSNetWork/TSNetWork+Business.swift
  66. 3 3
      AIEmoji/Common/Purchase/TSPurchaseManager.swift
  67. 1 0
      AIEmoji/Common/Tool/TSCommonTool/TSCommonTool.swift
  68. 59 47
      AIEmoji/Common/View/TSPhotoPickerManager/TSPhotoPickerManager.swift
  69. 40 24
      AIEmoji/Res/ai_change_emote_style.json
  70. 36 0
      AIEmoji/Res/photo_to_photo_style.json

+ 36 - 0
AIEmoji.xcodeproj/project.pbxproj

@@ -178,6 +178,9 @@
 		A8F4134E2DA75E9E001E715A /* TSAboutDataVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F4134D2DA75E92001E715A /* TSAboutDataVC.swift */; };
 		A8F413512DA7B722001E715A /* TSPurchaseManager+DataReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F413502DA7B711001E715A /* TSPurchaseManager+DataReport.swift */; };
 		A8F413552DA8BA4E001E715A /* ai_change_emote_style.json in Resources */ = {isa = PBXBuildFile; fileRef = A8F413542DA8BA47001E715A /* ai_change_emote_style.json */; };
+		A8F413582DA8E507001E715A /* TSAIChangeEmoteVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F413572DA8E506001E715A /* TSAIChangeEmoteVC.swift */; };
+		A8F4135D2DA8E6CA001E715A /* TSAIChangeEmoteStyleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F4135C2DA8E6C8001E715A /* TSAIChangeEmoteStyleView.swift */; };
+		A8F413602DA8E972001E715A /* TSAIChangeEmoteVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F4135F2DA8E96D001E715A /* TSAIChangeEmoteVM.swift */; };
 		A8F7748B2D38E8B700AA6E93 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8F774812D38E8B700AA6E93 /* AppDelegate.swift */; };
 		A8F7748E2D38E8B700AA6E93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A8F774822D38E8B700AA6E93 /* Assets.xcassets */; };
 		A8F774902D38E8B700AA6E93 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8F774852D38E8B700AA6E93 /* LaunchScreen.storyboard */; };
@@ -424,6 +427,9 @@
 		A8F4134D2DA75E92001E715A /* TSAboutDataVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAboutDataVC.swift; sourceTree = "<group>"; };
 		A8F413502DA7B711001E715A /* TSPurchaseManager+DataReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSPurchaseManager+DataReport.swift"; sourceTree = "<group>"; };
 		A8F413542DA8BA47001E715A /* ai_change_emote_style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ai_change_emote_style.json; sourceTree = "<group>"; };
+		A8F413572DA8E506001E715A /* TSAIChangeEmoteVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIChangeEmoteVC.swift; sourceTree = "<group>"; };
+		A8F4135C2DA8E6C8001E715A /* TSAIChangeEmoteStyleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIChangeEmoteStyleView.swift; sourceTree = "<group>"; };
+		A8F4135F2DA8E96D001E715A /* TSAIChangeEmoteVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIChangeEmoteVM.swift; sourceTree = "<group>"; };
 		A8F774692D38E8B000AA6E93 /* AIEmoji.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AIEmoji.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		A8F774812D38E8B700AA6E93 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		A8F774822D38E8B700AA6E93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -1322,6 +1328,7 @@
 		A8BA765F2DA6479A000B6707 /* TSAILIstVC */ = {
 			isa = PBXGroup;
 			children = (
+				A8F413562DA8E500001E715A /* TSAIChangeEmoteVC */,
 				A8BA76732DA67E60000B6707 /* TSAIListHistoryBaseVC */,
 				A8BA76702DA65A81000B6707 /* TSAIUploadPhotoBaseVC */,
 				A8BA766A2DA6579A000B6707 /* TSAIPhotoGeneratorBaseVC */,
@@ -1391,6 +1398,32 @@
 			path = TSUploadPhotoPrivacyAlertVC;
 			sourceTree = "<group>";
 		};
+		A8F413562DA8E500001E715A /* TSAIChangeEmoteVC */ = {
+			isa = PBXGroup;
+			children = (
+				A8F4135E2DA8E956001E715A /* ViewModel */,
+				A8F4135B2DA8E6B6001E715A /* View */,
+				A8F413572DA8E506001E715A /* TSAIChangeEmoteVC.swift */,
+			);
+			path = TSAIChangeEmoteVC;
+			sourceTree = "<group>";
+		};
+		A8F4135B2DA8E6B6001E715A /* View */ = {
+			isa = PBXGroup;
+			children = (
+				A8F4135C2DA8E6C8001E715A /* TSAIChangeEmoteStyleView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		A8F4135E2DA8E956001E715A /* ViewModel */ = {
+			isa = PBXGroup;
+			children = (
+				A8F4135F2DA8E96D001E715A /* TSAIChangeEmoteVM.swift */,
+			);
+			path = ViewModel;
+			sourceTree = "<group>";
+		};
 		A8F774602D38E8B000AA6E93 = {
 			isa = PBXGroup;
 			children = (
@@ -1984,6 +2017,7 @@
 				A8F776422D3B75FC00AA6E93 /* TSBottomAlertVC.swift in Sources */,
 				A8F775192D38EC6800AA6E93 /* TSEmojisVC.swift in Sources */,
 				A80E725C2D3FB09400C64288 /* TSKeyboardView.swift in Sources */,
+				A8F413582DA8E507001E715A /* TSAIChangeEmoteVC.swift in Sources */,
 				A89EA6CC2D642CE2000EB181 /* TSChatViewController+NaviBar.swift in Sources */,
 				A8F7753B2D3918DE00AA6E93 /* TSNetworkManager+Loading.swift in Sources */,
 				A80E721A2D3F393A00C64288 /* DiyStickerModel.swift in Sources */,
@@ -2047,6 +2081,7 @@
 				A8F775432D39346400AA6E93 /* TSSetingModel.swift in Sources */,
 				A89EA6BA2D5DDE5B000EB181 /* TSPageNullView.swift in Sources */,
 				A89EA6C12D5ED289000EB181 /* TSChatCellConfig.swift in Sources */,
+				A8F413602DA8E972001E715A /* TSAIChangeEmoteVM.swift in Sources */,
 				A8F775502D39ECED00AA6E93 /* PhotoManager.swift in Sources */,
 				A8F7763F2D3B68E100AA6E93 /* TSGenmojiGennerateViewModel.swift in Sources */,
 				A8BA76612DA647AC000B6707 /* TSAILIstVC.swift in Sources */,
@@ -2144,6 +2179,7 @@
 				A8FB02B72D3E3A3D0031A396 /* TSEmojisChildViewModel.swift in Sources */,
 				A8F7754B2D39376800AA6E93 /* TSSettingListView.swift in Sources */,
 				A8F7748B2D38E8B700AA6E93 /* AppDelegate.swift in Sources */,
+				A8F4135D2DA8E6CA001E715A /* TSAIChangeEmoteStyleView.swift in Sources */,
 				A80327B02D813A0200AF7878 /* TSTTPSelectStyleCell.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 22 - 0
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/ai_emo_changePic@2x.png


BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_changePic.imageset/ai_emo_changePic@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/ai_emo_none@2x.png


BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_none.imageset/ai_emo_none@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/ai_emo_style_vip@2x.png


BIN
AIEmoji/Assets.xcassets/AIList/emo/ai_emo_style_vip.imageset/ai_emo_style_vip@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/ptp_style_3D@2x.png


BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_3D.imageset/ptp_style_3D@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/ptp_style_Claymation@2x.png


BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Claymation.imageset/ptp_style_Claymation@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/ptp_style_Pixel@2x.png


BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Pixel.imageset/ptp_style_Pixel@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/ptp_style_Sketch@2x.png


BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Sketch.imageset/ptp_style_Sketch@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/ptp_style_Toy@2x.png


BIN
AIEmoji/Assets.xcassets/PTP/style/ptp_style_Toy.imageset/ptp_style_Toy@3x.png


+ 10 - 11
AIEmoji/Business/Data/TSUserDefaultData.swift

@@ -41,7 +41,6 @@ func kHandleTSHistory(){
 
 // MARK: - 基础历史记录类
 class TSBaseHistoryManager<ModelType: TSBaseModel> {
-    
     // 子类必须重写的属性
     var historyKey: String { fatalError("必须重写 historyKey") }
     var exampleDataKey: String { fatalError("必须重写 exampleDataKey") }
@@ -161,7 +160,7 @@ class TSBaseHistoryManager<ModelType: TSBaseModel> {
 
 // MARK: - 新的储存方法
 // MARK: - 变老
-final class TSChangeOldAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
+final class TSChangeOldAgeHistory: TSBaseHistoryManager<TSActionInfoModel> {
     static let shared = TSChangeOldAgeHistory()
     override var historyKey: String { "kTSChangeOldAgeHistoryListString" }
 //    override var exampleDataKey: String { "insertPosterExampleData" }
@@ -170,12 +169,12 @@ final class TSChangeOldAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
         return listModels.firstIndex(where: {$0.id == modelID})
     }
     
-    override var exampleModels: [TSGenmojiModel] {
+    override var exampleModels: [TSActionInfoModel] {
         []
     }
 //
-//    private func createExampleModel(imageName: String) -> TSGenmojiModel {
-//        let model = TSGenmojiModel()
+//    private func createExampleModel(imageName: String) -> TSActionInfoModel {
+//        let model = TSActionInfoModel()
 //        model.modelType = .example
 //        model.request.prompt = "Example"
 //        model.request.promptSort = "Example"
@@ -185,11 +184,11 @@ final class TSChangeOldAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
 }
 
 // MARK: - 变年轻
-final class TSChangeBabyAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
+final class TSChangeBabyAgeHistory: TSBaseHistoryManager<TSActionInfoModel> {
     static let shared = TSChangeBabyAgeHistory()
     override var historyKey: String { "kTSChangeBabyAgeHistoryListString" }
     
-    override var exampleModels: [TSGenmojiModel] {
+    override var exampleModels: [TSActionInfoModel] {
         []
     }
     override func findModelID(modelID: Int) -> Int? {
@@ -263,7 +262,7 @@ final class TSChangeBabyAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
 class TSTextToPicHistory{
     @UserDefault(key: "textPicHistoryListString", defaultValue: "")
     static private var historyString: String
-    static var listModelArray: [TSGenmojiModel] = {
+    static var listModelArray: [TSActionInfoModel] = {
         
 //        if UserDefaults.standard.string(forKey: "insertPosterExampleData") == nil {
 //            insertExampleData()
@@ -271,18 +270,18 @@ class TSTextToPicHistory{
 //            UserDefaults.standard.synchronize()
 //        }
         
-        if let listModelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: historyString){
+        if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyString){
             return listModelArray
         }
         return []
     }()
     
-    static func saveModel(model:TSGenmojiModel){
+    static func saveModel(model:TSActionInfoModel){
         listModelArray.insert(model, at: 0)
         saveHistoryString()
     }
     
-    static func removeModel(model:TSGenmojiModel){
+    static func removeModel(model:TSActionInfoModel){
         listModelArray.removeAll { $0 === model }
         saveHistoryString()
     }

+ 2 - 2
AIEmoji/Business/General/TSBigIconBrowseVC/TSBigIconBrowseVC.swift

@@ -9,7 +9,7 @@ private let cellId = "TSBigIconBrowseCell"
 class TSBigIconBrowseVC: TSBottomAlertVC {
 
     
-    var dataModelArray = [TSGenmojiModel]()
+    var dataModelArray = [TSActionInfoModel]()
     var currentImage:UIImage?{
         let cell = collectionView.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? TSBigIconBrowseCell
         var image = cell?.netWorkImageView.image
@@ -17,7 +17,7 @@ class TSBigIconBrowseVC: TSBottomAlertVC {
         return image
     }
 
-    var currentModel:TSGenmojiModel?{
+    var currentModel:TSActionInfoModel?{
         if let model = dataModelArray.safeObj(At: currentIndex){
             return model
         }

+ 2 - 2
AIEmoji/Business/General/TSSmallIconBrowseVC/TSSmallIconBrowseVC.swift

@@ -9,14 +9,14 @@ private let cellId = "TSSmallIconBrowseCell"
 class TSSmallIconBrowseVC: TSBottomAlertVC {
 
     
-    var dataModelArray = [TSGenmojiModel]()
+    var dataModelArray = [TSActionInfoModel]()
     var currentImage:UIImage?{
         let cell = collectionView.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? TSSmallIconBrowseCell
         var image = cell?.netWorkImageView.image
         image = image?.pngImage
         return image
     }
-    var currentModel:TSGenmojiModel?{
+    var currentModel:TSActionInfoModel?{
         if let model = dataModelArray.safeObj(At: currentIndex){
             return model
         }

+ 10 - 6
AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIListHintBaseVC.swift

@@ -10,7 +10,7 @@ class TSAIListHintBaseVC: TSBaseVC {
     
     static var userDefaultsKey:String = "isFirstAIListAge"
     
-    
+    var imageMaxBitSize:Int = kUploadImageMaxBitSize
     var goodImageNamed:String = "ptp_goodImage"
     var badImageNamed:String = "ptp_badImage"
     
@@ -18,7 +18,7 @@ class TSAIListHintBaseVC: TSBaseVC {
     let popupContentViewW:CGFloat = k_ScreenWidth - 40.0
     let popupContentViewH:CGFloat = k_ScreenHeight - 268.0
     
-    var clickUpImageHandle:((UIImage?,PHAsset?)->Void)?
+    var clickUpImageHandle:((UIImage?)->Void)?
     lazy var popupContentView: UIView = {
         let popupContentView = UIView(frame: CGRectMake(0, 0, popupContentViewW, popupContentViewH))
         popupContentView.backgroundColor = "#222222".uiColor
@@ -44,7 +44,7 @@ class TSAIListHintBaseVC: TSBaseVC {
         setNavBarViewHidden(true)
         view.backgroundColor = .black.withAlphaComponent(0.7)
         
-        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickView)))
+//        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickView)))
         
         contentView.addSubview(popupContentView)
         popupContentView.center = view.center
@@ -165,10 +165,14 @@ class TSAIListHintBaseVC: TSBaseVC {
     }
     
     func pickSinglePhoto()  {
-        photoPickerManager.pickSinglePhoto { [weak self] image,phAsset in
+        photoPickerManager.pickSinglePhoto(maxBitSize: imageMaxBitSize) { [weak self] image, errorString in
             guard let self = self else { return }
-            dismiss()
-            clickUpImageHandle?(image,phAsset)
+            if let errorString = errorString {
+                TSToastShared.showToast(text: errorString)
+            }else{
+                dismiss()
+                clickUpImageHandle?(image)
+            }
         }
     }
 }

+ 258 - 0
AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/TSAIChangeEmoteVC.swift

@@ -0,0 +1,258 @@
+//
+//  TSAIChangeEmoteVC.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/10.
+//
+
+import PhotosUI
+
+class TSAIChangeEmoteVC: TSBaseVC {
+    
+    lazy var viewModel: TSAIChangeEmoteVM = {
+        let viewModel:TSAIChangeEmoteVM = TSAIChangeEmoteVM()
+        return viewModel
+    }()
+    
+    var upLoadImage:UIImage?{
+        didSet{
+            topImageView.image = upLoadImage
+        }
+    }
+    lazy var photoPickerManager: TSPhotoPickerManager = {
+        let photoPickerManager = TSPhotoPickerManager(viewController: self)
+        return photoPickerManager
+    }()
+    
+    //###################################### topImageView ######################################
+    lazy var topImageView: UIImageView = {
+        let imageView = UIImageView()
+        imageView.contentMode = .scaleAspectFit
+        return imageView
+    }()
+    
+    //###################################### style类型 ######################################
+    lazy var styleView: TSAIChangeEmoteStyleView = {
+        let styleView = TSAIChangeEmoteStyleView()
+        styleView.currentIndexPath = IndexPath(item: viewModel.selectedStyleIndex, section: 0)
+        styleView.dataArray = viewModel.selectStyleModels
+        styleView.selectedValueBlock = { [weak self] model in
+            guard let self = self else { return }
+            handelSelectedValueBlock(model: model)
+        }
+        return styleView
+    }()
+    //###################################### 按钮 ######################################
+    
+    lazy var saveBtn: UIButton = {
+        let btn = UIButton.createButton(title: "Save".localized,backgroundColor: .themeColor,font: .font(size: 12),titleColor: "#111111".uiColor,corner: 14){ [weak self]  in
+            guard let self = self else { return }
+            
+            if let img = topImageView.image, let image = img.pngImage{
+                PhotoManagerShared.saveImageToAlbum(image) { success, error in
+                    if success {
+                        kSavePhotoSuccesswShared.show(atView:self.view)
+                    }else{
+                        debugPrint(error)
+                    }
+                }
+            }
+        }
+        btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 25, bottom: 0, right: 25)
+        return btn
+    }()
+    
+    lazy var switchOriginalPictureBtn: UIButton = {
+        let switchOriginalPictureBtn = UIButton.createButton(image:UIImage(named: "switch_original_picture"))
+        switchOriginalPictureBtn.addTarget(self, action: #selector(switchOriginalPictureTouchDown), for: .touchDown)
+        switchOriginalPictureBtn.addTarget(self, action: #selector(switchOriginalPictureTouchUp), for: [.touchUpInside, .touchUpOutside, .touchCancel])
+        switchOriginalPictureBtn.isHidden = true
+        return switchOriginalPictureBtn
+    }()
+    
+    lazy var generateInView : TSGeneratorloadingView = {
+        let generateInView = TSGeneratorloadingView()
+        generateInView.setBackgroundColor(color: UIColor.black.withAlphaComponent(0.8))
+        generateInView.isHidden = true
+        return generateInView
+    }()
+    
+    override func createView() {
+        setUpView()
+        
+        view.addSubview(generateInView)
+        generateInView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+    }
+   
+    override func dealThings() {
+        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)
+        
+        TSAIAgeImageHintVC.userDefaultsKey = "isFirstAIChangeEmote"
+        
+        if TSAIAgeImageHintVC.isShowUploadImageHint{
+            TSAIAgeImageHintVC.isShowUploadImageHint = false
+            self.presentModalHintVC()
+        }else {
+            self.pickSinglePhoto()
+        }
+        
+    }
+}
+
+extension TSAIChangeEmoteVC {
+    
+    func setUpView() {
+        
+        addNormalNavBarView()
+        setPageTitle("")
+        normalNavBarView.barView.addSubview(saveBtn)
+        saveBtn.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.trailing.equalTo(-16)
+            make.height.equalTo(28)
+        }
+
+        contentView.addSubview(styleView)
+        contentView.addSubview(topImageView)
+
+        styleView.snp.makeConstraints { make in
+            make.bottom.equalTo(-10-k_Height_safeAreaInsetsBottom())
+            make.leading.trailing.equalTo(0)
+            make.height.equalTo(100)
+        }
+        
+        topImageView.snp.makeConstraints { make in
+            make.bottom.equalTo(styleView.snp.top).offset(-10)
+            make.leading.equalTo(0)
+            make.trailing.equalTo(0)
+            make.top.equalTo(0)
+        }
+        
+        topImageView.addSubview(switchOriginalPictureBtn)
+        switchOriginalPictureBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-16)
+            make.trailing.equalTo(-16)
+            make.width.equalTo(40)
+            make.height.equalTo(40)
+        }
+    }
+    
+}
+extension TSAIChangeEmoteVC {
+    func handelSelectedValueBlock(model:TSGenerateStyleModel)  {
+        switchOriginalPictureBtn.isHidden = true
+        if model.clickType == 1 { //无类型
+            topImageView.image = upLoadImage
+            styleView.agreeWillSelectIndexPath()
+        }else if model.clickType == 2 { //换图
+            self.pickSinglePhoto()
+        }else{
+            if kJudgeVip(externalBool: true, vc: self){ return }//判断 vip
+            viewModel.selectStyleModel = model
+            viewModel.uploadAndCreatImage()
+        }
+    }
+    
+    @objc func switchOriginalPictureTouchDown() {
+        self.topImageView.image = upLoadImage
+    }
+    
+    @objc func switchOriginalPictureTouchUp() {
+        guard let selectStyleModel = viewModel.selectStyleModel else { return }
+        guard let actionInfoModel = selectStyleModel.actionInfoModel else { return }
+        self.topImageView.setAsyncImage(urlString: actionInfoModel.response.resultUrl,placeholder:upLoadImage)
+    }
+}
+extension TSAIChangeEmoteVC {
+    
+    func pickSinglePhoto()  {
+        photoPickerManager.pickSinglePhoto(maxBitSize: kUploadImageMaxBitSize) { [weak self] image, errorString in
+            guard let self = self else { return }
+            if let errorString = errorString {
+                TSToastShared.showToast(text: errorString)
+            }else{
+                handlePhotoPicke(image: image)
+            }
+        }
+    }
+
+    func presentModalHintVC(){
+        let vc = TSAIAgeImageHintVC()
+        vc.clickUpImageHandle = { [weak self] image in
+            guard let self = self else { return }
+            handlePhotoPicke(image: image)
+        }
+        kPresentModalVC(target: self, modelVC: vc,transitionStyle: .crossDissolve)
+    }
+    
+    func handlePhotoPicke(image:UIImage?){
+        if let image = image {
+            upLoadImage = image
+            viewModel.upLoadImage = image
+            styleView.agreeWillSelectIndexPath()
+        }
+        
+        if upLoadImage == nil {
+            pop()
+        }
+    }
+}
+
+
+extension TSAIChangeEmoteVC {
+    func upDateView(state:TSProgressState,model:TSActionInfoModel?){
+        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)
+            case .none:
+                generateInView.isHidden = true
+                generateInView.isRotating = false
+            default:
+                showLoading()
+        }
+    }
+    func showProgress(text:String) {
+        generateInView.isHidden = false
+        generateInView.showLoading(text: text)
+        generateInView.isRotating = true
+    }
+    
+    func showLoading(){
+        generateInView.isHidden = false
+        generateInView.showLoading(text: "Generating".localized + " ...".localized)
+        generateInView.isRotating = true
+   
+    }
+    
+    func showError(text:String?){
+        let msg = "Failed to generate, please try later".localized
+        generateInView.isHidden = false
+        generateInView.showError(text: msg)
+        generateInView.isRotating = false
+    }
+    
+    func showSuccess(model:TSActionInfoModel){
+        generateInView.isHidden = true
+        generateInView.isRotating = false
+        
+        viewModel.selectStyleModel?.actionInfoModel = model
+
+        self.topImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:upLoadImage)
+        
+        styleView.agreeWillSelectIndexPath()
+        switchOriginalPictureBtn.isHidden = false
+    }
+}

+ 212 - 0
AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/View/TSAIChangeEmoteStyleView.swift

@@ -0,0 +1,212 @@
+//
+//  TSAIChangeEmoteStyleView.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/10.
+//
+
+class TSAIChangeEmoteStyleView:TSBaseView {
+    
+    var selectedValueBlock:((TSGenerateStyleModel)->Void)?
+    
+    var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
+        didSet{
+            styleCollectionView.reloadData()
+            if dataArray.count > 0 {
+                self.styleCollectionView.selectItem(at: self.currentIndexPath, animated: false, scrollPosition: .centeredHorizontally)
+            }
+        }
+    }
+    
+    lazy var layout: UICollectionViewFlowLayout = {
+        let layout = UICollectionViewFlowLayout()
+        layout.scrollDirection = .horizontal
+        layout.itemSize = CGSize(width: 60, height: 100)
+        layout.minimumInteritemSpacing = 12.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(TSAIChangeEmoteStyleCell.self, forCellWithReuseIdentifier: TSAIChangeEmoteStyleCell.cellID)
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        return collectionView
+    }()
+    lazy var willSelectIndexPath = currentIndexPath
+    var currentIndexPath:IndexPath = IndexPath(item: 0, section: 0){
+        didSet{
+            for (i,model) in dataArray.enumerated(){
+                if i == currentIndexPath.item {
+                    model.isSelected = true
+                }else {
+                    model.isSelected = false
+                }
+            }
+            styleCollectionView.reloadData()
+        }
+    }
+    
+    override func creatUI() {
+
+        currentIndexPath = IndexPath(item: 0, section: 0)
+        contentView.addSubview(styleCollectionView)
+        styleCollectionView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.trailing.equalTo(0)
+            make.height.equalTo(0)
+            make.bottom.equalTo(0)
+        }
+    }
+    
+    func unCheck(){
+        styleCollectionView.deselectItem(at: currentIndexPath, animated: true)
+    }
+    
+    func agreeWillSelectIndexPath(){
+        currentIndexPath = willSelectIndexPath
+    }
+    
+}
+
+extension TSAIChangeEmoteStyleView: 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: TSAIChangeEmoteStyleCell.cellID, for: indexPath)
+        if let cell = cell as? TSAIChangeEmoteStyleCell,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){
+            willSelectIndexPath = indexPath
+            selectedValueBlock?(model)
+        }
+    }
+    
+    
+//    // 在 didSelectItemAt 方法中处理选中
+//    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+//        
+//        if let model = dataArray.safeObj(At: indexPath.item),let selectedValueBlock = selectedValueBlock{
+//            if selectedValueBlock(model){
+//                currentIndexPath = indexPath
+//                handleSelectedCellForItem(at: indexPath, isSelected: true)
+//            }else{
+//                handleSelectedCellForItem(at: indexPath, isSelected: false)
+//            }
+//        }
+//        
+//  
+//    }
+//
+////    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
+////        if let cell = collectionView.cellForItem(at: indexPath) {
+////            cell.isSelected = false
+////            // 可以在这里更新 UI 以反映取消选中状态
+////        }
+////    }
+//    
+//    func handleSelectedCellForItem(at indexPath: IndexPath,isSelected:Bool){
+//        if let cell = styleCollectionView.cellForItem(at: indexPath) {
+//            cell.isSelected = true
+//        }
+//    }
+}
+
+class TSAIChangeEmoteStyleCell: TSBaseCollectionCell {
+    
+    static let cellID = "TSAIChangeEmoteStyleCell"
+
+//    override var isSelected: Bool{
+//        didSet{
+//            boardImageView.isHidden = isSelected ? false : true
+//        }
+//    }
+    
+    var itemModel:TSGenerateStyleModel = TSGenerateStyleModel(){
+        didSet{
+            imageView.image = UIImage(named: itemModel.imageName)
+            vipImageView.isHidden = itemModel.isVip == false
+            textLabel.text = itemModel.imageText.localized
+            boardImageView.isHidden = itemModel.isSelected ? false : true
+        }
+    }
+    
+    lazy var imageView: UIImageView = {
+        let imageView = UIImageView()
+        imageView.cornerRadius = 8.0
+        return imageView
+    }()
+    
+    lazy var vipImageView: UIImageView = {
+        let vipImageView = UIImageView.createImageView(imageName: "ai_emo_style_vip")
+        vipImageView.isHidden = true
+        return vipImageView
+    }()
+    
+    lazy var boardImageView: UIImageView = {
+        let boardImageView = UIImageView.createImageView(imageName: "ai_emo_selected_border")
+        boardImageView.isHidden = true
+        return boardImageView
+    }()
+
+    
+    lazy var textLabel: UILabel = {
+        let textLabel = UILabel.createLabel(font: .font(size: 10,weight: .medium),textColor: .white,textAlignment: .center,numberOfLines: 0)
+        return textLabel
+    }()
+    
+    override func creatUI() {
+        //cell 100*110
+   
+        bgContentView.addSubview(imageView)
+        imageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(60)
+            make.height.equalTo(80)
+        }
+        
+        imageView.addSubview(vipImageView)
+        vipImageView.snp.makeConstraints { make in
+            make.trailing.equalTo(0)
+            make.top.equalTo(0.0)
+            make.width.equalTo(18)
+            make.height.equalTo(14)
+        }
+        
+        imageView.addSubview(boardImageView)
+        boardImageView.snp.makeConstraints { make in
+            make.top.bottom.leading.trailing.equalTo(0)
+        }
+ 
+        bgContentView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.equalTo(imageView.snp.bottom).offset(4)
+            make.centerX.equalToSuperview()
+        }
+    }
+    
+}
+

+ 234 - 0
AIEmoji/Business/TSAILIstVC/TSAIChangeEmoteVC/ViewModel/TSAIChangeEmoteVM.swift

@@ -0,0 +1,234 @@
+//
+//  TSAIChangeEmoteVM.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/10.
+//
+
+import ObjectMapper
+import Alamofire
+
+class TSAIChangeEmoteVM {
+    
+
+    //###################################### 样式选择 ######################################
+    var selectedStyleIndex:Int = 0
+    lazy var selectStyleModels: [TSGenerateStyleModel] = {
+        var selectStyleModels = [TSGenerateStyleModel]()
+        if let dataArray = Mapper<TSGenerateStyleModel>().mapArray(JSONfile: "ai_change_emote_style.json"){
+            selectStyleModels = dataArray
+            
+            if let model = dataArray.safeObj(At: selectedStyleIndex) {
+                selectStyleModel = model //加上默认的选择
+            }
+        }
+        
+        return selectStyleModels
+    }()
+    
+    var selectStyleModel:TSGenerateStyleModel?
+    
+
+    
+    //###################################### 生成图片 ######################################
+    var uploadRequest:Request?
+    var creatRequest:Request?
+    var queryRequest:Request?
+    var stopNetwork = false
+   
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
+    var aiText:String = ""
+    var generatingProgress = 0
+    
+    var upLoadImage:UIImage?{
+        didSet{
+            imageUrl = nil
+            for model in selectStyleModels {
+                model.actionInfoModel  = nil
+            }
+        }
+    }
+    var imageUrl:String?
+
+}
+
+extension TSAIChangeEmoteVM {
+    
+    func creatImage() {
+        guard let imageUrl = imageUrl else { return }
+        guard let selectStyleModel = selectStyleModel else { return }
+        
+        generatingProgress = 0
+        stopNetwork = false
+        stateDatauPblished = (.start,nil)
+        stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
+        
+        let postDict = ["emotionType":selectStyleModel.style,
+                        "imageUrl":imageUrl,
+                        "device":getUserInfoJsonString()]
+        
+        creatRequest = TSNetworkShared.post(urlType: .changeEmotion,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 = TSActionInfoModel(JSON: result) {
+                    switch genmojiModel.actionStatus {
+                    case .success:
+                        if let url = URL(string:genmojiModel.response.resultUrl) {
+                            UIImageView.downloadImageWithProgress(url: url) { [weak self]  progress in
+                                guard let self = self else { return }
+                        
+                                let progressInt = Int(progress*10.0)
+                                let progressString = "Generating".localized + " \(90 + progressInt)%"
+                                stateDatauPblished = (.progressString(progressString),nil)
+                                dePrint("生成后图片下载进度 \(progress)")
+                            } completion: {[weak self] image in
+                                guard let self = self else { return }
+                                self.stateDatauPblished = (.success(nil),genmojiModel)
+                                self.selectStyleModel?.actionInfoModel = genmojiModel
+                                generatingProgress = 0
+                            }
+
+                        }else{
+                            self.stateDatauPblished = (.success(nil),genmojiModel)
+                            self.selectStyleModel?.actionInfoModel = 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 {
+        let progress = progress*(0.9) // 预留 10% 进度给图片下载
+        //Generating 0%-100%
+        var progressInt = Int(progress*100)
+
+        if progressInt > 99 {
+            progressInt = 99
+        }
+        
+        generatingProgress = progressInt
+        return "Generating".localized + " \(progressInt)%"
+    }
+    
+    
+    func uploadAndCreatImage() {
+        
+        if let model = selectStyleModel?.actionInfoModel {
+            self.stateDatauPblished = (.success(nil),model)
+            return
+        }
+        
+        if let imageUrl = imageUrl,imageUrl.contains("http") {
+            creatImage()
+            return
+        }
+        
+        stopNetwork = false
+        stateDatauPblished = (.start,nil)
+        
+        stateDatauPblished = (.progressString(uploadingPhoto(progress: 0.0)),nil)
+        uploadImage { [weak self]  progress in
+            guard let self = self else { return }
+            if generatingProgress == 0 {
+                stateDatauPblished = (.progressString(uploadingPhoto(progress: progress)),nil)
+            }
+        } completion: { [weak self]  data, error in
+            guard let self = self else { return }
+            if let error = error {
+                imageUrl = nil
+                self.stateDatauPblished = (.failed(error.localizedDescription),nil)
+            }else{
+                if let string = data as? String {
+                    imageUrl = string
+                    creatImage()
+                }
+            }
+        }
+    }
+    
+    func uploadingPhoto(progress:Float) -> String {
+        //Uploading Photo 0%-100%
+        var progressInt = Int(progress*100)
+        if progressInt > 99 {
+            progressInt = 99
+        }
+        return "Uploading Photo".localized + " \(progressInt)%"
+    }
+    
+    func uploadImage(
+        progressHandler: @escaping (Float) -> Void, // 上传进度回调
+        completion: @escaping (Any?, Error?) -> Void)
+    {
+        guard let imageData = upLoadImage?.pngData() else { return }
+        stateDatauPblished = (.start,nil)
+        let dataArray = [
+            ["data": imageData,
+             "fieldName": "file", // 字段名
+             "fileName": "image.png", // 文件名
+             "mimeType": "image/png" // MIME 类型
+            ]
+        ]
+        
+        uploadRequest = TSNetworkShared.uploadData(
+            urlType: .upload,
+            dataArray: dataArray,
+            progressHandler: { progress in
+                progressHandler(progress)
+            },completion: { [weak self] result in
+            guard let self = self else { return }
+            switch result {
+            case .success(let data):
+                if let dataDict = data as? [String:Any] ,
+                   dataDict.safeInt(forKey: "code") == 200,
+                   let picUrl = dataDict["result"] as? String{
+                    completion(picUrl,nil)
+                }else{
+                    let error = NSError(domain: "Service exception", code: 0)
+                    completion(nil,error)
+                }
+            case .failure(let error):
+                completion(nil,error)
+            }
+        })
+    }
+    
+}

+ 3 - 3
AIEmoji/Business/TSAILIstVC/TSAILIstVC/TSAILIstVC.swift

@@ -53,12 +53,12 @@ class TSAILIstVC: TSBaseVC {
         sectionModel.addSubItemModel(
             createItemModel(
                 leftImageName:"aiList_emote",
-                leftTitle: "Change expression".localized,
-                leftSubTitle: "AI helps you Change expression".localized,
+                leftTitle: "Change Emotion".localized,
+                leftSubTitle: "Change your facial emotion in one click".localized,
                 rightViewStyle: 0,
                 tapBlock: { [weak self] model, _, _ in
                    guard let self = self else { return }
-                    let baseVc = TSAIUploadPhotoBaseVC(titleString: model.leftTitle ?? "", generatorStyle: .ageChild)
+                    let baseVc = TSAIChangeEmoteVC()
                     kPushVC(target: self, modelVC: baseVc)
                                 
         }))

+ 1 - 1
AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVC.swift

@@ -53,7 +53,7 @@ class TSAIListHistoryBaseVC: TSBaseVC {
             guard let self = self else { return }
  
             if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
-                var dataModelArray:[TSGenmojiModel] = []
+                var dataModelArray:[TSActionInfoModel] = []
                 for itemModel in sections.items {
                     dataModelArray.append(itemModel.dataModel)
                 }

+ 1 - 1
AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVM.swift

@@ -52,7 +52,7 @@ class TSAIListHistoryBaseVM {
 }
  
 extension TSAIListHistoryBaseVM {
-    var listModelArray:[TSGenmojiModel]{
+    var listModelArray:[TSActionInfoModel]{
         switch generatorStyle {
         case .ageOld:
             TSChangeOldAgeHistory.shared.listModels

+ 8 - 10
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift

@@ -7,8 +7,8 @@
 
 class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
     
-    var imageModel:TSGenmojiModel?
-    var complete:((TSGenmojiModel)->Void)
+    var imageModel:TSActionInfoModel?
+    var complete:((TSActionInfoModel)->Void)
     
 //    var prompt:String
 //    var promptSort:String
@@ -19,7 +19,7 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
     var generatorStyle:TSGeneratorImageStyle
     
     var progressState = TSProgressState.none
-//    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSGenmojiModel)->Void)) {
+//    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSActionInfoModel)->Void)) {
 //        self.prompt = prompt
 //        self.promptSort = promptSort
 //        self.imageUrl = imageUrl
@@ -32,7 +32,7 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
 //    }
     
     
-    init(upLoadImage:UIImage,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSGenmojiModel)->Void)) {
+    init(upLoadImage:UIImage,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSActionInfoModel)->Void)) {
         self.upLoadImage = upLoadImage
         self.generatorStyle = generatorStyle
         self.complete = complete
@@ -75,7 +75,7 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
         
         super.createView()
         
-        //关闭按钮
+
         contentView.addSubview(switchOriginalPictureBtn)
         switchOriginalPictureBtn.snp.makeConstraints { make in
             make.bottom.equalTo(-k_Height_safeAreaInsetsBottom() - 76)
@@ -123,9 +123,7 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
     //重新生成
     @objc override func clickRegenerateBtn(){
         //判断 vip
-        if kJudgeVip(externalBool: kPurchaseDefault.freeNumAvailable(type: .picToPic) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
+        if kJudgeVip(externalBool: kPurchaseDefault.freeNumAvailable(type: .picToPic) == false, vc: self){ return }
         
         viewModel.uploadAndCreatImage()
     }
@@ -166,7 +164,7 @@ extension TSAIListPhotoGeneratorBaseVC {
 }
 extension TSAIListPhotoGeneratorBaseVC {
     
-    func upDateView(state:TSProgressState,model:TSGenmojiModel?){
+    func upDateView(state:TSProgressState,model:TSActionInfoModel?){
         progressState = state
         switch state {
             case .failed(let errorStr):
@@ -221,7 +219,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         switchOriginalPictureBtn.isHidden = true
     }
     
-    func showSuccess(model:TSGenmojiModel){
+    func showSuccess(model:TSActionInfoModel){
         generateInView.isHidden = true
         generateInView.isRotating = false
 

+ 4 - 4
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift

@@ -14,7 +14,7 @@ class TSAIListPhotoGeneratorBaseVM {
     var queryRequest:Request?
     var stopNetwork = false
     
-    @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
     var generatingProgress = 0
     
 //    var prompt:String
@@ -58,7 +58,7 @@ class TSAIListPhotoGeneratorBaseVM {
 //
 //        kDelayOnMainThread(2.0) {
 //            if kRandomBool() {
-//                let infoModel = TSGenmojiModel(JSON:actionInfoDictPoster )
+//                let infoModel = TSActionInfoModel(JSON:actionInfoDictPoster )
 //                self.stateDatauPblished = (.success(nil),infoModel)
 //            }else{
 //                self.stateDatauPblished = (.failed("error?.localizedDescription"),nil)
@@ -104,7 +104,7 @@ class TSAIListPhotoGeneratorBaseVM {
         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 = TSGenmojiModel(JSON: result) {
+                if let genmojiModel = TSActionInfoModel(JSON: result) {
                     switch genmojiModel.actionStatus {
                     case .success:
                         if let url = URL(string:genmojiModel.response.resultUrl) {
@@ -114,7 +114,7 @@ class TSAIListPhotoGeneratorBaseVM {
                                 let progressInt = Int(progress*10.0)
                                 let progressString = "Generating".localized + " \(90 + progressInt)%"
                                 stateDatauPblished = (.progressString(progressString),nil)
-                                dePrint("当前进度: \(progress)")
+                                dePrint("生成后图片下载进度: \(progress)")
                             } completion: {[weak self] image in
                                 guard let self = self else { return }
                                 self.stateDatauPblished = (.success(nil),genmojiModel)

+ 9 - 5
AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift

@@ -290,9 +290,13 @@ extension TSAIUploadPhotoBaseVC {
     }
     
     func pickSinglePhoto()  {
-        photoPickerManager.pickSinglePhoto { [weak self] image,phAsset in
+        photoPickerManager.pickSinglePhoto(maxBitSize: kUploadImageMaxBitSize) { [weak self] image, errorString in
             guard let self = self else { return }
-            handleSinglePhoto(image: image, phAsset: phAsset)
+            if let errorString = errorString {
+                TSToastShared.showToast(text: errorString)
+            }else{
+                upLoadImage = image
+            }
         }
     }
     
@@ -322,9 +326,9 @@ extension TSAIUploadPhotoBaseVC {
     }
     func presentModalHintVC(){
         let vc = TSAIAgeImageHintVC()
-        vc.clickUpImageHandle = { [weak self] image,phAsset in
+        vc.clickUpImageHandle = { [weak self] image in
             guard let self = self else { return }
-            handleSinglePhoto(image: image, phAsset: phAsset)
+            upLoadImage = image
         }
         kPresentModalVC(target: self, modelVC: vc,transitionStyle: .crossDissolve)
     }
@@ -351,7 +355,7 @@ extension TSAIUploadPhotoBaseVC {
         kPresentModalVC(target: self, modelVC: gennerateVC,transitionStyle: .crossDissolve)
     }
     
-    func saveModel(model:TSGenmojiModel){
+    func saveModel(model:TSActionInfoModel){
         switch generatorStyle {
         case .ageOld:
             TSChangeOldAgeHistory.shared.saveModel(model: model)

+ 2 - 2
AIEmoji/Business/TSEmojisVC/TSEmojisChildVC/TSEmojisChildVC.swift

@@ -41,9 +41,9 @@ class TSEmojisChildVC: TSBaseVC {
             guard let self = self else { return }
             
             if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSEmojisColSectionModel{
-                var dataModelArray:[TSGenmojiModel] = []
+                var dataModelArray:[TSActionInfoModel] = []
                 for itemModel in sections.items {
-                    let model = TSGenmojiModel()
+                    let model = TSActionInfoModel()
                     model.response.resultUrl = itemModel.dataModel.imageUrl
                     model.response.vip = itemModel.dataModel.vip
                     dataModelArray.append(model)

+ 5 - 5
AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateVC.swift

@@ -7,11 +7,11 @@
 
 class TSGenmojiGennerateVC: TSBottomAlertVC {
     
-    var imageModel:TSGenmojiModel?
-    var complete:((TSGenmojiModel)->Void)
+    var imageModel:TSActionInfoModel?
+    var complete:((TSActionInfoModel)->Void)
     var progressState = TSProgressState.none
     var aiText:String
-    init(aiText: String,complete:@escaping ((TSGenmojiModel)->Void)) {
+    init(aiText: String,complete:@escaping ((TSActionInfoModel)->Void)) {
         self.aiText = aiText
         self.complete = complete
         super.init()
@@ -126,7 +126,7 @@ extension TSGenmojiGennerateVC {
     
 }
 extension TSGenmojiGennerateVC {
-    func upDateView(state:TSProgressState,model:TSGenmojiModel?){
+    func upDateView(state:TSProgressState,model:TSActionInfoModel?){
         progressState = state
         switch state {
             case .failed(let errorStr):
@@ -188,7 +188,7 @@ extension TSGenmojiGennerateVC {
         isClickTheBlankClosePage = true
     }
     
-    func showSuccess(model:TSGenmojiModel){
+    func showSuccess(model:TSActionInfoModel){
         generateInView.isHidden = true
         generateInView.isRotating = false
         submitBtn.isHidden = true

+ 2 - 2
AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateViewModel.swift

@@ -101,7 +101,7 @@ class TSGenmojiGennerateViewModel {
     var queryRequest:Request?
     var stopNetwork = false
     
-    @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
     var aiText:String = ""
     var generatingProgress = 0
     func creatImageEmoji(text:String) {
@@ -129,7 +129,7 @@ class TSGenmojiGennerateViewModel {
         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 = TSGenmojiModel(JSON: result) {
+                if let genmojiModel = TSActionInfoModel(JSON: result) {
                     switch genmojiModel.actionStatus {
                     case .success:
                         TSToastShared.hideLoading()

+ 2 - 2
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/Model/TSGenmojiModel.swift

@@ -1,12 +1,12 @@
 //
-//  TSGenmojiModel.swift
+//  TSActionInfoModel.swift
 //  AIEmoji
 //
 //  Created by 100Years on 2025/1/16.
 //
 
 import ObjectMapper
-class TSGenmojiModel: TSBaseModel {
+class TSActionInfoModel: TSBaseModel {
     
     enum ModelType:Int {
         case normal

+ 1 - 1
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/TSGenmojiVC.swift

@@ -48,7 +48,7 @@ class TSGenmojiVC: TSBaseVC {
             }
             
             if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
-                var dataModelArray:[TSGenmojiModel] = []
+                var dataModelArray:[TSActionInfoModel] = []
                 for itemModel in sections.items {
                     dataModelArray.append(itemModel.dataModel)
                 }

+ 2 - 2
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift

@@ -196,9 +196,9 @@ class TSGenmojiCoLItemModel: TSBaseModel {
     var style:TSGenmojiCoLStyple = .generate
     
     // 主要是给历史记录使用的
-    var dataModel:TSGenmojiModel = TSGenmojiModel()
+    var dataModel:TSActionInfoModel = TSActionInfoModel()
     //给图生图选择样式使用
-    var ptpStyleModels:[TSPTPStyleModel] = []
+    var ptpStyleModels:[TSGenerateStyleModel] = []
     
     override func mapping(map: ObjectMapper.Map) {
         dataModel           <- map["dataModel"]

+ 5 - 5
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiViewModel.swift

@@ -23,8 +23,8 @@ class TSGenmojiViewModel {
     private var enmojiHistoryListString: String
     
     
-    lazy var listModelArray: [TSGenmojiModel] = {
-        if let listModelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: enmojiHistoryListString){
+    lazy var listModelArray: [TSActionInfoModel] = {
+        if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: enmojiHistoryListString){
             return listModelArray
         }
         return []
@@ -61,13 +61,13 @@ class TSGenmojiViewModel {
  
 extension TSGenmojiViewModel {
     //历史记录
-    var modelArray:[TSGenmojiModel]{
+    var modelArray:[TSActionInfoModel]{
         get{
             let sectionModel = TSGenmojiCoLSectionModel()
             sectionModel.style = .history
             sectionModel.name = "History".localized
         
-            if let modelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: enmojiHistoryListString){
+            if let modelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: enmojiHistoryListString){
                 return modelArray
             }
             return []
@@ -80,7 +80,7 @@ extension TSGenmojiViewModel {
     }
     
     //返回值,是否需要清空后刷新
-    func saveModel(model:TSGenmojiModel)->Bool{
+    func saveModel(model:TSActionInfoModel)->Bool{
         listModelArray.insert(model, at: 0)
         if let jsonString = listModelArray.toJSONString() {
             enmojiHistoryListString = jsonString

+ 3 - 3
AIEmoji/Business/TSPTPGeneratorVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoBrowseVC.swift

@@ -8,7 +8,7 @@
 private let cellId = "TSAIPhotoBrowseCell"
 class TSAIPhotoBrowseVC: TSBaseVC {
 
-    var dataModelArray = [TSGenmojiModel]()
+    var dataModelArray = [TSActionInfoModel]()
     var currentImage:UIImage?{
         let cell = collectionView.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? TSAIPhotoBrowseCell
         var image = cell?.netWorkImageView.image
@@ -16,7 +16,7 @@ class TSAIPhotoBrowseVC: TSBaseVC {
         return image
     }
 
-    var currentModel:TSGenmojiModel?{
+    var currentModel:TSActionInfoModel?{
         if let model = dataModelArray.safeObj(At: currentIndex){
             return model
         }
@@ -297,7 +297,7 @@ class TSAIPhotoBrowseCell : TSBaseCollectionCell{
         
     }
     
-    var model:TSGenmojiModel = TSGenmojiModel(){
+    var model:TSActionInfoModel = TSActionInfoModel(){
         didSet{
             dePrint("TSAIPhotoBrowseCell didSet model")
             if model.modelType == .example {

+ 2 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPTPBrowseVC/TSPTPBrowseVC.swift

@@ -9,7 +9,7 @@ private let cellId = "TSPTPBrowseCell"
 class TSPTPBrowseVC: TSBottomAlertVC {
 
     
-    var dataModelArray = [TSGenmojiModel]()
+    var dataModelArray = [TSActionInfoModel]()
     var currentImage:UIImage?{
         let cell = collectionView.cellForItem(at: IndexPath(item: currentIndex, section: 0)) as? TSPTPBrowseCell
         var image = cell?.netWorkImageView.image
@@ -17,7 +17,7 @@ class TSPTPBrowseVC: TSBottomAlertVC {
         return image
     }
 
-    var currentModel:TSGenmojiModel?{
+    var currentModel:TSActionInfoModel?{
         if let model = dataModelArray.safeObj(At: currentIndex){
             return model
         }

+ 5 - 5
AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/TSPTPGeneratorVC.swift

@@ -7,8 +7,8 @@
 
 class TSPTPGeneratorVC: TSAIPhotoGeneratorBaseVC {
     
-    var imageModel:TSGenmojiModel?
-    var complete:((TSGenmojiModel)->Void)
+    var imageModel:TSActionInfoModel?
+    var complete:((TSActionInfoModel)->Void)
     
     var prompt:String
     var promptSort:String
@@ -16,7 +16,7 @@ class TSPTPGeneratorVC: TSAIPhotoGeneratorBaseVC {
     var upLoadImage:UIImage
     var style:String
     var progressState = TSProgressState.none
-    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,complete:@escaping ((TSGenmojiModel)->Void)) {
+    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,complete:@escaping ((TSActionInfoModel)->Void)) {
         self.prompt = prompt
         self.promptSort = promptSort
         self.imageUrl = imageUrl
@@ -130,7 +130,7 @@ extension TSPTPGeneratorVC {
 }
 extension TSPTPGeneratorVC {
     
-    func upDateView(state:TSProgressState,model:TSGenmojiModel?){
+    func upDateView(state:TSProgressState,model:TSActionInfoModel?){
         progressState = state
         switch state {
             case .failed(let errorStr):
@@ -182,7 +182,7 @@ extension TSPTPGeneratorVC {
         netWorkImageView.isHidden = true
     }
     
-    func showSuccess(model:TSGenmojiModel){
+    func showSuccess(model:TSActionInfoModel){
         generateInView.isHidden = true
         generateInView.isRotating = false
 

+ 4 - 4
AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/VM/TSPTPGeneratorVM.swift

@@ -39,7 +39,7 @@ class TSPTPGeneratorVM {
     var queryRequest:Request?
     var stopNetwork = false
     
-    @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
    
     var prompt:String
     var imageUrl:String?
@@ -73,7 +73,7 @@ class TSPTPGeneratorVM {
 //
 //        kDelayOnMainThread(2.0) {
 //            if kRandomBool() {
-//                let infoModel = TSGenmojiModel(JSON:actionInfoDictPoster )
+//                let infoModel = TSActionInfoModel(JSON:actionInfoDictPoster )
 //                self.stateDatauPblished = (.success(nil),infoModel)
 //            }else{
 //                self.stateDatauPblished = (.failed("error?.localizedDescription"),nil)
@@ -112,7 +112,7 @@ class TSPTPGeneratorVM {
         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 = TSGenmojiModel(JSON: result) {
+                if let genmojiModel = TSActionInfoModel(JSON: result) {
                     switch genmojiModel.actionStatus {
                     case .success:
                         if let url = URL(string:genmojiModel.response.resultUrl) {
@@ -122,7 +122,7 @@ class TSPTPGeneratorVM {
                                 let progressInt = Int(progress*10.0)
                                 let progressString = "Generating".localized + " \(90 + progressInt)%"
                                 stateDatauPblished = (.progressString(progressString),nil)
-                                dePrint("当前进度: \(progress)")
+                                dePrint("生成后图片下载进度 \(progress)")
                             } completion: {[weak self] image in
                                 guard let self = self else { return }
                                 self.stateDatauPblished = (.success(nil),genmojiModel)

+ 7 - 29
AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/TSPTPInputVC.swift

@@ -160,32 +160,10 @@ class TSPTPInputVC: TSBaseVC {
     
     
     func pickSinglePhoto()  {
-        photoPickerManager.pickSinglePhoto { [weak self] image,phAsset in
+        photoPickerManager.pickSinglePhoto(maxBitSize: kUploadImageMaxBitSize) { [weak self] image, errorString in
             guard let self = self else { return }
-            handleSinglePhoto(image: image, phAsset: phAsset)
-        }
-    }
-    
-    func handleSinglePhoto(image:UIImage?,phAsset:PHAsset?){
-        let maxSize = 10 * 1024 * 1024
-        
-        if let image = image,let phAsset = phAsset {
-            // 方法2:异步获取详细大小(不阻塞主线程)
-            TSPhotoSizeHelper.getImageFileSizeAsync(asset: phAsset) {[weak self] size in
-                guard let self = self else { return }
-                
-                let mbSize = Double(size) / (1024 * 1024)
-                print("精确大小: \(mbSize) MB,size = \(size)")
-                if size > maxSize {
-                    TSToastShared.showToast(text: "Photo must be smaller than 10MB.".localized)
-                }else{
-                    viewModel.upLoadImage = image
-                    uploadView.upLoadImage = image
-                }
-            }
-        }else if let image = image {
-            if image.isLargerThan(byteSize: maxSize) {
-                TSToastShared.showToast(text: "Photo must be smaller than 10MB.".localized)
+            if let errorString = errorString {
+                TSToastShared.showToast(text: errorString)
             }else{
                 viewModel.upLoadImage = image
                 uploadView.upLoadImage = image
@@ -193,7 +171,6 @@ class TSPTPInputVC: TSBaseVC {
         }
     }
     
-    
     //###################################### 选择风格 ######################################
     lazy var selectStyleView: TSPTPSelectStyleView = {
         let selectStyleView = TSPTPSelectStyleView()
@@ -297,7 +274,7 @@ class TSPTPInputVC: TSBaseVC {
             guard let self = self else { return }
  
             if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
-                var dataModelArray:[TSGenmojiModel] = []
+                var dataModelArray:[TSActionInfoModel] = []
                 for itemModel in sections.items {
                     dataModelArray.append(itemModel.dataModel)
                 }
@@ -432,9 +409,10 @@ extension TSPTPInputVC {
     
     func presentModalHintVC(){
         let vc = TSAIAgeImageHintVC()
-        vc.clickUpImageHandle = { [weak self] image,phAsset in
+        vc.clickUpImageHandle = { [weak self] image in
             guard let self = self else { return }
-            handleSinglePhoto(image: image, phAsset: phAsset)
+            viewModel.upLoadImage = image
+            uploadView.upLoadImage = image
         }
         kPresentModalVC(target: self, modelVC: vc,transitionStyle: .crossDissolve)
     }

+ 13 - 13
AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/VM/TSPTPInputVM.swift

@@ -14,8 +14,8 @@ class TSPTPInputVM {
     var uploadRequest:Request?
 
     //上传图片模型,用于上传图片参数的传递
-    private var updateImageModel: TSPTPStyleModel = {
-        var updateImageModel = TSPTPStyleModel()
+    private var updateImageModel: TSGenerateStyleModel = {
+        var updateImageModel = TSGenerateStyleModel()
         return updateImageModel
     }()
     
@@ -28,7 +28,7 @@ class TSPTPInputVM {
         }
     }
     
-    var selectedPTPStyleModel:TSPTPStyleModel?{
+    var selectedPTPStyleModel:TSGenerateStyleModel?{
         didSet{
             isCanGennerateBlock?(isCanGennerate)
         }
@@ -37,9 +37,9 @@ class TSPTPInputVM {
     var selectedStyleIndex:Int = 0
     
     //选择类型组
-    lazy var ptpStyleModels: [TSPTPStyleModel] = {
-        var ptpStyleModels = [TSPTPStyleModel]()
-        if let dataArray = Mapper<TSPTPStyleModel>().mapArray(JSONfile: "photo_to_photo_style.json"){
+    lazy var ptpStyleModels: [TSGenerateStyleModel] = {
+        var ptpStyleModels = [TSGenerateStyleModel]()
+        if let dataArray = Mapper<TSGenerateStyleModel>().mapArray(JSONfile: "photo_to_photo_style.json"){
             ptpStyleModels = dataArray
             
             if let model = dataArray.safeObj(At: selectedStyleIndex) {
@@ -54,8 +54,8 @@ class TSPTPInputVM {
     private var historyListString: String
     
     
-    lazy var listModelArray: [TSGenmojiModel] = {
-        if let listModelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: historyListString){
+    lazy var listModelArray: [TSActionInfoModel] = {
+        if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyListString){
             return listModelArray
         }
         return []
@@ -103,8 +103,8 @@ class TSPTPInputVM {
         }
     }
     
-    func createExampleModel(imageName:String)->TSGenmojiModel{
-        let model = TSGenmojiModel()
+    func createExampleModel(imageName:String)->TSActionInfoModel{
+        let model = TSActionInfoModel()
         model.modelType = .example
         model.request.prompt = "Example"
         model.request.promptSort = "Example"
@@ -126,9 +126,9 @@ class TSPTPInputVM {
  
 extension TSPTPInputVM {
     //历史记录
-    var modelArray:[TSGenmojiModel]{
+    var modelArray:[TSActionInfoModel]{
         get{
-            if let modelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: historyListString){
+            if let modelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyListString){
                 return modelArray
             }
             return []
@@ -141,7 +141,7 @@ extension TSPTPInputVM {
     }
     
     //返回值,是否需要清空后刷新
-    func saveModel(model:TSGenmojiModel)->Bool{
+    func saveModel(model:TSActionInfoModel)->Bool{
         listModelArray.insert(model, at: 0)
         if let jsonString = listModelArray.toJSONString() {
             historyListString = jsonString

+ 2 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/View/TSPTPSelectStyleView.swift

@@ -7,7 +7,7 @@
 
 class TSPTPSelectStyleView : TSBaseView{
     var viewH: CGFloat = 110.0
-    var dataArray: [TSPTPStyleModel] = [TSPTPStyleModel](){
+    var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
         didSet{
             styleCollectionView.reloadData()
             
@@ -19,7 +19,7 @@ class TSPTPSelectStyleView : TSBaseView{
         }
     }
     
-    var clickHandle:((TSPTPStyleModel)->Void)?
+    var clickHandle:((TSGenerateStyleModel)->Void)?
     lazy var layout: UICollectionViewFlowLayout = {
         let layout = UICollectionViewFlowLayout()
         layout.scrollDirection = .horizontal

+ 2 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/Cell/TSPTPSelectStyleCell.swift

@@ -6,7 +6,7 @@
 //
 
 class TSPTPSelectStyleCell : TSBaseCollectionCell{
-    var dataArray: [TSPTPStyleModel] = [TSPTPStyleModel](){
+    var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
         didSet{
             styleCollectionView.reloadData()
         }
@@ -101,7 +101,7 @@ class TSPTPSelectStyleCCell: TSBaseCollectionCell {
         }
     }
     
-    var itemModel:TSPTPStyleModel = TSPTPStyleModel(){
+    var itemModel:TSGenerateStyleModel = TSGenerateStyleModel(){
         didSet{
             imageView.image = UIImage(named: itemModel.imageName)
             

+ 8 - 3
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/M/TSPTPStyleModel.swift

@@ -1,5 +1,5 @@
 //
-//  TSPTPStyleModel.swift
+//  TSGenerateStyleModel.swift
 //  AIEmoji
 //
 //  Created by 100Years on 2025/2/25.
@@ -8,13 +8,14 @@
 
 import ObjectMapper
 
-class TSPTPStyleModel: TSBaseModel {
+class TSGenerateStyleModel: TSBaseModel {
     var image:UIImage?//给上传图片用的,非模型使用
     var imageName:String = ""
     var imageText:String = ""
     var prompt:String = ""
     var isVip:Bool = false
-    var specialStyle:Int = 0 //0 普通类型,1 热门类型,2 新类型
+    var specialStyle:Int = 0 //0 普通类型,1 热门类型,2 新类型,3 点击更换图片 4.原图
+    var clickType:Int = 0 //0 无响应, 1空类型 2.换图
     var style:String = ""
     override func mapping(map: ObjectMapper.Map) {
         imageName               <- map["imageName"]
@@ -22,7 +23,11 @@ class TSPTPStyleModel: TSBaseModel {
         prompt                  <- map["prompt"]
         isVip                   <- map["isVip"]
         specialStyle            <- map["specialStyle"]
+        clickType               <- map["clickType"]
         style                   <- map["style"]
     }
+    
+    var actionInfoModel:TSActionInfoModel? //对应生成的结果
+    var isSelected: Bool = false
 }
 

+ 2 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/TSPhotoToPhotoVC.swift

@@ -168,7 +168,7 @@ class TSPhotoToPhotoVC: TSBaseVC {
                         }
                     }
                 }
-            }else if let model = cellCp as? TSPTPStyleModel ,indexPath == IndexPath(item: 0, section: 1) {
+            }else if let model = cellCp as? TSGenerateStyleModel ,indexPath == IndexPath(item: 0, section: 1) {
                 //选择了某个样式
                 viewModel.selectedPTPStyleModel = model
                 updateVipView()
@@ -194,7 +194,7 @@ class TSPhotoToPhotoVC: TSBaseVC {
             }
             
             if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
-                var dataModelArray:[TSGenmojiModel] = []
+                var dataModelArray:[TSActionInfoModel] = []
                 for itemModel in sections.items {
                     dataModelArray.append(itemModel.dataModel)
                 }

+ 14 - 14
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/VM/TSPhotoToPhotoVM.swift

@@ -11,12 +11,12 @@ class TSPhotoToPhotoVM {
     var colDataArray:[TSComponent] = [TSComponent]()
     
     var uploadRequest:Request?
-    @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
    
 
     //上传图片模型,用于上传图片参数的传递
-    private var updateImageModel: TSPTPStyleModel = {
-        var updateImageModel = TSPTPStyleModel()
+    private var updateImageModel: TSGenerateStyleModel = {
+        var updateImageModel = TSGenerateStyleModel()
         return updateImageModel
     }()
     
@@ -29,16 +29,16 @@ class TSPhotoToPhotoVM {
         }
     }
     
-    var selectedPTPStyleModel:TSPTPStyleModel?{
+    var selectedPTPStyleModel:TSGenerateStyleModel?{
         didSet{
             isCanGennerateBlock?(isCanGennerate)
         }
     }
     
     //选择类型组
-    lazy var ptpStyleModels: [TSPTPStyleModel] = {
-        var ptpStyleModels = [TSPTPStyleModel]()
-        if let dataArray = Mapper<TSPTPStyleModel>().mapArray(JSONfile: "photo_to_photo_style.json"){
+    lazy var ptpStyleModels: [TSGenerateStyleModel] = {
+        var ptpStyleModels = [TSGenerateStyleModel]()
+        if let dataArray = Mapper<TSGenerateStyleModel>().mapArray(JSONfile: "photo_to_photo_style.json"){
             ptpStyleModels = dataArray
             
             if let model = dataArray.first {
@@ -53,8 +53,8 @@ class TSPhotoToPhotoVM {
     private var historyListString: String
     
     
-    lazy var listModelArray: [TSGenmojiModel] = {
-        if let listModelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: historyListString){
+    lazy var listModelArray: [TSActionInfoModel] = {
+        if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyListString){
             return listModelArray
         }
         return []
@@ -128,8 +128,8 @@ class TSPhotoToPhotoVM {
         }
     }
     
-    func createExampleModel(imageName:String)->TSGenmojiModel{
-        let model = TSGenmojiModel()
+    func createExampleModel(imageName:String)->TSActionInfoModel{
+        let model = TSActionInfoModel()
         model.modelType = .example
         model.request.prompt = "Example"
         model.request.promptSort = "Example"
@@ -153,9 +153,9 @@ class TSPhotoToPhotoVM {
  
 extension TSPhotoToPhotoVM {
     //历史记录
-    var modelArray:[TSGenmojiModel]{
+    var modelArray:[TSActionInfoModel]{
         get{
-            if let modelArray = Mapper<TSGenmojiModel>().mapArray(JSONString: historyListString){
+            if let modelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyListString){
                 return modelArray
             }
             return []
@@ -168,7 +168,7 @@ extension TSPhotoToPhotoVM {
     }
     
     //返回值,是否需要清空后刷新
-    func saveModel(model:TSGenmojiModel)->Bool{
+    func saveModel(model:TSActionInfoModel)->Bool{
         listModelArray.insert(model, at: 0)
         if let jsonString = listModelArray.toJSONString() {
             historyListString = jsonString

+ 1 - 7
AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift

@@ -288,14 +288,9 @@ class TSPurchaseVC: TSBaseVC {
     }
 }
 
-
-
-
-
-
 func kJudgeVip(externalBool:Bool,
                vc:UIViewController,
-               closePageBlock:(()->Void)?) -> Bool {
+               closePageBlock:(()->Void)? = nil) -> Bool {
     //判断 vip
     if externalBool,
        PurchaseManager.default.isVip == false
@@ -306,7 +301,6 @@ func kJudgeVip(externalBool:Bool,
     return false
 }
 
-
 extension TSPurchaseVC{
     
     static func show(target:UIViewController,closePageBlock:(()->Void)?){

+ 5 - 5
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/VM/TSTTPInputVM.swift

@@ -23,9 +23,9 @@ let kRandomTextToRintone:[String] = [
 class TSTTPInputVM {
     var selectedStyleIndex:Int = 0
     //选择 prompt 类型组
-    lazy var ptpStyleModels: [TSPTPStyleModel] = {
-        var ptpStyleModels = [TSPTPStyleModel]()
-        if let dataArray = Mapper<TSPTPStyleModel>().mapArray(JSONfile: "text_to_photo_style.json"){
+    lazy var ptpStyleModels: [TSGenerateStyleModel] = {
+        var ptpStyleModels = [TSGenerateStyleModel]()
+        if let dataArray = Mapper<TSGenerateStyleModel>().mapArray(JSONfile: "text_to_photo_style.json"){
             ptpStyleModels = dataArray
             
             if let model = dataArray.safeObj(At: selectedStyleIndex) {
@@ -45,7 +45,7 @@ class TSTTPInputVM {
     
 
     //选择的 prompt 类型
-    var selectPromptModel:TSPTPStyleModel?{
+    var selectPromptModel:TSGenerateStyleModel?{
         didSet{
             isCanGennerateBlock?(isCanGennerate)
         }
@@ -77,7 +77,7 @@ extension TSTTPInputVM {
         return prompt
     }
 
-    func saveModel(model:TSGenmojiModel){
+    func saveModel(model:TSActionInfoModel){
         TSTextToPicHistory.saveModel(model: model)
     }
 }

+ 3 - 3
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSTTPStyleView.swift

@@ -7,9 +7,9 @@
 
 class TSTTPStyleView:TSBaseView {
     
-    var selectedValueBlock:((TSPTPStyleModel)->Void)?
+    var selectedValueBlock:((TSGenerateStyleModel)->Void)?
     
-    var dataArray: [TSPTPStyleModel] = [TSPTPStyleModel](){
+    var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
         didSet{
             styleCollectionView.reloadData()
             if dataArray.count > 0 {
@@ -116,7 +116,7 @@ class TSPromptStyleViewCell: TSBaseCollectionCell {
         }
     }
     
-    var itemModel:TSPTPStyleModel = TSPTPStyleModel(){
+    var itemModel:TSGenerateStyleModel = TSGenerateStyleModel(){
         didSet{
             imageView.image = UIImage(named: itemModel.imageName)
     

+ 1 - 1
AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/TSTextGeneralPictureVC.swift

@@ -28,7 +28,7 @@ class TSTextGeneralPictureVC: TSBaseVC {
             guard let self = self else { return }
             if indexPath.section == 0{
                 if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
-                    var dataModelArray:[TSGenmojiModel] = []
+                    var dataModelArray:[TSActionInfoModel] = []
                     for itemModel in sections.items {
                         dataModelArray.append(itemModel.dataModel)
                     }

+ 2 - 2
AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/View/TSTTPSelectStyleCell.swift

@@ -6,7 +6,7 @@
 //
 
 class TSTTPSelectStyleCell : TSBaseCollectionCell{
-    var dataArray: [TSPTPStyleModel] = [TSPTPStyleModel](){
+    var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
         didSet{
             styleCollectionView.reloadData()
         }
@@ -100,7 +100,7 @@ class TSTTPSelectStyleCCell: TSBaseCollectionCell {
         }
     }
     
-    var itemModel:TSPTPStyleModel = TSPTPStyleModel(){
+    var itemModel:TSGenerateStyleModel = TSGenerateStyleModel(){
         didSet{
             imageView.image = UIImage(named: itemModel.imageName)
             textLabel.text = itemModel.imageText.localized

+ 5 - 5
AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVC.swift

@@ -7,12 +7,12 @@
 
 class TSTextPicGennerateVC: TSAIPhotoGeneratorBaseVC {
     
-    var imageModel:TSGenmojiModel?
-    var complete:((TSGenmojiModel)->Void)
+    var imageModel:TSActionInfoModel?
+    var complete:((TSActionInfoModel)->Void)
     var aiText:String
     var style:String
     var progressState = TSProgressState.none
-    init(aiText: String,style: String,complete:@escaping ((TSGenmojiModel)->Void)) {
+    init(aiText: String,style: String,complete:@escaping ((TSActionInfoModel)->Void)) {
         self.aiText = aiText
         self.style = style
         self.complete = complete
@@ -121,7 +121,7 @@ extension TSTextPicGennerateVC {
     
 }
 extension TSTextPicGennerateVC {
-    func upDateView(state:TSProgressState,model:TSGenmojiModel?){
+    func upDateView(state:TSProgressState,model:TSActionInfoModel?){
         progressState = state
         switch state {
             case .failed(let errorStr):
@@ -172,7 +172,7 @@ extension TSTextPicGennerateVC {
         netWorkImageView.isHidden = true
     }
     
-    func showSuccess(model:TSGenmojiModel){
+    func showSuccess(model:TSActionInfoModel){
         generateInView.isHidden = true
         generateInView.isRotating = false
 

+ 4 - 4
AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVM.swift

@@ -18,7 +18,7 @@ class TSTextPicGennerateVM {
     var queryRequest:Request?
     var stopNetwork = false
    
-    @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
+    @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
     var aiText:String = ""
     var generatingProgress = 0
     
@@ -43,7 +43,7 @@ class TSTextPicGennerateVM {
 //
 //        kDelayOnMainThread(2.0) {
 //            if kRandomBool() {
-//                let infoModel = TSGenmojiModel(JSON:actionInfoDictPoster )
+//                let infoModel = TSActionInfoModel(JSON:actionInfoDictPoster )
 //                self.stateDatauPblished = (.success(nil),infoModel)
 //            }else{
 //                self.stateDatauPblished = (.failed("error?.localizedDescription"),nil)
@@ -84,7 +84,7 @@ class TSTextPicGennerateVM {
         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 = TSGenmojiModel(JSON: result) {
+                if let genmojiModel = TSActionInfoModel(JSON: result) {
                     switch genmojiModel.actionStatus {
                     case .success:
                         if let url = URL(string:genmojiModel.response.resultUrl) {
@@ -94,7 +94,7 @@ class TSTextPicGennerateVM {
                                 let progressInt = Int(progress*10.0)
                                 let progressString = "Generating".localized + " \(90 + progressInt)%"
                                 stateDatauPblished = (.progressString(progressString),nil)
-                                dePrint("当前进度: \(progress)")
+                                dePrint("生成后图片下载进度 \(progress)")
                             } completion: {[weak self] image in
                                 guard let self = self else { return }
                                 self.stateDatauPblished = (.success(nil),genmojiModel)

+ 12 - 4
AIEmoji/Business/VIewTool/TSGeneratorloadingView.swift

@@ -39,9 +39,13 @@ class TSGeneratorloadingView: TSBaseView {
     
     private var targetView: UIView = UIView()
     
-    override func creatUI() {
-        
+    lazy var blurEffect: UIVisualEffectView = {
         let blurEffect = createBlurEffectView(style: .dark)
+        return blurEffect
+    }()
+    
+    override func creatUI() {
+
         contentView.addSubview(blurEffect)
         
         contentView.addSubview(imageView)
@@ -65,8 +69,7 @@ class TSGeneratorloadingView: TSBaseView {
             make.trailing.equalTo(-16)
         }
     }
-    
-    
+
     override func dealThings() {
         // 监听应用生命周期事件
         NotificationCenter.default.addObserver(
@@ -133,4 +136,9 @@ class TSGeneratorloadingView: TSBaseView {
     @objc private func handleAppWillEnterForeground() {
         isRotating = isRotating
     }
+    
+    func setBackgroundColor(color:UIColor){
+        blurEffect.removeFromSuperview()
+        contentView.backgroundColor = color
+    }
 }

+ 1 - 0
AIEmoji/Common/NetworkManager/TSNetWork/TSNetWork+Business.swift

@@ -22,6 +22,7 @@ enum TSNeURLType:String {
     
     case changeAge = "/api/image/change-age"       //换年龄
     case subscriptionApple = "/api/subscription/apple"       //苹果订阅
+    case changeEmotion = "/api/image/change-emotion"       //更换表情
     
     func getUrlString() -> String {
         return baseURL + self.rawValue

+ 3 - 3
AIEmoji/Common/Purchase/TSPurchaseManager.swift

@@ -143,9 +143,9 @@ public class PurchaseManager: NSObject {
     }
 
     @objc public var isVip: Bool {
-//        #if DEBUG
-//            return true
-//        #endif
+        #if DEBUG
+            return true
+        #endif
         guard let expiresDate = expiredDate else {
             return false
         }

+ 1 - 0
AIEmoji/Common/Tool/TSCommonTool/TSCommonTool.swift

@@ -222,3 +222,4 @@ func kExecuteOnMainThread(_ block: @escaping () -> Void) {
 }
 
 let kAppName:String = "Chibi" //Chibi Ghiblii
+let kUploadImageMaxBitSize:Int = 10 * 1024 * 1024 //10M

+ 59 - 47
AIEmoji/Common/View/TSPhotoPickerManager/TSPhotoPickerManager.swift

@@ -13,7 +13,8 @@ class TSPhotoPickerManager: NSObject {
     // MARK: - Properties
     private weak var viewController: UIViewController?
     private var completionHandler: ((UIImage?,PHAsset?) -> Void)?
-    
+    private var completionSizeHandler: ((UIImage?,String?) -> Void)?
+    private var imagePicker = UIImagePickerController()
     // MARK: - Initializers
     init(viewController: UIViewController) {
         self.viewController = viewController
@@ -23,7 +24,6 @@ class TSPhotoPickerManager: NSObject {
     /// 打开照片选择器,单选一张照片
     func pickSinglePhoto(completion: @escaping (UIImage?,PHAsset?) -> Void) {
         self.completionHandler = completion
-        
         // 检查相册权限
         checkPhotoLibraryPermission { [weak self] authorized in
             guard let self = self else { return }
@@ -55,23 +55,13 @@ class TSPhotoPickerManager: NSObject {
     
     /// 打开照片选择器
     private func openPhotoPicker() {
-//        if #available(iOS 14, *) {
-//            var configuration = PHPickerConfiguration(photoLibrary: .shared())
-//            configuration.selectionLimit = 1 // 只能选择一张照片
-//            configuration.filter = .images // 只显示照片,不显示视频
-//            configuration.preferredAssetRepresentationMode = .current // 使用高质量图片
-//            
-//            let picker = PHPickerViewController(configuration: configuration)
-//            picker.delegate = self
-//            viewController?.present(picker, animated: true, completion: nil)
-//        } else {
-            // iOS 14 以下使用旧的 UIImagePickerController
-            let imagePicker = UIImagePickerController()
-            imagePicker.sourceType = .photoLibrary
-            imagePicker.delegate = self
-            imagePicker.mediaTypes = ["public.image"] // 只选择照片
-            viewController?.present(imagePicker, animated: true, completion: nil)
-//        }
+        imagePicker = UIImagePickerController()
+        imagePicker.sourceType = .photoLibrary
+        imagePicker.delegate = self
+        imagePicker.mediaTypes = ["public.image"] // 只选择照片
+//        imagePicker.modalPresentationStyle = .overFullScreen
+//        imagePicker.modalTransitionStyle = .crossDissolve
+        viewController?.present(imagePicker, animated: true, completion: nil)
     }
     
     /// 显示权限提示
@@ -91,46 +81,68 @@ class TSPhotoPickerManager: NSObject {
     }
 }
 
-//// MARK: - PHPickerViewControllerDelegate (iOS 14+)
-//@available(iOS 14, *)
-//extension TSPhotoPickerManager: PHPickerViewControllerDelegate {
-//    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
-//        picker.dismiss(animated: true) {
-//            guard let result = results.first else {
-//                self.completionHandler?(nil,nil)
-//                return
-//            }
-//            
-//            // 获取选中的图片
-//            result.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] (object, error) in
-//                if let image = object as? UIImage {
-//                    DispatchQueue.main.async {
-//                        self?.completionHandler?(image)
-//                    }
-//                } else {
-//                    DispatchQueue.main.async {
-//                        self?.completionHandler?(nil,nil)
-//                    }
-//                }
-//            }
-//        }
-//    }
-//}
-
 // MARK: - UIImagePickerControllerDelegate & UINavigationControllerDelegate (iOS 14 以下)
 extension TSPhotoPickerManager: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
     func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
-        picker.dismiss(animated: true) {
+//        picker.dismiss(animated: true) {
             if let image = info[.originalImage] as? UIImage {
                 self.completionHandler?(image,info[.phAsset] as? PHAsset )
             } else {
                 self.completionHandler?(nil,nil)
             }
+//        }
+        
+        if completionSizeHandler == nil {
+            picker.dismiss(animated: true, completion: nil)
         }
+
     }
     
     func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
-        picker.dismiss(animated: true, completion: nil)
         self.completionHandler?(nil,nil)
+        if completionSizeHandler == nil {
+            picker.dismiss(animated: true, completion: nil)
+        }
+    }
+}
+
+
+
+extension TSPhotoPickerManager{
+    
+    // MARK: - Public Methods
+    /// 打开照片选择器,单选一张照片
+    func pickSinglePhoto(maxBitSize:Int, completion: @escaping (UIImage?,String?) -> Void) {
+        self.completionSizeHandler = completion
+        pickSinglePhoto { [weak self] image,phAsset in
+            guard let self = self else { return }
+            if let image = image,let phAsset = phAsset {
+                // 方法2:异步获取详细大小(不阻塞主线程)
+                TSPhotoSizeHelper.getImageFileSizeAsync(asset: phAsset) {[weak self] size in
+                    guard let self = self else { return }
+                    
+                    let mbSize = Double(size) / (1024 * 1024)
+                    print("精确大小: \(mbSize) MB,size = \(size)")
+                    if size > maxBitSize {
+                        self.completionSizeHandler?(nil,"Photo must be smaller than 10MB.".localized)
+                    }else{
+                        self.completionSizeHandler?(image,nil)
+                        self.completionSizeHandler = nil
+                        imagePicker.dismiss(animated: true)
+                    }
+                }
+            }else if let image = image {
+                if image.isLargerThan(byteSize: maxBitSize) {
+                    self.completionSizeHandler?(nil,"Photo must be smaller than 10MB.".localized)
+                }else{
+                    self.completionSizeHandler?(image,nil)
+                    self.completionSizeHandler = nil
+                    imagePicker.dismiss(animated: true)
+                }
+            }else{
+                self.completionSizeHandler?(nil,nil)
+                imagePicker.dismiss(animated: true)
+            }
+        }
     }
 }

+ 40 - 24
AIEmoji/Res/ai_change_emote_style.json

@@ -1,52 +1,68 @@
 [
     {
-        "imageName": "none",
+        "imageName": "ai_emo_changePic",
+        "imageText": "Change",
+        "prompt":"",
+        "style":"",
+        "clickType":2,
+        "isVip": false
+    },
+    {
+        "imageName": "ai_emo_none",
         "imageText": "None",
         "prompt":"",
+        "clickType":1,
         "style":"No Style",
         "isVip": false
     },
     {
-        "imageName": "☺️",
-        "imageText": "酒窝笑",
+        "imageName": "ai_emo_dimpledSmile",
+        "imageText": "Dimple",
         "prompt":"",
-        "style":"",
-        "isVip": false
+        "style":"jiuwo",
+        "isVip": true
     },
     {
-        "imageName": "☺️",
-        "imageText": "梨涡笑",
+        "imageName": "ai_emo_pearSmile",
+        "imageText": "Smile",
         "prompt":"",
-        "style":"",
-        "isVip": false
+        "style":"liwo",
+        "isVip": true
     },
     {
-        "imageName": "☺️",
-        "imageText": "露牙笑",
+        "imageName": "ai_emo_grin",
+        "imageText": "Toothy smile",
         "prompt":"",
-        "style":"",
-        "isVip": false
+        "style":"big_smile_white_teeth",
+        "isVip": true
     },
     {
-        "imageName": "☺️",
-        "imageText": "勉强笑",
+        "imageName": "ai_emo_classic_teeth",
+        "imageText": "Laugh",
         "prompt":"",
-        "style":"",
-        "isVip": false
+        "style":"classic_white_teeth",
+        "isVip": true
+    },
+    {
+        "imageName": "ai_emo_tightSmile",
+        "imageText": "Reluctant",
+        "prompt":"",
+        "style":"tight_smile",
+        "isVip": true
     },
     {
-        "imageName": "☺️",
+        "imageName": "ai_emo_cool",
         "imageText": "Cool",
         "prompt":"",
-        "style":"",
-        "isVip": false
+        "style":"cool",
+        "isVip": true
     },
     {
-        "imageName": "☺️",
+        "imageName": "ai_emo_sad",
         "imageText": "Sad",
         "prompt":"",
-        "style":"",
-        "isVip": false
-    },
+        "style":"sad",
+        "isVip": true
+    }
 ]
 

+ 36 - 0
AIEmoji/Res/photo_to_photo_style.json

@@ -4,6 +4,7 @@
         "imageText": "Ghibli",
         "prompt":"Studio Ghibli-inspired anime aesthetic, Hayao Miyazaki style, vibrant yet soft color palette, detailed hand-painted textures, whimsical dreamlike atmosphere, soft cel-shading, watercolor wash effect, subtle grain texture, preserving original composition. Style strength: 85%",
         "specialStyle":1,
+        "specialStyle":1,
         "isVip": true
     },
     {
@@ -33,6 +34,41 @@
         "specialStyle":0,
         "isVip": true
     },
+    {
+        "imageName": "ptp_style_Claymation",
+        "imageText": "Claymation",
+        "prompt":"粘土动画风特征",
+        "specialStyle":0,
+        "isVip": true
+    },
+    {
+        "imageName": "ptp_style_Pixel",
+        "imageText": "Pixel",
+        "prompt":"把图片变成 Pixar 风格",
+        "specialStyle":0,
+        "isVip": true
+    },
+    {
+        "imageName": "ptp_style_3D",
+        "imageText": "3D",
+        "prompt":"",
+        "specialStyle":0,
+        "isVip": true
+    },
+    {
+        "imageName": "ptp_style_Sketch",
+        "imageText": "Sketch",
+        "prompt":"A detailed pencil sketch of uploaded photo, bold strokes for shadows, fine lines for details, textured paper background, monochrome, realistic shading --v 5.0",
+        "specialStyle":0,
+        "isVip": true
+    },
+    {
+        "imageName": "ptp_style_Toy",
+        "imageText": "Toy",
+        "prompt":"",
+        "specialStyle":0,
+        "isVip": false
+    },
     {
         "imageName": "ptp_style_0",
         "imageText": "Retro Anime",