Procházet zdrojové kódy

年龄改变开发完毕

100Years před 1 týdnem
rodič
revize
a2b397fc47
26 změnil soubory, kde provedl 670 přidání a 113 odebrání
  1. 16 0
      AIEmoji.xcodeproj/project.pbxproj
  2. 22 0
      AIEmoji/Assets.xcassets/AIList/ailist_upload_big_bg.imageset/Contents.json
  3. binární
      AIEmoji/Assets.xcassets/AIList/ailist_upload_big_bg.imageset/ailist_upload_big_bg@2x.png
  4. binární
      AIEmoji/Assets.xcassets/AIList/ailist_upload_big_bg.imageset/ailist_upload_big_bg@3x.png
  5. 2 2
      AIEmoji/Assets.xcassets/Common/circle_selected.imageset/Contents.json
  6. binární
      AIEmoji/Assets.xcassets/Common/circle_selected.imageset/circle_selected@2x.png
  7. binární
      AIEmoji/Assets.xcassets/Common/circle_selected.imageset/circle_selected@3x.png
  8. 22 0
      AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/Contents.json
  9. 0 0
      AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/circle_unSelected@2x.png
  10. 0 0
      AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/circle_unSelected@3x.png
  11. 22 0
      AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/Contents.json
  12. binární
      AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/switch_original_picture@2x.png
  13. binární
      AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/switch_original_picture@3x.png
  14. 94 17
      AIEmoji/Business/Data/TSUserDefaultData.swift
  15. 2 2
      AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIAgeImageHintVC.swift
  16. 3 6
      AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIListHintBaseVC.swift
  17. 5 3
      AIEmoji/Business/TSAILIstVC/TSAILIstVC/TSAILIstVC.swift
  18. 104 0
      AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVC.swift
  19. 65 0
      AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVM.swift
  20. 60 11
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift
  21. 25 11
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift
  22. 189 38
      AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift
  23. 17 4
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift
  24. 1 1
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/TSPTPInputVC.swift
  25. 17 18
      AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift
  26. 4 0
      AIEmoji/Common/NetworkManager/TSNetWork/TSNetWork+Business.swift

+ 16 - 0
AIEmoji.xcodeproj/project.pbxproj

@@ -163,6 +163,8 @@
 		A8BA766C2DA657E8000B6707 /* TSAIListPhotoGeneratorBaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8BA766B2DA657E6000B6707 /* TSAIListPhotoGeneratorBaseVC.swift */; };
 		A8BA766F2DA65824000B6707 /* TSAIListPhotoGeneratorBaseVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8BA766E2DA65823000B6707 /* TSAIListPhotoGeneratorBaseVM.swift */; };
 		A8BA76722DA65A95000B6707 /* TSAIUploadPhotoBaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8BA76712DA65A94000B6707 /* TSAIUploadPhotoBaseVC.swift */; };
+		A8BA76752DA67E66000B6707 /* TSAIListHistoryBaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8BA76742DA67E65000B6707 /* TSAIListHistoryBaseVC.swift */; };
+		A8BA76772DA68619000B6707 /* TSAIListHistoryBaseVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8BA76762DA68617000B6707 /* TSAIListHistoryBaseVM.swift */; };
 		A8EEADD42D3E6C660032C5A0 /* Flower💐.json in Resources */ = {isa = PBXBuildFile; fileRef = A8EEADD32D3E6C610032C5A0 /* Flower💐.json */; };
 		A8EEADD62D3E6CD80032C5A0 /* Fish🐠.json in Resources */ = {isa = PBXBuildFile; fileRef = A8EEADD52D3E6CD30032C5A0 /* Fish🐠.json */; };
 		A8EEADD82D3E74D20032C5A0 /* Pink🩷.json in Resources */ = {isa = PBXBuildFile; fileRef = A8EEADD72D3E74CB0032C5A0 /* Pink🩷.json */; };
@@ -402,6 +404,8 @@
 		A8BA766B2DA657E6000B6707 /* TSAIListPhotoGeneratorBaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIListPhotoGeneratorBaseVC.swift; sourceTree = "<group>"; };
 		A8BA766E2DA65823000B6707 /* TSAIListPhotoGeneratorBaseVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIListPhotoGeneratorBaseVM.swift; sourceTree = "<group>"; };
 		A8BA76712DA65A94000B6707 /* TSAIUploadPhotoBaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIUploadPhotoBaseVC.swift; sourceTree = "<group>"; };
+		A8BA76742DA67E65000B6707 /* TSAIListHistoryBaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIListHistoryBaseVC.swift; sourceTree = "<group>"; };
+		A8BA76762DA68617000B6707 /* TSAIListHistoryBaseVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIListHistoryBaseVM.swift; sourceTree = "<group>"; };
 		A8EEADD32D3E6C610032C5A0 /* Flower💐.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "Flower💐.json"; sourceTree = "<group>"; };
 		A8EEADD52D3E6CD30032C5A0 /* Fish🐠.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "Fish🐠.json"; sourceTree = "<group>"; };
 		A8EEADD72D3E74CB0032C5A0 /* Pink🩷.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "Pink🩷.json"; sourceTree = "<group>"; };
@@ -1306,6 +1310,7 @@
 		A8BA765F2DA6479A000B6707 /* TSAILIstVC */ = {
 			isa = PBXGroup;
 			children = (
+				A8BA76732DA67E60000B6707 /* TSAIListHistoryBaseVC */,
 				A8BA76702DA65A81000B6707 /* TSAIUploadPhotoBaseVC */,
 				A8BA766A2DA6579A000B6707 /* TSAIPhotoGeneratorBaseVC */,
 				A8BA76692DA6578C000B6707 /* TSAILIstVC */,
@@ -1357,6 +1362,15 @@
 			path = TSAIUploadPhotoBaseVC;
 			sourceTree = "<group>";
 		};
+		A8BA76732DA67E60000B6707 /* TSAIListHistoryBaseVC */ = {
+			isa = PBXGroup;
+			children = (
+				A8BA76742DA67E65000B6707 /* TSAIListHistoryBaseVC.swift */,
+				A8BA76762DA68617000B6707 /* TSAIListHistoryBaseVM.swift */,
+			);
+			path = TSAIListHistoryBaseVC;
+			sourceTree = "<group>";
+		};
 		A8F774602D38E8B000AA6E93 = {
 			isa = PBXGroup;
 			children = (
@@ -2022,6 +2036,7 @@
 				A80E722F2D3F3E1400C64288 /* TSDiyCanvasView.swift in Sources */,
 				A80E72672D409C7D00C64288 /* Template+More.swift in Sources */,
 				A89EA6AC2D5B3EFB000EB181 /* TSRealmManager.swift in Sources */,
+				A8BA76772DA68619000B6707 /* TSAIListHistoryBaseVM.swift in Sources */,
 				A80EDDE42D6EB8FA003CD332 /* TSPTPSelectStyleCell.swift in Sources */,
 				A8F775172D38EB7400AA6E93 /* TSTabBarController.swift in Sources */,
 				A80E73E12D533E5800C64288 /* TSPurchaseVC.swift in Sources */,
@@ -2061,6 +2076,7 @@
 				A80EDDF02D6EC045003CD332 /* TSPTPStyleModel.swift in Sources */,
 				A85E47BE2D68999B0018D62D /* ShareActivityItemProvider.swift in Sources */,
 				A8F7763C2D3B429B00AA6E93 /* TSCommonloadingView.swift in Sources */,
+				A8BA76752DA67E66000B6707 /* TSAIListHistoryBaseVC.swift in Sources */,
 				A8F776322D3A771400AA6E93 /* TSGenmojiCollectionViewModel.swift in Sources */,
 				A80E721E2D3F3A7500C64288 /* DiyElement.swift in Sources */,
 				A83404D32D9D23FA00C140E4 /* TSGeneratorloadingView.swift in Sources */,

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

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

binární
AIEmoji/Assets.xcassets/AIList/ailist_upload_big_bg.imageset/ailist_upload_big_bg@2x.png


binární
AIEmoji/Assets.xcassets/AIList/ailist_upload_big_bg.imageset/ailist_upload_big_bg@3x.png


+ 2 - 2
AIEmoji/Assets.xcassets/Common/selected_circle.imageset/Contents.json → AIEmoji/Assets.xcassets/Common/circle_selected.imageset/Contents.json

@@ -5,12 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "selected_circle@2x.png",
+      "filename" : "circle_selected@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "selected_circle@3x.png",
+      "filename" : "circle_selected@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

binární
AIEmoji/Assets.xcassets/Common/circle_selected.imageset/circle_selected@2x.png


binární
AIEmoji/Assets.xcassets/Common/circle_selected.imageset/circle_selected@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/Contents.json

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

+ 0 - 0
AIEmoji/Assets.xcassets/Common/selected_circle.imageset/selected_circle@2x.png → AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/circle_unSelected@2x.png


+ 0 - 0
AIEmoji/Assets.xcassets/Common/selected_circle.imageset/selected_circle@3x.png → AIEmoji/Assets.xcassets/Common/circle_unSelected.imageset/circle_unSelected@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/Contents.json

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

binární
AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/switch_original_picture@2x.png


binární
AIEmoji/Assets.xcassets/Common/switch_original_picture.imageset/switch_original_picture@3x.png


+ 94 - 17
AIEmoji/Business/Data/TSUserDefaultData.swift

@@ -41,6 +41,7 @@ func kHandleTSHistory(){
 
 // MARK: - 基础历史记录类
 class TSBaseHistoryManager<ModelType: TSBaseModel> {
+    
     // 子类必须重写的属性
     var historyKey: String { fatalError("必须重写 historyKey") }
     var exampleDataKey: String { fatalError("必须重写 exampleDataKey") }
@@ -89,6 +90,11 @@ class TSBaseHistoryManager<ModelType: TSBaseModel> {
         saveHistory()
     }
     
+    func removeALLModel() {
+        listModels.removeAll()
+        saveHistory()
+    }
+    
     func replaceModel(oldID: Int, newModel: ModelType){
         if let index = findModelID(modelID: oldID) {
             listModels[index] = newModel
@@ -153,35 +159,106 @@ class TSBaseHistoryManager<ModelType: TSBaseModel> {
     }
 }
 
-// MARK: - 海报历史记录
-final class TSPosterHistory: TSBaseHistoryManager<TSGenmojiModel> {
-    static let shared = TSPosterHistory()
-    override var historyKey: String { "kPosterTextPicHistoryListString" }
-    override var exampleDataKey: String { "insertPosterExampleData" }
+// MARK: - 新的储存方法
+// MARK: - 变老
+final class TSChangeOldAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
+    static let shared = TSChangeOldAgeHistory()
+    override var historyKey: String { "kTSChangeOldAgeHistoryListString" }
+//    override var exampleDataKey: String { "insertPosterExampleData" }
     
     override func findModelID(modelID: Int) -> Int? {
         return listModels.firstIndex(where: {$0.id == modelID})
     }
     
     override var exampleModels: [TSGenmojiModel] {
-        [
-            createExampleModel(imageName: "poster_example_0"),
-            createExampleModel(imageName: "poster_example_1"),
-            createExampleModel(imageName: "poster_example_2")
-        ]
+        []
     }
+//
+//    private func createExampleModel(imageName: String) -> TSGenmojiModel {
+//        let model = TSGenmojiModel()
+//        model.modelType = .example
+//        model.request.prompt = "Example"
+//        model.request.promptSort = "Example"
+//        model.response.resultUrl = imageName
+//        return model
+//    }
+}
+
+// MARK: - 变年轻
+final class TSChangeBabyAgeHistory: TSBaseHistoryManager<TSGenmojiModel> {
+    static let shared = TSChangeBabyAgeHistory()
+    override var historyKey: String { "kTSChangeBabyAgeHistoryListString" }
     
-    private func createExampleModel(imageName: String) -> TSGenmojiModel {
-        let model = TSGenmojiModel()
-        model.modelType = .example
-        model.request.prompt = "Example"
-        model.request.promptSort = "Example"
-        model.response.resultUrl = imageName
-        return model
+    override var exampleModels: [TSGenmojiModel] {
+        []
+    }
+    override func findModelID(modelID: Int) -> Int? {
+        return listModels.firstIndex(where: {$0.id == modelID})
     }
 }
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// MARK: - 旧的储存方法
 //海报历史记录
 class TSTextToPicHistory{
     @UserDefault(key: "textPicHistoryListString", defaultValue: "")

+ 2 - 2
AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIAgeImageHintVC.swift

@@ -8,8 +8,8 @@
 class TSAIAgeImageHintVC: TSAIListHintBaseVC {
     override func createData() {
         Self.userDefaultsKey = "isFirstAIListAge"
-        goodImageNamed = ""
-        badImageNamed = ""
+        goodImageNamed = "ptp_goodImage"
+        badImageNamed = "ptp_badImage"
         super.createData()
     }
 }

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

@@ -28,18 +28,17 @@ class TSAIListHintBaseVC: TSBaseVC {
     
     
     lazy var noPromptsBtn: UIButton = {
-        let noPromptsBtn = UIButton.createButton(title: "No more prompts".localized,image: UIImage(named: "selected_circle"),font: .font(size: 11),titleColor: .white.withAlphaComponent(0.6)){ [weak self]  in
+        let noPromptsBtn = UIButton.createButton(title: "No more prompts".localized,image: UIImage(named: "circle_unSelected"),font: .font(size: 11),titleColor: .white.withAlphaComponent(0.6)){ [weak self]  in
             guard let self = self else { return }
             changeNoPromptsBtn()
         }
-        noPromptsBtn.setImage(UIImage(named: "radioboxSelected"), for: .selected)
+        noPromptsBtn.setImage(UIImage(named: "circle_selected"), for: .selected)
         return noPromptsBtn
     }()
     override func createView() {
         setNavBarViewHidden(true)
         view.backgroundColor = .black.withAlphaComponent(0.7)
         
-        
         view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickView)))
         
         contentView.addSubview(popupContentView)
@@ -135,8 +134,6 @@ class TSAIListHintBaseVC: TSBaseVC {
             make.height.equalTo(48)
         }
 
-        
-        noPromptsBtn.isSelected = true
         popupContentView.addSubview(noPromptsBtn)
         noPromptsBtn.snp.makeConstraints { make in
             make.top.equalTo(submitBtn.snp.bottom).offset(12)
@@ -148,7 +145,7 @@ class TSAIListHintBaseVC: TSBaseVC {
     
     func changeNoPromptsBtn(){
         noPromptsBtn.isSelected = !noPromptsBtn.isSelected
-        Self.isShowUploadImageHint = noPromptsBtn.isSelected
+        Self.isShowUploadImageHint = !noPromptsBtn.isSelected
     }
     
     static var isShowUploadImageHint:Bool{

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

@@ -18,9 +18,9 @@ class TSAILIstVC: TSBaseVC {
                 leftTitle: "Change Age".localized,
                 leftSubTitle: "AI predicts what you look like in your old age.".localized,
                 rightViewStyle: 0,
-                tapBlock: { [weak self] _, _, _ in
+                tapBlock: { [weak self] model, _, _ in
                    guard let self = self else { return }
-                    let baseVc = TSAIUploadPhotoBaseVC(generatorStyle: .ageOld)
+                    let baseVc = TSAIUploadPhotoBaseVC(titleString: model.leftTitle ?? "", generatorStyle: .ageOld)
                     kPushVC(target: self, modelVC: baseVc)
         }))
         
@@ -30,8 +30,10 @@ class TSAILIstVC: TSBaseVC {
                 leftTitle: "Back to Baby".localized,
                 leftSubTitle: "AI helps you go back to being a baby.".localized,
                 rightViewStyle: 0,
-                tapBlock: { [weak self] _, _, _ in
+                tapBlock: { [weak self] model, _, _ in
                    guard let self = self else { return }
+                    let baseVc = TSAIUploadPhotoBaseVC(titleString: model.leftTitle ?? "", generatorStyle: .ageChild)
+                    kPushVC(target: self, modelVC: baseVc)
                                 
         }))
 

+ 104 - 0
AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVC.swift

@@ -0,0 +1,104 @@
+//
+//  TSAIListHistoryBaseVC.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/9.
+//
+
+class TSAIListHistoryBaseVC: TSBaseVC {
+    
+    var generatorStyle:TSGeneratorImageStyle
+    var titleString:String?
+    init(titleString:String? = nil,generatorStyle:TSGeneratorImageStyle) {
+        self.titleString = titleString
+        self.generatorStyle = generatorStyle
+        super.init()
+    }
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    lazy var viewModel: TSAIListHistoryBaseVM = {
+        let viewModel = TSAIListHistoryBaseVM(generatorStyle: generatorStyle)
+        return viewModel
+    }()
+    
+    //###################################### 集合视图 ######################################
+    let collectionViewBtootm:CGFloat = 80
+    lazy var collectionComponent: TSCollectionViewComponent = {
+        let layout = UICollectionViewFlowLayout()
+        let cp = TSCollectionViewComponent(frame: CGRect.zero, layout: layout, attributes: [:])
+        cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: collectionViewBtootm, right: 0)
+        
+        
+        // 禁用自动 contentInset 调整
+          if #available(iOS 11.0, *) {
+              cp.collectionView.contentInsetAdjustmentBehavior = .never
+          } else {
+              automaticallyAdjustsScrollViewInsets = false
+          }
+        
+        cp.sectionActionHandler = { [weak self] cellCp, indexPath in
+            guard let self = self else { return }
+            if let cmd = cellCp as? String, cmd == "delete"  {
+                showCustomAlert(message: "Are you sure to delete".localized, deleteHandler:  {
+                    self.viewModel.removeAllHistoryList()
+                    self.collectionComponent.clear()
+                    self.collectionComponent.reloadView(with: self.viewModel.colDataArray)
+                })
+            }
+        }
+        
+        cp.itemDidSelectedHandler = { [weak self] (object, indexPath) in
+            guard let self = self else { return }
+ 
+            if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
+                var dataModelArray:[TSGenmojiModel] = []
+                for itemModel in sections.items {
+                    dataModelArray.append(itemModel.dataModel)
+                }
+                
+                let browseVC = TSAIPhotoBrowseVC()
+                browseVC.dataModelArray = dataModelArray
+                browseVC.currentIndex = indexPath.item
+                kPresentModalVC(target: self, modelVC: browseVC,transitionStyle: .crossDissolve)
+            }
+        }
+
+        return cp
+    }()
+    
+    override func createData() {
+        
+    }
+    
+    override func createView() {
+        
+        addNormalNavBarView()
+        
+        var titleString = "History".localized
+        if let title = self.titleString {
+            titleString = title
+        }
+        setPageTitle(titleString)
+        _ = setNavigationItem("", imageName: "delete_white", direction: .right, action: #selector(clickNavRight))
+        
+        
+        contentView.addSubview(collectionComponent.collectionView)
+        collectionComponent.collectionView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        collectionComponent.clear()
+        collectionComponent.reloadView(with:viewModel.colDataArray)
+    }
+    
+    @objc func clickNavRight() {
+        showCustomAlert(message: "Are you sure to delete".localized, deleteHandler:  {
+            self.viewModel.removeAllHistoryList()
+            self.collectionComponent.clear()
+            self.collectionComponent.reloadView(with: self.viewModel.colDataArray)
+        })
+    }
+    
+}

+ 65 - 0
AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVM.swift

@@ -0,0 +1,65 @@
+//
+//  TSAIListHistoryBaseVM.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/9.
+//
+
+import Alamofire
+import ObjectMapper
+class TSAIListHistoryBaseVM {
+
+    var colDataArray:[TSComponent] = [TSComponent]()
+    lazy var historySeciton: TSGenmojiCoLSectionModel = {
+        let sectionModel = TSGenmojiCoLSectionModel()
+        sectionModel.style = .changeAgeHistory
+        sectionModel.name = "History".localized
+        for model in listModelArray {
+            let itemModel = TSGenmojiCoLItemModel()
+            itemModel.style = sectionModel.style
+            itemModel.dataModel = model
+            sectionModel.items.append(itemModel)
+        }
+        return sectionModel
+    }()
+    
+    var generatorStyle:TSGeneratorImageStyle
+    init(generatorStyle:TSGeneratorImageStyle) {
+        self.generatorStyle = generatorStyle
+        self.combinedData()
+    }
+    
+    func combinedData(){
+        colDataArray.removeAll()
+        
+        if historySeciton.items.count > 0 {
+            colDataArray.append(historySeciton)
+        }
+    }
+    
+    func removeAllHistoryList(){
+
+        switch generatorStyle {
+        case .ageOld:
+            TSChangeOldAgeHistory.shared.removeALLModel()
+        case .ageChild:
+            TSChangeBabyAgeHistory.shared.removeALLModel()
+        }
+        
+        colDataArray.removeAll()
+    }
+    
+}
+ 
+extension TSAIListHistoryBaseVM {
+    var listModelArray:[TSGenmojiModel]{
+        switch generatorStyle {
+        case .ageOld:
+            TSChangeOldAgeHistory.shared.listModels
+        case .ageChild:
+            TSChangeBabyAgeHistory.shared.listModels
+        }
+    }
+}
+
+

+ 60 - 11
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift

@@ -10,20 +10,30 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
     var imageModel:TSGenmojiModel?
     var complete:((TSGenmojiModel)->Void)
     
-    var prompt:String
-    var promptSort:String
-    var imageUrl:String
+//    var prompt:String
+//    var promptSort:String
+
+//    var style:String
+    var imageUrl:String?
     var upLoadImage:UIImage
-    var style:String
     var generatorStyle:TSGeneratorImageStyle
     
     var progressState = TSProgressState.none
-    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSGenmojiModel)->Void)) {
-        self.prompt = prompt
-        self.promptSort = promptSort
-        self.imageUrl = imageUrl
+//    init(prompt:String,promptSort:String,imageUrl:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSGenmojiModel)->Void)) {
+//        self.prompt = prompt
+//        self.promptSort = promptSort
+//        self.imageUrl = imageUrl
+//        self.upLoadImage = upLoadImage
+//        self.style = style
+//        self.generatorStyle = generatorStyle
+//        self.complete = complete
+//        
+//        super.init()
+//    }
+    
+    
+    init(upLoadImage:UIImage,generatorStyle:TSGeneratorImageStyle,complete:@escaping ((TSGenmojiModel)->Void)) {
         self.upLoadImage = upLoadImage
-        self.style = style
         self.generatorStyle = generatorStyle
         self.complete = complete
         
@@ -31,7 +41,8 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
     }
     
     lazy var viewModel: TSAIListPhotoGeneratorBaseVM = {
-        let viewModel:TSAIListPhotoGeneratorBaseVM = TSAIListPhotoGeneratorBaseVM(prompt: prompt,upLoadImage:upLoadImage,style: style, generatorStyle: generatorStyle)
+//        let viewModel:TSAIListPhotoGeneratorBaseVM = TSAIListPhotoGeneratorBaseVM(prompt: prompt,upLoadImage:upLoadImage,style: style, generatorStyle: generatorStyle)
+        let viewModel:TSAIListPhotoGeneratorBaseVM = TSAIListPhotoGeneratorBaseVM(upLoadImage: upLoadImage, generatorStyle: generatorStyle)
         return viewModel
     }()
 
@@ -45,6 +56,17 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
         return generateInView
     }()
     
+    
+    lazy var switchOriginalPictureBtn: UIButton = {
+        let switchOriginalPictureBtn = UIButton.createButton(image:UIImage(named: "switch_original_picture")){ [weak self]  in
+            guard let self = self else { return }
+            switchOriginalPictureHandle()
+        }
+        switchOriginalPictureBtn.isHidden = true
+        return switchOriginalPictureBtn
+    }()
+    
+
     override func createView() {
 
         contentView.addSubview(generateInView)
@@ -53,6 +75,16 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
         }
         
         super.createView()
+        
+        //关闭按钮
+        contentView.addSubview(switchOriginalPictureBtn)
+        switchOriginalPictureBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-k_Height_safeAreaInsetsBottom() - 76)
+            make.trailing.equalTo(-16)
+            make.width.equalTo(40)
+            make.height.equalTo(40)
+        }
+        
     }
     
     override func closePage() {
@@ -161,6 +193,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         isClickTheBlankClosePage = false
         bottomView.isHidden = true
         netWorkImageView.isHidden = true
+        switchOriginalPictureBtn.isHidden = true
     }
     
     func showLoading(){
@@ -171,6 +204,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         isClickTheBlankClosePage = false
         bottomView.isHidden = true
         netWorkImageView.isHidden = true
+        switchOriginalPictureBtn.isHidden = true
     }
     
     func showError(text:String?){
@@ -185,6 +219,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         bigSaveBtn.isHidden = true
         bottomView.isHidden = false
         netWorkImageView.isHidden = true
+        switchOriginalPictureBtn.isHidden = true
     }
     
     func showSuccess(model:TSGenmojiModel){
@@ -198,6 +233,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         bigSaveBtn.isHidden = false
         bottomView.isHidden = false
         netWorkImageView.isHidden = false
+        switchOriginalPictureBtn.isHidden = false
         
         self.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!){ [weak self] image in
             guard let self = self else { return }
@@ -207,8 +243,21 @@ extension TSAIListPhotoGeneratorBaseVC {
         
         kPurchaseDefault.useOnceForFree(type: .picToPic)
         if let model = imageModel {
-            model.request.promptSort = promptSort
             complete(model)
         }
     }
+    
+    func switchOriginalPictureHandle() {
+        
+        guard let imageModel = imageModel else { return }
+        switchOriginalPictureBtn.isSelected = !switchOriginalPictureBtn.isSelected
+        
+        if switchOriginalPictureBtn.isSelected {
+            self.netWorkImageView.image = upLoadImage
+        }else {
+            self.netWorkImageView.setAsyncImage(urlString: imageModel.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!){ [weak self] image in
+                guard let self = self else { return }
+            }
+        }
+    }
 }

+ 25 - 11
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift

@@ -15,18 +15,25 @@ class TSAIListPhotoGeneratorBaseVM {
     var stopNetwork = false
     
     @Published var stateDatauPblished:(TSProgressState,TSGenmojiModel?) = (TSProgressState.none,nil)
-   
-    var prompt:String
+    var generatingProgress = 0
+    
+//    var prompt:String
+//    var imageUrl:String?
+//    var upLoadImage:UIImage
+//    var style:String
+//    var generatorStyle:TSGeneratorImageStyle
+//    init(prompt:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle) {
+//        self.prompt = prompt
+//        self.upLoadImage = upLoadImage
+//        self.style = style
+//        self.generatorStyle = generatorStyle
+//    }
+    
     var imageUrl:String?
     var upLoadImage:UIImage
-    var style:String
     var generatorStyle:TSGeneratorImageStyle
-    
-    var generatingProgress = 0
-    init(prompt:String,upLoadImage:UIImage,style:String,generatorStyle:TSGeneratorImageStyle) {
-        self.prompt = prompt
+    init(upLoadImage:UIImage,generatorStyle:TSGeneratorImageStyle) {
         self.upLoadImage = upLoadImage
-        self.style = style
         self.generatorStyle = generatorStyle
     }
     
@@ -60,16 +67,23 @@ class TSAIListPhotoGeneratorBaseVM {
 //
 //    }
     
+    var targetAge:Int {
+        switch generatorStyle {
+        case .ageOld:
+            return 70
+        case .ageChild:
+            return 5
+        }
+    }
     func creatImage() {
         guard let imageUrl = imageUrl else { return }
         generatingProgress = 0
         stopNetwork = false
         stateDatauPblished = (.start,nil)
         stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
-        creatRequest = TSNetworkShared.post(urlType: .imageRewrite,parameters:
-                                                ["prompt":prompt,
+        creatRequest = TSNetworkShared.post(urlType: .changeAge,parameters:
+                                                ["targetAge":targetAge,
                                                  "imageUrl":imageUrl,
-                                                 "style":style,
                                                  "device":getUserInfoJsonString()
                                                 ]) { [weak self] data,error in
             guard let self = self else { return }

+ 189 - 38
AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift

@@ -14,15 +14,21 @@ enum TSGeneratorImageStyle {
 
 class TSAIUploadPhotoBaseVC: TSBaseVC {
     var generatorStyle:TSGeneratorImageStyle
-    
-    init(generatorStyle:TSGeneratorImageStyle) {
+    var titleString:String
+    init(titleString:String,generatorStyle:TSGeneratorImageStyle) {
+        self.titleString = titleString
         self.generatorStyle = generatorStyle
         super.init()
     }
     @MainActor required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-    
+    //#####################################数据区#####################################
+    let lineSpacing = 6.0
+    lazy var photoPickerManager: TSPhotoPickerManager = {
+        let photoPickerManager = TSPhotoPickerManager(viewController: self)
+        return photoPickerManager
+    }()
     //#####################################底部基础#####################################
     lazy var cusStackView: TSCustomStackView = {
         let cusStackView = TSCustomStackView(axis: .vertical,spacing: 0)
@@ -33,7 +39,7 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
     lazy var submitBtn: UIButton = {
         let submitBtn = kCreateNormalSubmitBtn(title: "Accept".localized) { [weak self]  in
             guard let self = self else { return }
-        
+            generateImage()
         }
         submitBtn.cornerRadius = 24.0
         return submitBtn
@@ -44,16 +50,20 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
         didSet{
             if let image = upLoadImage {
                 upLoadView.isHidden = true
-                uploadExampleImageView.isHidden = true
+//                uploadExampleImageView.isHidden = true
                 uploadImageView.isHidden = false
                 deleteBtn.isHidden = false
                 uploadImageView.image = image
+                
+                
+                submitBtn.isEnabled = true
             }else {
                 upLoadView.isHidden = false
-                uploadExampleImageView.isHidden = false
+//                uploadExampleImageView.isHidden = false
                 uploadImageView.isHidden = true
                 deleteBtn.isHidden = true
                 uploadImageView.image = nil
+                submitBtn.isEnabled = false
             }
         }
     }
@@ -80,30 +90,30 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
         return bgView
     }()
     
-    lazy var uploadExampleImageView: UIImageView = {
-        let uploadExampleImageView = UIImageView()
-        uploadExampleImageView.image = UIImage(named: "ptp_upload_example")
-        uploadExampleImageView.contentMode = .scaleAspectFill
-        uploadExampleImageView.cornerRadius = 12
-        uploadExampleImageView.isHidden = false
-        
-        let button = UIButton.createButton(title:"Tap to select photo".localized,backgroundColor:.black.withAlphaComponent(0.4),font: .font(size: 14),titleColor: .white,corner: 12)
-        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
-        uploadExampleImageView.addSubview(button)
-        button.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-            make.bottom.equalTo(-20)
-            make.height.equalTo(24)
-        }
-        
-        return uploadExampleImageView
-    }()
+//    lazy var uploadExampleImageView: UIImageView = {
+//        let uploadExampleImageView = UIImageView()
+//        uploadExampleImageView.image = UIImage(named: "ptp_upload_example")
+//        uploadExampleImageView.contentMode = .scaleAspectFill
+//        uploadExampleImageView.cornerRadius = 12
+//        uploadExampleImageView.isHidden = false
+//        
+//        let button = UIButton.createButton(title:"Tap to select photo".localized,backgroundColor:.black.withAlphaComponent(0.4),font: .font(size: 14),titleColor: .white,corner: 12)
+//        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
+//        uploadExampleImageView.addSubview(button)
+//        button.snp.makeConstraints { make in
+//            make.centerX.equalToSuperview()
+//            make.bottom.equalTo(-20)
+//            make.height.equalTo(24)
+//        }
+//        
+//        return uploadExampleImageView
+//    }()
     
     lazy var uploadImageView: UIImageView = {
         let uploadImageView = UIImageView()
         uploadImageView.contentMode = .scaleAspectFit
         uploadImageView.cornerRadius = 12
-        upLoadView.isHidden = true
+//        upLoadView.isHidden = true
         return uploadImageView
     }()
     
@@ -112,7 +122,7 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
         
         let bgView = UIView()
         bgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action:#selector(clickBgView)))
-        let bgImageView = UIImageView.createImageView(imageName: "ptp_upload_bg")
+        let bgImageView = UIImageView.createImageView(imageName: "ailist_upload_big_bg")
         bgImageView.contentMode = .scaleToFill
         bgView.addSubview(bgImageView)
         bgImageView.snp.makeConstraints { make in
@@ -121,15 +131,15 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
 
         bgView.addSubview(upLoadView)
         upLoadView.snp.makeConstraints { make in
-            make.top.equalTo(88)
+            make.top.equalTo(244*kDesignScale)
             make.centerX.equalToSuperview()
         }
         
-        bgView.addSubview(uploadExampleImageView)
-        uploadExampleImageView.snp.makeConstraints { make in
-            make.top.leading.equalTo(8)
-            make.bottom.trailing.equalTo(-8)
-        }
+//        bgView.addSubview(uploadExampleImageView)
+//        uploadExampleImageView.snp.makeConstraints { make in
+//            make.top.leading.equalTo(8)
+//            make.bottom.trailing.equalTo(-8)
+//        }
         
         bgView.addSubview(uploadImageView)
         uploadImageView.snp.makeConstraints { make in
@@ -154,8 +164,8 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
     override func createView() {
         
         addNormalNavBarView()
-        setPageTitle("Change Age")
-        
+        setPageTitle(titleString)
+        _ = setNavigationItem("", imageName: "aichat_history", direction: .right, action: #selector(clickNavRight))
         
         contentView.addSubview(submitBtn)
         submitBtn.snp.makeConstraints { make in
@@ -172,13 +182,41 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
             make.bottom.equalTo(submitBtn.snp.top).offset(-10)
         }
         
-
+        setUpStackView()
+    }
+    
+    override func dealThings() {
+        kSetBtnVipIcon(btn: self.submitBtn, show: true)
+//        NotificationCenter.default.addObserver(self, selector: #selector(updateVipView), name: .kPurchaseDidChanged, object: nil)
+//        updateVipView()
+        
+        kDelayMainShort {
+            if TSAIAgeImageHintVC.isShowUploadImageHint{
+                self.presentModalHintVC()
+            }
+        }
     }
+}
+
+extension TSAIUploadPhotoBaseVC {
+    
+//    @objc func updateVipView() {
+//        kExecuteOnMainThread {
+//        
+//            var showVip = kPurchaseDefault.generateVipShow(type: .picToPic)
+//            if showVip == false {
+//                showVip = self.viewModel.selectedPTPStyleModel?.isVip ?? false
+//            }
+//            kSetBtnVipIcon(btn: self.submitBtn, show: showVip)
+//        }
+//    }
     
     
     func setUpStackView(){
         
+        //添加上传一大块
         let bgView = UIView()
+//        bgView.backgroundColor = .yellow.withAlphaComponent(0.1)
         bgView.addSubview(uploadImageBgView)
         cusStackView.addSubviewToStack(bgView)
     
@@ -190,14 +228,127 @@ class TSAIUploadPhotoBaseVC: TSBaseVC {
             make.bottom.equalTo(-16)
         }
 
-        uploadImageBgView.addSubview(deleteBtn)
+        bgView.addSubview(deleteBtn)
         deleteBtn.snp.makeConstraints { make in
-            make.top.equalTo(-6)
-            make.trailing.equalTo(-4)
+            make.top.equalTo(0)
+            make.trailing.equalTo(-32*kDesignScale)
             make.width.height.equalTo(32)
         }
+        
+        
+        //文字信息区域
+        cusStackView.addSubviewToStack(getTextInfoCell(text: "Size ≤ 5mb".localized))
+        cusStackView.addSpacing(height: lineSpacing)
+        cusStackView.addSubviewToStack(getTextInfoCell(text: "Single photo with face fully visible".localized))
+        cusStackView.addSpacing(height: lineSpacing)
+        cusStackView.addSubviewToStack(getTextInfoCell(text: "No group photos, covered faces, nudes".localized))
+    }
+    
+    func getTextInfoCell(text:String) -> UIView {
+        
+        let bgView = UIView()
+        let pointView = UIView()
+        pointView.backgroundColor = .white.withAlphaComponent(0.7)
+        pointView.cornerRadius = 1
+        bgView.addSubview(pointView)
+        pointView.snp.makeConstraints { make in
+            make.top.equalTo(7)
+            make.leading.equalTo(22)
+            make.width.height.equalTo(2)
+        }
+        let textLabel1 = UILabel.createLabel(text: text,font: .font(size: 12),textColor: .white.withAlphaComponent(0.6),numberOfLines: 0)
+        textLabel1.setLineSpacing(lineSpacing)
+        bgView.addSubview(textLabel1)
+        textLabel1.snp.makeConstraints { make in
+            make.top.bottom.equalToSuperview()
+            make.leading.equalTo(16+16)
+            make.trailing.equalTo(-16)
+        }
+        return bgView
+    }
+
+}
+
+extension TSAIUploadPhotoBaseVC {
+
+    @objc func clickNavRight() {
+        kPushVC(target: self, modelVC: TSAIListHistoryBaseVC(generatorStyle: generatorStyle))
     }
     
     @objc func clickBgView() {
+        pickSinglePhoto()
+    }
+    
+    func pickSinglePhoto()  {
+        photoPickerManager.pickSinglePhoto { [weak self] image,phAsset in
+            guard let self = self else { return }
+
+            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
+                        upLoadImage = image
+                    }
+                }
+            }else if let image = image {
+                if image.isLargerThan(byteSize: maxSize) {
+                    TSToastShared.showToast(text: "Photo must be smaller than 10MB.".localized)
+                }else{
+//                    viewModel.upLoadImage = image
+                    upLoadImage = image
+                }
+            }
+        }
+    }
+    
+    func presentModalHintVC(){
+        let vc = TSAIAgeImageHintVC()
+        vc.clickUpImageHandle = { [weak self]  in
+            guard let self = self else { return }
+            pickSinglePhoto()
+        }
+        kPresentModalVC(target: self, modelVC: vc,transitionStyle: .crossDissolve)
+    }
+    
+
+}
+
+
+extension TSAIUploadPhotoBaseVC {
+    
+    func generateImage() {
+        
+        //判断 vip
+        if kJudgeVip(externalBool: true, vc: self) { [weak self] in
+            guard let self = self else { return }
+        }{ return }
+        
+    
+        guard let upLoadImage = upLoadImage else { return }
+        let gennerateVC = TSAIListPhotoGeneratorBaseVC(upLoadImage: upLoadImage, generatorStyle: generatorStyle) { [weak self] model in
+            guard let self = self else { return }
+            saveModel(model: model)
+        }
+        
+        kPresentModalVC(target: self, modelVC: gennerateVC,transitionStyle: .crossDissolve)
     }
+    
+    func saveModel(model:TSGenmojiModel){
+        switch generatorStyle {
+        case .ageOld:
+            TSChangeOldAgeHistory.shared.saveModel(model: model)
+        case .ageChild:
+            TSChangeBabyAgeHistory.shared.saveModel(model: model)
+        }
+    }
+
 }

+ 17 - 4
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift

@@ -18,6 +18,12 @@ let kPTPHistoryDesignScale = kPTPHistoryDesignW/kPTPHistoryDesignH
 private let kPTPHistoryW = (k_ScreenWidth-32.0-14.0)/2.0
 private let kPTPHistoryH = kPTPHistoryW/kPTPHistoryDesignScale
 
+
+
+let kChnageAgeHistoryDesignH = 293.0
+let kChnageAgeHistoryDesignScale = kPTPHistoryDesignW/kChnageAgeHistoryDesignH
+private let kChnageAgeHistoryH = kPTPHistoryW/kChnageAgeHistoryDesignScale
+
 class TSGenmojiColViewModel: TSBaseModel {
     
     lazy var generateSectionModel: TSGenmojiCoLSectionModel = {
@@ -42,6 +48,9 @@ enum TSGenmojiCoLStyple : Int {
     case ptpSelectStyle //图生图选择样式
     case ptpPicHistory  //图生图后的历史记录
     
+    case changeAgeHistory  //改变年龄
+    
+    
     var sectionInset: UIEdgeInsets {
         switch self {
         case .generate,.textPicGenerate:
@@ -56,6 +65,8 @@ enum TSGenmojiCoLStyple : Int {
             return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
         case .ptpUpload:
             return UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
+        case .changeAgeHistory:
+            return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
         }
     }
         
@@ -65,7 +76,7 @@ enum TSGenmojiCoLStyple : Int {
             return 0
         case .history:
             return 16
-        case .textPicHistory,.ptpPicHistory:
+        case .textPicHistory,.ptpPicHistory,.changeAgeHistory:
             return 13
         case .ptpEntrance,.ptpUpload,.ptpSelectStyle:
             return 0
@@ -78,7 +89,7 @@ enum TSGenmojiCoLStyple : Int {
             return 0
         case .history:
             return 16
-        case .textPicHistory,.ptpPicHistory:
+        case .textPicHistory,.ptpPicHistory,.changeAgeHistory:
             return 13
         case .ptpEntrance,.ptpUpload,.ptpSelectStyle:
             return 0
@@ -102,6 +113,8 @@ enum TSGenmojiCoLStyple : Int {
             return CGSize(width: k_ScreenWidth, height: 110)
         case .ptpPicHistory:
             return CGSize(width: kPTPHistoryW, height: kPTPHistoryH)
+        case .changeAgeHistory:
+            return CGSize(width: kPTPHistoryW, height: kChnageAgeHistoryH)
         }
     }
     
@@ -109,7 +122,7 @@ enum TSGenmojiCoLStyple : Int {
         switch self {
         case .generate,.textPicGenerate:
             return TSGenmojiGennerateCell.self
-        case .history,.textPicHistory,.ptpPicHistory:
+        case .history,.textPicHistory,.ptpPicHistory,.changeAgeHistory:
             return TSGenmojiItemCell.self
         case .ptpEntrance:
             return TSPTPGeneratorCell.self
@@ -122,7 +135,7 @@ enum TSGenmojiCoLStyple : Int {
     
     var headerViewSize:CGSize {
         switch self {
-        case .generate,.textPicGenerate,.ptpEntrance:
+        case .generate,.textPicGenerate,.ptpEntrance,.changeAgeHistory:
             return CGSize.zero
         case .history,.textPicHistory,.ptpPicHistory,.ptpSelectStyle,.ptpUpload:
             return CGSizeMake(k_ScreenWidth, 60)

+ 1 - 1
AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/TSPTPInputVC.swift

@@ -359,7 +359,7 @@ class TSPTPInputVC: TSBaseVC {
     override func dealThings() {
         NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
         updateVipView()
-        collectionViewObserverHandle()
+//        collectionViewObserverHandle()
 ////        // 监听键盘事件
 //        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
 //        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)

+ 17 - 18
AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift

@@ -321,10 +321,9 @@ struct PurchaseView :View {
     
     var body: some View {
         ScrollView {
-            Spacer()//.frame(height: 31)
-            
+            Spacer().frame(height: 31*kDesignScale)
             VStack {
-         
+                
                 customText(text: "\(kAppName) ",fontName: .KelsiFill,color:UIColor.themeColor.color).frame(height: 53*kDesignScale)
                 
                 Spacer().frame(height: 16)
@@ -338,16 +337,16 @@ struct PurchaseView :View {
                     .cornerRadius(17.0)
                     .overlay(
                         RoundedRectangle(cornerRadius: 16)
-                        .strokeBorder(
-                              LinearGradient(
-                                  colors: [Color.hex("#FA794F"), Color.hex("#F8C32A"),Color.hex("#FEFBF4")],
-                                  startPoint: .leading,
-                                  endPoint: .trailing
-                              ),
-                              lineWidth: 2
-                          )
+                            .strokeBorder(
+                                LinearGradient(
+                                    colors: [Color.hex("#FA794F"), Color.hex("#F8C32A"),Color.hex("#FEFBF4")],
+                                    startPoint: .leading,
+                                    endPoint: .trailing
+                                ),
+                                lineWidth: 2
+                            )
                     )
-
+                
                 Spacer().frame(height: 36)
                 
                 ZStack {
@@ -375,7 +374,7 @@ struct PurchaseView :View {
                         
                     }.font(.font(size: 16)).foregroundColor(UIColor.white.color)
                 }
-         
+                
             }
             
             Spacer().frame(height: 44)
@@ -390,7 +389,7 @@ struct PurchaseView :View {
                     TSVipRecView()
                         .offset(y:-14)
                 }
-          
+                
                 HStack {
                     PurchaseItemView(title: "One Month".localized, type: .month, selectedType: $viewModel.selectedType).onTapGesture {
                         viewModel.selectedType = .month
@@ -399,7 +398,7 @@ struct PurchaseView :View {
                         viewModel.selectedType = .week
                     }
                 }
-
+                
                 Button {
                     viewModel.buyPublisher.send(true)
                 } label: {
@@ -408,7 +407,7 @@ struct PurchaseView :View {
                         Text("Continue")
                             .font(.system(size: 16))
                             .foregroundColor(.hex("#111111"))
-                            
+                        
                     }.frame(maxWidth: .infinity ,minHeight: 48.0)
                         .cornerRadius(24.0)
                 }
@@ -416,7 +415,7 @@ struct PurchaseView :View {
                 HStack {
                     Text("Recurring billing, cancel anytime".localized)
                         .foregroundColor(Color.hex("#FFBD59")) +
-                        Text(",Payment will be charged to your iTunes account at confirmation of purchase. Subscriptions automatically renew for the same applicable term and price, unless auto-renew is turned off at least 24 hours before the end of the current period.".localized)
+                    Text(",Payment will be charged to your iTunes account at confirmation of purchase. Subscriptions automatically renew for the same applicable term and price, unless auto-renew is turned off at least 24 hours before the end of the current period.".localized)
                         .foregroundColor(UIColor.lesserText.color)
                 }
                 .multilineTextAlignment(.center).font(.font(size: 8))
@@ -425,7 +424,7 @@ struct PurchaseView :View {
                 }
                 
                 Spacer().frame(height: 6.0)
-
+                
                 HStack(spacing: 8) {
                     Text("Terms of us".localized)
                         .onTapGesture {

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

@@ -19,6 +19,10 @@ enum TSNeURLType:String {
     case chatV2 = "/api/text/chat/v2"             //AI 对话接口V2,扩展了 DeepSeek 深度思考
     
     case config = "/api/ops/aichat-config"       //App配置
+    
+    case changeAge = "/api/image/change-age"       //换年龄
+
+    
     func getUrlString() -> String {
         return baseURL + self.rawValue
     }