Pārlūkot izejas kodu

3.6.14(2)预测宝宝

100Years 2 nedēļas atpakaļ
vecāks
revīzija
1b813c089a
28 mainītis faili ar 781 papildinājumiem un 102 dzēšanām
  1. 34 10
      AIEmoji.xcodeproj/project.pbxproj
  2. 22 0
      AIEmoji/Assets.xcassets/AIList/aiList_futureBaby.imageset/Contents.json
  3. BIN
      AIEmoji/Assets.xcassets/AIList/aiList_futureBaby.imageset/aiList_futureBaby@2x.png
  4. BIN
      AIEmoji/Assets.xcassets/AIList/aiList_futureBaby.imageset/aiList_futureBaby@3x.png
  5. 22 0
      AIEmoji/Assets.xcassets/AIList/hint/ptp_futureBaby_goodImage.imageset/Contents.json
  6. BIN
      AIEmoji/Assets.xcassets/AIList/hint/ptp_futureBaby_goodImage.imageset/ptp_futureBaby_goodImage@2x.png
  7. BIN
      AIEmoji/Assets.xcassets/AIList/hint/ptp_futureBaby_goodImage.imageset/ptp_futureBaby_goodImage@3x.png
  8. 6 1
      AIEmoji/Business/Data/TSDBHistoryManager.swift
  9. 13 0
      AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIListHintBaseVC.swift
  10. 11 0
      AIEmoji/Business/TSAILIstVC/TSAILIstVC/TSAILIstVC.swift
  11. 2 0
      AIEmoji/Business/TSAILIstVC/TSAIListHistoryBaseVC/TSAIListHistoryBaseVC.swift
  12. 44 6
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift
  13. 101 75
      AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift
  14. 12 4
      AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift
  15. 164 0
      AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSFutureBabyVC.swift
  16. 19 0
      AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSFutureBabyVM.swift
  17. 77 0
      AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSPredictBabyStyleView.swift
  18. 176 0
      AIEmoji/Business/VIewTool/TSAISmallUploadView/TSAISmallUploadView.swift
  19. 6 6
      AIEmoji/Common/Purchase/TSPurchaseManager.swift
  20. 8 0
      AIEmoji/de.lproj/Localizable.strings
  21. 8 0
      AIEmoji/en.lproj/Localizable.strings
  22. 8 0
      AIEmoji/es.lproj/Localizable.strings
  23. 8 0
      AIEmoji/ja.lproj/Localizable.strings
  24. 8 0
      AIEmoji/ko.lproj/Localizable.strings
  25. 8 0
      AIEmoji/pt-BR.lproj/Localizable.strings
  26. 8 0
      AIEmoji/pt-PT.lproj/Localizable.strings
  27. 8 0
      AIEmoji/zh-Hans.lproj/Localizable.strings
  28. 8 0
      AIEmoji/zh-Hant.lproj/Localizable.strings

+ 34 - 10
AIEmoji.xcodeproj/project.pbxproj

@@ -149,6 +149,10 @@
 		A88508B62DBF142B000FBCEC /* TSGennertatorSelectStyleVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88508B52DBF142A000FBCEC /* TSGennertatorSelectStyleVC.swift */; };
 		A8990DE92DDF241500DD55FE /* TYCycleImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990DE82DDF241300DD55FE /* TYCycleImageView.swift */; };
 		A8990E022DE1800100DD55FE /* launch.png in Resources */ = {isa = PBXBuildFile; fileRef = A8990E012DE1800100DD55FE /* launch.png */; };
+		A8990EE52DEE8C2300DD55FE /* TSAISmallUploadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990EE42DEE8C2200DD55FE /* TSAISmallUploadView.swift */; };
+		A8990EE82DEE8CC200DD55FE /* TSFutureBabyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990EE72DEE8CBF00DD55FE /* TSFutureBabyVC.swift */; };
+		A8990EEA2DEE8CDC00DD55FE /* TSFutureBabyVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990EE92DEE8CD900DD55FE /* TSFutureBabyVM.swift */; };
+		A8990EEC2DEE8EED00DD55FE /* TSPredictBabyStyleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990EEB2DEE8EE200DD55FE /* TSPredictBabyStyleView.swift */; };
 		A899D34A2D827A0E00AB9C1C /* TSChatThinkingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A899D3492D8279FB00AB9C1C /* TSChatThinkingModel.swift */; };
 		A89EA64B2D59A588000EB181 /* MessageKit in Frameworks */ = {isa = PBXBuildFile; productRef = A89EA64A2D59A588000EB181 /* MessageKit */; };
 		A89EA6542D59A9F4000EB181 /* TSTextLayoutSizeCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A89EA64F2D59A9F4000EB181 /* TSTextLayoutSizeCalculator.swift */; };
@@ -439,6 +443,10 @@
 		A88508B52DBF142A000FBCEC /* TSGennertatorSelectStyleVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGennertatorSelectStyleVC.swift; sourceTree = "<group>"; };
 		A8990DE82DDF241300DD55FE /* TYCycleImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TYCycleImageView.swift; sourceTree = "<group>"; };
 		A8990E012DE1800100DD55FE /* launch.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = launch.png; sourceTree = "<group>"; };
+		A8990EE42DEE8C2200DD55FE /* TSAISmallUploadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAISmallUploadView.swift; sourceTree = "<group>"; };
+		A8990EE72DEE8CBF00DD55FE /* TSFutureBabyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSFutureBabyVC.swift; sourceTree = "<group>"; };
+		A8990EE92DEE8CD900DD55FE /* TSFutureBabyVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSFutureBabyVM.swift; sourceTree = "<group>"; };
+		A8990EEB2DEE8EE200DD55FE /* TSPredictBabyStyleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPredictBabyStyleView.swift; sourceTree = "<group>"; };
 		A899D3492D8279FB00AB9C1C /* TSChatThinkingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSChatThinkingModel.swift; sourceTree = "<group>"; };
 		A89EA64C2D59A9F4000EB181 /* CustomMessageFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomMessageFlowLayout.swift; sourceTree = "<group>"; };
 		A89EA64E2D59A9F4000EB181 /* TSLayoutSizeCalculator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSLayoutSizeCalculator.swift; sourceTree = "<group>"; };
@@ -1352,6 +1360,24 @@
 			path = TSGennertatorSelectStyleVC;
 			sourceTree = "<group>";
 		};
+		A8990EE32DEE8C0B00DD55FE /* TSAISmallUploadView */ = {
+			isa = PBXGroup;
+			children = (
+				A8990EE42DEE8C2200DD55FE /* TSAISmallUploadView.swift */,
+			);
+			path = TSAISmallUploadView;
+			sourceTree = "<group>";
+		};
+		A8990EE62DEE8CBA00DD55FE /* TSPredictBabyVC */ = {
+			isa = PBXGroup;
+			children = (
+				A8990EEB2DEE8EE200DD55FE /* TSPredictBabyStyleView.swift */,
+				A8990EE92DEE8CD900DD55FE /* TSFutureBabyVM.swift */,
+				A8990EE72DEE8CBF00DD55FE /* TSFutureBabyVC.swift */,
+			);
+			path = TSPredictBabyVC;
+			sourceTree = "<group>";
+		};
 		A899D3482D8279E500AB9C1C /* CHatMessageModel */ = {
 			isa = PBXGroup;
 			children = (
@@ -1522,6 +1548,7 @@
 		A8BA765F2DA6479A000B6707 /* TSAILIstVC */ = {
 			isa = PBXGroup;
 			children = (
+				A8990EE62DEE8CBA00DD55FE /* TSPredictBabyVC */,
 				A82D60772DB7703000596190 /* TSAIExpandImageVC */,
 				A8D6383A2DB1FC6E00A96C0E /* TSAIListVideoPlayerVC */,
 				A8F413562DA8E500001E715A /* TSAIChangeEmoteVC */,
@@ -1833,11 +1860,11 @@
 		A8F775332D38FC8E00AA6E93 /* VIewTool */ = {
 			isa = PBXGroup;
 			children = (
+				A8990EE32DEE8C0B00DD55FE /* TSAISmallUploadView */,
 				A83404DC2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift */,
 				A89EA6B92D5DDE4E000EB181 /* TSPageNullView.swift */,
 				A8F7763B2D3B429A00AA6E93 /* TSCommonloadingView.swift */,
 				A81BECA42DD1EF91005D06A2 /* TSGeneratorloadingView */,
-				A8F776282D3A709200AA6E93 /* UILabel */,
 				A8F775342D38FC9A00AA6E93 /* TSViewTool.swift */,
 			);
 			path = VIewTool;
@@ -1933,13 +1960,6 @@
 			path = View;
 			sourceTree = "<group>";
 		};
-		A8F776282D3A709200AA6E93 /* UILabel */ = {
-			isa = PBXGroup;
-			children = (
-			);
-			path = UILabel;
-			sourceTree = "<group>";
-		};
 		A8F776292D3A70AA00AA6E93 /* UILabel */ = {
 			isa = PBXGroup;
 			children = (
@@ -2283,6 +2303,7 @@
 				A80EDD4D2D6C3F82003CD332 /* MarkdownStrikethrough.swift in Sources */,
 				A80EDD4E2D6C3F82003CD332 /* MarkdownUnescaping.swift in Sources */,
 				A80EDD4F2D6C3F82003CD332 /* MarkdownParser+UIKit.swift in Sources */,
+				A8990EEC2DEE8EED00DD55FE /* TSPredictBabyStyleView.swift in Sources */,
 				A88508882DBCD944000FBCEC /* MemoryLeakChecker.swift in Sources */,
 				A8F4134A2DA75863001E715A /* TSUploadPhotoPrivacyAlertVC.swift in Sources */,
 				A80EDD502D6C3F82003CD332 /* MarkdownFont+Traits.swift in Sources */,
@@ -2290,6 +2311,7 @@
 				A875870F2D81689A00286A66 /* TSPTPEnterView.swift in Sources */,
 				A80EDD522D6C3F82003CD332 /* MarkdownCode+AppKit.swift in Sources */,
 				A82D60832DB87D1A00596190 /* TSAIExpandChangeView.swift in Sources */,
+				A8990EE52DEE8C2300DD55FE /* TSAISmallUploadView.swift in Sources */,
 				A80EDD532D6C3F82003CD332 /* MarkdownHeader.swift in Sources */,
 				A80EDD542D6C3F82003CD332 /* MarkdownQuote.swift in Sources */,
 				A80EDD552D6C3F82003CD332 /* UIFont+Traits.swift in Sources */,
@@ -2301,6 +2323,7 @@
 				A80EDD5A2D6C3F82003CD332 /* MarkdownParser.swift in Sources */,
 				A80EDD5B2D6C3F82003CD332 /* MarkdownCommonElement.swift in Sources */,
 				A82D60792DB7703D00596190 /* TSAIExpandImageVC.swift in Sources */,
+				A8990EE82DEE8CC200DD55FE /* TSFutureBabyVC.swift in Sources */,
 				A80EDD682D6C5098003CD332 /* TSChatMsgBaseView.swift in Sources */,
 				A8BA764F2DA50B52000B6707 /* CpuMapManager.swift in Sources */,
 				A8BA766C2DA657E8000B6707 /* TSAIListPhotoGeneratorBaseVC.swift in Sources */,
@@ -2395,6 +2418,7 @@
 				A87587182D81814500286A66 /* TSAIThinkingView.swift in Sources */,
 				A85E47962D672ADA0018D62D /* TSTextPicGennerateVC.swift in Sources */,
 				A82D60A02DBA1B0500596190 /* TSImageGenerateView.swift in Sources */,
+				A8990EEA2DEE8CDC00DD55FE /* TSFutureBabyVM.swift in Sources */,
 				A80E72562D3F98D700C64288 /* TSDiyKeyboardViewVC.swift in Sources */,
 				A8F775032D38EA8C00AA6E93 /* GlobalImports.swift in Sources */,
 				A89EA67A2D59D25F000EB181 /* TSAIChatVM.swift in Sources */,
@@ -2536,7 +2560,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 3.6.13;
+				MARKETING_VERSION = 3.6.14;
 				PRODUCT_BUNDLE_IDENTIFIER = com.girl.music.wallpaper;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -2575,7 +2599,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 3.6.13;
+				MARKETING_VERSION = 3.6.14;
 				PRODUCT_BUNDLE_IDENTIFIER = com.girl.music.wallpaper;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

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

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

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


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


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

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

BIN
AIEmoji/Assets.xcassets/AIList/hint/ptp_futureBaby_goodImage.imageset/ptp_futureBaby_goodImage@2x.png


BIN
AIEmoji/Assets.xcassets/AIList/hint/ptp_futureBaby_goodImage.imageset/ptp_futureBaby_goodImage@3x.png


+ 6 - 1
AIEmoji/Business/Data/TSDBHistoryManager.swift

@@ -26,7 +26,7 @@ enum TSDBHistoryType: String,CaseIterable {
     case photoQuality = "kTSAIPhotoQualityHistoryListString"   //照片变高清
     case motherDay = "kTSAIMotherDayHistoryListString"   //母亲节
     case catTohuman = "kTSAICatTohumanHistoryListString"   //猫变人
-    
+    case futureBaby = "kTSAIFutureBabyHistoryListString"   //预测宝宝
 }
 
 
@@ -312,5 +312,10 @@ extension TSRealmManager {
     var catTohumanDBHistory:TSDBHistory {
         return getDBHistory(type: TSDBHistoryType.catTohuman)
     }
+    
+    //预测宝宝
+    var futureBabyDBHistory:TSDBHistory {
+        return getDBHistory(type: TSDBHistoryType.futureBaby)
+    }
 }
 

+ 13 - 0
AIEmoji/Business/TSAILIstVC/TSAIAgeImageHintVC/TSAIListHintBaseVC.swift

@@ -77,6 +77,19 @@ class TSAIListHintBaseVC: TSBaseVC {
                           badText: "Bad photo examples".localized,
                           badInfoText: "No clear faces or group shots".localized)
         }
+        
+        
+        static var futureBabyConfig:Config {
+            return Config(imageMaxBitSize: kUploadImageMaxBit10Size,
+                          goodImageNamed: "ptp_futureBaby_goodImage",
+                          badImageNamed: "ptp_badImage",
+                          titleText: "Upload your photos".localized,
+                          titleSubText: "",
+                          goodText: "Good photo examples".localized,
+                          goodInfoText: "Fully clear and visible face, in good lighting".localized,
+                          badText: "Bad photo examples".localized,
+                          badInfoText: "Group photos, covered faces, nudes".localized)
+        }
     }
     
     var config:Config = Config.defaultConfig

+ 11 - 0
AIEmoji/Business/TSAILIstVC/TSAILIstVC/TSAILIstVC.swift

@@ -12,6 +12,17 @@ class TSAILIstVC: TSBaseVC {
         let sectionModel = TSBasicSectionModel()
         dataArray.append(sectionModel)
 
+        //预测宝宝
+        sectionModel.addSubItemModel(createItemModel(
+            leftImageName:"aiList_futureBaby",
+            leftTitle: "AI Baby Generator".localized,
+            leftSubTitle: "To see what will your future baby look like".localized,
+            rightViewStyle: 0,
+            tapBlock: { [weak self] model, _, _ in
+               guard let self = self else { return }
+                kPushVC(target: self, modelVC: TSFutureBabyVC())
+            }))
+        
         //猫咪变人
         let catTohumanItemModel = createItemModel(
             leftImageName:"aiList_catTohuman",

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

@@ -147,6 +147,8 @@ extension TSAIListHistoryBaseVC{
             TSRMShared.motherDayDBHistory
         case .catTohuman:
             TSRMShared.catTohumanDBHistory
+        case .futureBaby:
+            TSRMShared.futureBabyDBHistory
         }
     }
     

+ 44 - 6
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIListPhotoGeneratorBaseVC.swift

@@ -4,24 +4,31 @@
 //
 //  Created by 100Years on 2025/4/9.
 //
-
+import Kingfisher
 struct TSAIListPhotoGeneratorModel {
     var upLoadImage:UIImage
     var generatorStyle:TSGeneratorImageStyle
     var expandEdge:UIEdgeInsets
     var expandViewSizes:(CGSize,CGSize)?
     var additionalPrompt:String//追加的提示词
+    
+    //预测宝宝
+    var upLoadImages:[UIImage]?
+    
+    
     init(upLoadImage: UIImage,
          generatorStyle: TSGeneratorImageStyle,
          expandEdge:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0),
          expandViewSizes:(CGSize,CGSize)? = nil,
-         additionalPrompt:String = ""
+         additionalPrompt:String = "",
+         upLoadImages:[UIImage]? = nil
     ) {
         self.upLoadImage = upLoadImage
         self.generatorStyle = generatorStyle
         self.expandEdge = expandEdge
         self.expandViewSizes = expandViewSizes
         self.additionalPrompt = additionalPrompt
+        self.upLoadImages = upLoadImages
     }
 }
 
@@ -86,6 +93,23 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
         return switchOriginalPictureBtn
     }()
     
+    lazy var rotatingPictureBtn: TSUIExpandedTouchButton = {
+        let rotatingPictureBtn = TSUIExpandedTouchButton()
+        rotatingPictureBtn.setUpButton(image:UIImage(named: "rotating_picture")){ [weak self]  in
+            guard let self = self else { return }
+            //旋转图片并储存
+            if let image = netWorkImageView.image?.rotated(by: .degrees90) {
+                netWorkImageView.image = image
+                if let resultUrl = self.imageModel?.response.resultUrl,
+                   let url = URL(string: resultUrl){
+                    ImageCache.default.store(image, forKey: url.cacheKey)
+                }
+            }
+        }
+        rotatingPictureBtn.isHidden = true
+        return rotatingPictureBtn
+    }()
+    
     override func createView() {
 
         contentView.addSubview(generateInView)
@@ -103,6 +127,14 @@ class TSAIListPhotoGeneratorBaseVC: TSAIPhotoGeneratorBaseVC {
             make.height.equalTo(40)
         }
         
+        contentView.addSubview(rotatingPictureBtn)
+        rotatingPictureBtn.snp.makeConstraints { make in
+            make.bottom.equalTo(-k_Height_safeAreaInsetsBottom() - 76)
+            make.trailing.equalTo(-16)
+            make.width.equalTo(40)
+            make.height.equalTo(40)
+        }
+        
         bigSaveBtn.setTitleImageSpace(spacing: 0)
         
         if viewModel.generatorModel.generatorStyle == .photoExpand {
@@ -277,7 +309,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         bottomView.isHidden = true
         netWorkImageView.isHidden = true
         switchOriginalPictureBtn.isHidden = true
-        
+        rotatingPictureBtn.isHidden = true
         setVideoHidden()
     }
     
@@ -288,7 +320,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         bottomView.isHidden = true
         netWorkImageView.isHidden = true
         switchOriginalPictureBtn.isHidden = true
-        
+        rotatingPictureBtn.isHidden = true
         setVideoHidden()
     }
     
@@ -302,7 +334,7 @@ extension TSAIListPhotoGeneratorBaseVC {
         bottomView.isHidden = true
         netWorkImageView.isHidden = true
         switchOriginalPictureBtn.isHidden = true
-        
+        rotatingPictureBtn.isHidden = true
         setVideoHidden()
     }
     
@@ -316,7 +348,13 @@ extension TSAIListPhotoGeneratorBaseVC {
         bigSaveBtn.isHidden = false
         bottomView.isHidden = false
         netWorkImageView.isHidden = false
-        switchOriginalPictureBtn.isHidden = false
+        
+        if viewModel.generatorModel.generatorStyle == .futureBaby {
+            rotatingPictureBtn.isHidden = false
+        }else{
+            switchOriginalPictureBtn.isHidden = false
+        }
+        
         isSavePhotoMark = false
         self.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!)
         

+ 101 - 75
AIEmoji/Business/TSAILIstVC/TSAIPhotoGeneratorBaseVC/TSAIPhotoGeneratorBaseVM/TSAIListPhotoGeneratorBaseVM.swift

@@ -30,9 +30,9 @@ class TSAIListPhotoGeneratorBaseVM {
     var stopNetwork = false
     
     @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
-    var generatingProgress = 0
     
     var imageUrl:String?
+    var imageUrls:[String]?
     var generatorModel:TSAIListPhotoGeneratorModel
     init(generatorModel:TSAIListPhotoGeneratorModel) {
         self.generatorModel = generatorModel
@@ -68,7 +68,12 @@ class TSAIListPhotoGeneratorBaseVM {
 //    }
     
     func uploadAndCreatImage() {
-        
+        //上传多个图片
+        if let _ = generatorModel.upLoadImages {
+            uploadImagesAndCreat()
+            return
+        }
+        //上传单个图片
         if let imageUrl = imageUrl,imageUrl.contains("http") {
             creatImage()
             return
@@ -80,9 +85,9 @@ class TSAIListPhotoGeneratorBaseVM {
         stateDatauPblished = (.progressString(uploadingPhoto(progress: 0.0)),nil)
         uploadRequest = TSNetworkShared.uploadImage(upLoadImage: generatorModel.upLoadImage, maxKb: generatorModel.generatorStyle.imageMaxKb) { [weak self]  progress in
             guard let self = self else { return }
-            if generatingProgress == 0 {
-                stateDatauPblished = (.progressString(uploadingPhoto(progress: progress)),nil)
-            }
+          
+            stateDatauPblished = (.progressString(uploadingPhoto(progress: progress)),nil)
+            
         } completion: { [weak self]  data, error in
             guard let self = self else { return }
             if let error = error {
@@ -97,79 +102,106 @@ class TSAIListPhotoGeneratorBaseVM {
         }
     }
     
+    private func uploadImagesAndCreat() {
+        
+        if let imageUrls = imageUrls{
+            creatImage()
+            return
+        }
+        guard let upLoadImages = generatorModel.upLoadImages else { return }
+        var uploadImageUrls:[String] = []
+        let progressRatio:Float = 1.0/Float(upLoadImages.count)//进度分割比例
+        var totalProgress:Float = 0.0//总进度
+        stopNetwork = false
+        stateDatauPblished = (.start,nil)
+        stateDatauPblished = (.progressString(uploadingPhoto(progress: 0.0)),nil)
+        
+        let group = DispatchGroup()
+        for image in upLoadImages {
+            group.enter()
+            uploadRequest = TSNetworkShared.uploadImage(upLoadImage: image, maxKb: generatorModel.generatorStyle.imageMaxKb) { [weak self]  progress in
+                guard let self = self else { return }
+                totalProgress+=progress*progressRatio
+                stateDatauPblished = (.progressString(uploadingPhoto(progress: totalProgress)),nil)
+            } completion: { [weak self]  data, error in
+                guard let self = self else { return }
+                if let error = error {
+                    self.imageUrls = nil
+                    self.stateDatauPblished = (TSProgressState.getFailed(error.tsDesc,error.tsCode),nil)
+                }else{
+                    if let string = data as? String {
+                        uploadImageUrls.append(string)
+                    }
+                }
+                group.leave()
+            }
+        }
+
+        group.notify(queue: .main) {
+            if uploadImageUrls.count == upLoadImages.count {
+                self.imageUrls = uploadImageUrls
+                self.imageUrl = ""
+                self.creatImage()
+            }
+        }
+    }
+    
+    
     func creatImage() {
         guard let imageUrl = imageUrl else { return }
-        generatingProgress = 0
         stopNetwork = false
         stateDatauPblished = (.start,nil)
         stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
         
         var urlType:TSNeURLType = .changeAge
-        var postDict:[String:Any] = [:]
+        var postDict:[String:Any] = [
+            "device":getUserInfoJsonString(),
+            "imageUrl":imageUrl
+        ]
         switch generatorModel.generatorStyle {
-            case .ageOld:
-            postDict = ["targetAge":70,
-                        "imageUrl":imageUrl,
-                        "device":getUserInfoJsonString()
-                       ]
-            case .ageChild:
-            postDict = ["targetAge":5,
-                        "imageUrl":imageUrl,
-                        "device":getUserInfoJsonString()
-                       ]
-            case .oldPhoto:
-            urlType = .imageRestore
-            postDict = ["imageUrl":imageUrl,
-                        "device":getUserInfoJsonString()
-                       ]
-            case .eyeOpen:
-            urlType = .eyeOpen
-            postDict = ["imageUrl":imageUrl,
-                        "device":getUserInfoJsonString()
-                       ]
-            case .pretty:
-            urlType = .pretty
-            postDict = ["imageUrl":imageUrl,
-                        "level":1.0,
-                        "device":getUserInfoJsonString()
+        case .ageOld:
+        postDict = ["targetAge":70
+                   ]
+        case .ageChild:
+        postDict = ["targetAge":5
+                   ]
+        case .oldPhoto:
+        urlType = .imageRestore
+        case .eyeOpen:
+        urlType = .eyeOpen
+        case .pretty:
+        urlType = .pretty
+        postDict = ["level":1.0]
+        case .photoLive:
+            urlType = .photoAnimation
+        case .photoExpand:
+            urlType = .photoExpand
+            postDict = ["prompt":"高清智能扩图上传的照片,无缝衔接,自然延伸,风格一致,内容协调,细节丰富,过渡平滑,色彩统一,符合原图,合理补全",
+                        "top":generatorModel.expandEdge.top,
+                        "left":generatorModel.expandEdge.left,
+                        "bottom":generatorModel.expandEdge.bottom,
+                        "right":generatorModel.expandEdge.right
                        ]
-            case .photoLive:
-                urlType = .photoAnimation
-                postDict = ["imageUrl":imageUrl,
-                            "device":getUserInfoJsonString()
-                           ]
-            case .photoExpand:
-                urlType = .photoExpand
-                postDict = ["imageUrl":imageUrl,
-                            "prompt":"高清智能扩图上传的照片,无缝衔接,自然延伸,风格一致,内容协调,细节丰富,过渡平滑,色彩统一,符合原图,合理补全",
-                            "device":getUserInfoJsonString(),
-                            "top":generatorModel.expandEdge.top,
-                            "left":generatorModel.expandEdge.left,
-                            "bottom":generatorModel.expandEdge.bottom,
-                            "right":generatorModel.expandEdge.right
-                           ]
-            case .photoQuality:
-//                urlType = .overResolution
-//                postDict = ["imageUrl":imageUrl,
-//                            "device":getUserInfoJsonString()
-//                           ]
-                urlType = .imageRewrite
-                postDict = ["prompt":"提高上传图片的清晰度,不要改变任何",
-                            "imageUrl":imageUrl,
-                            "device":getUserInfoJsonString(),
-                            "advance": generatorModel.generatorStyle.advance]
-            case .motherDay:
-                urlType = .imageRewrite
-                postDict = ["prompt":"把照片转化为Q版人物形象,3D黏土风,是真实世界的光影,保留原始人物数量和细节,包括服装和造型。整体放在一张拍立得照片中,有一只手握着拍立得相纸。图中角色从拍立得相纸中,突破边框,延伸进入现实世界的二维空间。背景要温馨,包含母亲节快乐的元素。处理掉异常现象如半个物体",
-                            "imageUrl":imageUrl,
-                            "device":getUserInfoJsonString(),
-                            "advance": generatorModel.generatorStyle.advance]
-            case .catTohuman:
-                urlType = .imageRewrite
-                postDict = ["prompt":"Turn my pets into a human" + generatorModel.additionalPrompt,
-                            "imageUrl":imageUrl,
-                            "device":getUserInfoJsonString(),
-                            "advance": generatorModel.generatorStyle.advance]
+        case .photoQuality:
+            urlType = .imageRewrite
+            postDict = ["prompt":"提高上传图片的清晰度,不要改变任何",
+                        "advance": generatorModel.generatorStyle.advance]
+        case .motherDay:
+            urlType = .imageRewrite
+            postDict = ["prompt":"把照片转化为Q版人物形象,3D黏土风,是真实世界的光影,保留原始人物数量和细节,包括服装和造型。整体放在一张拍立得照片中,有一只手握着拍立得相纸。图中角色从拍立得相纸中,突破边框,延伸进入现实世界的二维空间。背景要温馨,包含母亲节快乐的元素。处理掉异常现象如半个物体",
+                        "advance": generatorModel.generatorStyle.advance]
+        case .catTohuman:
+            urlType = .imageRewrite
+            postDict = ["prompt":"Turn my pets into a human" + generatorModel.additionalPrompt,
+                        "advance": generatorModel.generatorStyle.advance]
+        case .futureBaby:
+            guard let imageUrls = imageUrls else { return }
+            urlType = .imageRewrite
+            postDict = ["prompt":"AI-generated a child, blending the uploaded photo's parents' facial features, balanced genetic traits, realistic portrait, age-progression, gender-appropriate stylish clothing, playful yet natural expression, family resemblance, high-detail rendering, soft lighting." + generatorModel.additionalPrompt,
+                        "advance": generatorModel.generatorStyle.advance,
+                        "imageUrls":imageUrls
+                        ]
+            postDict.removeValue(forKey: "imageUrl")
         }
         creatRequest = TSNetworkShared.post(urlType: urlType,parameters: postDict) { [weak self] data,error in
             guard let self = self else { return }
@@ -209,27 +241,22 @@ class TSAIListPhotoGeneratorBaseVM {
                                         }
 
                                         self.stateDatauPblished = (.success(nil),genmojiModel)
-                                        self.generatingProgress = 0
                                     }else{
                                         self.stateDatauPblished = (.generalNormalFailed,nil)
-                                        self.generatingProgress = 0
                                     }
                                 }
                             }else {
                                 downloadImage(urlString: genmojiModel.response.resultUrl) { [weak self] in
                                     guard let self = self else { return }
                                     self.stateDatauPblished = (.success(nil),genmojiModel)
-                                    generatingProgress = 0
                                 }
                             }
                         }else{
                             self.stateDatauPblished = (.success(nil),genmojiModel)
-                            generatingProgress = 0
                         }
                         
                     case .failed:
                         self.stateDatauPblished = (TSProgressState.getFailed(genmojiModel.response.codeErrorMsg,genmojiModel.response.code),nil)
-                        generatingProgress = 0
                     default:
                         stateDatauPblished = (.progressString(generating(progress: genmojiModel.percent)),nil)
                         if stopNetwork == false {
@@ -297,7 +324,6 @@ class TSAIListPhotoGeneratorBaseVM {
             progressInt = 99
         }
         
-        generatingProgress = progressInt
         return generatingText + " \(progressInt)%"
     }
     

+ 12 - 4
AIEmoji/Business/TSAILIstVC/TSAIUploadPhotoBaseVC/TSAIUploadPhotoBaseVC.swift

@@ -18,7 +18,7 @@ enum TSGeneratorImageStyle {
     case photoQuality    //照片变高清
     case motherDay    //母亲节
     case catTohuman    //猫变人
-    
+    case futureBaby    //预测宝宝
     
     
     var imageMaxKb:Int{
@@ -43,6 +43,8 @@ enum TSGeneratorImageStyle {
             return 10*1024
         case .catTohuman:
             return 10*1024
+        case .futureBaby:
+            return 10*1024
         }
     }
     
@@ -68,6 +70,8 @@ enum TSGeneratorImageStyle {
             return kUploadImageMaxBit10Size
         case .catTohuman:
             return kUploadImageMaxBit10Size
+        case .futureBaby:
+            return kUploadImageMaxBit10Size
         }
     }
     
@@ -93,6 +97,8 @@ enum TSGeneratorImageStyle {
             return "isFirstAIMotherDay"
         case .catTohuman:
             return "isFirstAICatTohuman"
+        case .futureBaby:
+            return "isFirstAIFutureBaby"
         }
     }
     
@@ -118,12 +124,14 @@ enum TSGeneratorImageStyle {
             return .getDefaultConfig(imageMaxBitSize: imageMaxBitSize)
         case .catTohuman:
             return .catTohumanConfig
+        case .futureBaby:
+            return .futureBabyConfig
         }
     }
     
     var advance:Bool{
         switch self {
-        case .catTohuman,.motherDay:
+        case .catTohuman,.motherDay,.futureBaby:
             return true
         default:
             return false
@@ -469,8 +477,8 @@ extension TSAIUploadPhotoBaseVC {
             TSRMShared.prettyDBHistory.updateData(model)
         case .photoLive:
             TSRMShared.photoLiveDBHistory.updateData(model)
-        case .photoExpand:
-            dePrint("photoExpand")
+        case .photoExpand,.futureBaby:
+            dePrint("--")
         case .photoQuality:
             TSRMShared.photoQualityDBHistory.updateData(model)
         case .motherDay:

+ 164 - 0
AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSFutureBabyVC.swift

@@ -0,0 +1,164 @@
+//
+//  TSPredictBabyVC.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+import Combine
+class TSFutureBabyVC: TSBaseVC{
+
+    lazy var viewModel: TSFutureBabyVM = {
+        let viewModel = TSFutureBabyVM()
+        return viewModel
+    }()
+    @Published private(set) var isCanGennerate: Bool = false
+    lazy var customStackView: TSCustomStackView = {
+        let customStackView = TSCustomStackView(axis: .vertical)
+        return customStackView
+    }()
+
+    //##############################上传图片##############################
+    lazy var imageStackView: TSCustomStackView = {
+        let imageStackView = TSCustomStackView(axis: .horizontal,alignment: .center,spacing: 0.0)
+        return imageStackView
+    }()
+    
+    lazy var personUploadView: TSAISmallUploadView = {
+        let personUploadView = TSAISmallUploadView()
+        personUploadView.targetVC = self
+        personUploadView.titleLab.text = "Parent1".localized
+        return personUploadView
+    }()
+    
+    lazy var garmentUploadView: TSAISmallUploadView = {
+        let garmentUploadView = TSAISmallUploadView()
+        garmentUploadView.targetVC = self
+        garmentUploadView.titleLab.text = "Parent2".localized
+        return garmentUploadView
+    }()
+    //##############################选性别##############################
+    lazy var genderStyleView: TSPredictBabyStyleView = {
+        let genderStyleView = TSPredictBabyStyleView(title: "Gender".localized, styles: ["Female".localized,"Male".localized,"Random".localized])
+        return genderStyleView
+    }()
+    
+    lazy var ageStyleView: TSPredictBabyStyleView = {
+        let genderStyleView = TSPredictBabyStyleView(title: "Age".localized, styles: ["3-5".localized,"5-10","15-18"])
+        return genderStyleView
+    }()
+    
+    //##############################按钮##############################
+    lazy var submitBtn: UIButton = {
+        let submitBtn = kCreateNormalSubmitBtn(title: "Generate".localized) { [weak self]  in
+            guard let self = self else { return }
+            generateImage()
+        }
+        submitBtn.cornerRadius = 24.0
+        return submitBtn
+    }()
+    override func createView() {
+        
+        addNormalNavBarView()
+        setPageTitle("Future Baby".localized)
+        _ = setNavigationItem("", imageName: "aichat_history", direction: .right, action: #selector(clickNavRight))
+        
+        contentView.addSubview(submitBtn)
+        submitBtn.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.width.equalTo(250*kDesignScale)
+            make.height.equalTo(48)
+            make.bottom.equalTo(-10-k_Height_safeAreaInsetsBottom())
+        }
+        
+        contentView.addSubview(customStackView)
+        customStackView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.leading.trailing.equalToSuperview()
+            make.bottom.equalTo(submitBtn.snp.top).offset(-10)
+        }
+        
+        let upImageW = (k_ScreenWidth - 32.0 - 10.0) / 2.0
+        let upImageH = personUploadView.viewH
+        
+        customStackView.addSubviewToStack(imageStackView,length: upImageH)
+        imageStackView.addSpacing(length: 16.0)
+        imageStackView.addSubviewToStack(personUploadView,length: upImageW)
+        imageStackView.addSpacing(length: 10.0)
+        imageStackView.addSubviewToStack(garmentUploadView,length: upImageW)
+        customStackView.addSpacing(length: 24.0)
+        customStackView.addSubviewToStack(genderStyleView, length: 80.0)
+        customStackView.addSubviewToStack(ageStyleView, length: 80.0)
+    }
+    
+    override func dealThings() {
+        Publishers.CombineLatest4(
+            personUploadView.$upLoadImage,
+            garmentUploadView.$upLoadImage,
+            genderStyleView.$selectedStyle,
+            ageStyleView.$selectedStyle
+        )
+        .map { (image1, image2, style1, style2) -> Bool in
+            return image1 != nil && image2 != nil && style1 != nil && style2 != nil
+        }
+        .assign(to: \.isCanGennerate, on: self)
+        .store(in: &cancellable)
+        
+        self.$isCanGennerate.receive(on: DispatchQueue.main).sink { [weak self] enble in
+            guard let self = self else { return }
+            submitBtn.isEnabled = enble
+        }.store(in: &cancellable)
+        
+    }
+}
+
+extension TSFutureBabyVC {
+    
+    @objc func clickNavRight() {
+        kPushVC(target: self, modelVC: TSAIListHistoryBaseVC(generatorStyle: .futureBaby))
+    }
+    
+    func getSex(genderStr:String)->String{
+        if genderStr == "Female".localized {
+            return "female"
+        }else if genderStr == "Male".localized {
+            return "male"
+        }
+        return ""
+    }
+    
+    func generateImage() {
+        if kJudgeVip(externalBool: true, vc: self){ return } //判断 vip
+        
+        guard let upLoadImage1 = personUploadView.upLoadImage else { return }
+        guard let upLoadImage2 = garmentUploadView.upLoadImage else { return }
+        guard let genderStr = genderStyleView.selectedStyle else { return }
+        guard let ageStr = ageStyleView.selectedStyle else { return }
+        let getSex = getSex(genderStr: genderStr)
+        var additionalPrompt = ""
+        if !getSex.isEmpty {
+            additionalPrompt = additionalPrompt + getSex
+        }
+        if !ageStr.isEmpty {
+            additionalPrompt = additionalPrompt + ","+ageStr
+        }
+        
+        let gennerateVC = TSAIListPhotoGeneratorBaseVC(generatorModel:
+            TSAIListPhotoGeneratorModel(
+                upLoadImage: upLoadImage1,
+                generatorStyle: .futureBaby,
+                additionalPrompt: additionalPrompt,
+                upLoadImages: [upLoadImage1,upLoadImage2]
+            )
+        ){ [weak self] model in
+            guard let self = self else { return }
+            saveModel(model: model)
+        }
+        kPresentModalVC(target: self, modelVC: gennerateVC,transitionStyle: .crossDissolve)
+    }
+    
+    func saveModel(model:TSActionInfoModel){
+        TSRMShared.futureBabyDBHistory.updateData(model)
+    }
+
+}

+ 19 - 0
AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSFutureBabyVM.swift

@@ -0,0 +1,19 @@
+//
+//  TSPredictBabyVM.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+import ObjectMapper
+
+
+class TSFutureBabyVM {
+    
+    lazy var sectionDataArray: [TSSimpleSectionData] = {
+        let sectionModel = TSSimpleSectionData()
+        sectionModel.title = "Garment Library".localized
+//        sectionModel.items = selectStyleModels
+        return [sectionModel]
+    }()
+}

+ 77 - 0
AIEmoji/Business/TSAILIstVC/TSPredictBabyVC/TSPredictBabyStyleView.swift

@@ -0,0 +1,77 @@
+//
+//  TSPredictBabyStyleView.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/6/2.
+//
+import Combine
+import BetterSegmentedControl
+class TSPredictBabyStyleView: TSBaseView {
+    
+    @Published var selectedStyle:String?
+    var title:String
+    var styles:[String]
+    init(title: String, styles: [String]) {
+        self.title = title
+        self.styles = styles
+        self.selectedStyle = self.styles.first
+        super.init(frame: .zero)
+    }
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    lazy var titleLabel: UILabel = {
+        let titleLabel = UILabel.createLabel(text: title,font: .font(size: 14,weight: .medium),textColor: .white.withAlphaComponent(0.8))
+        return titleLabel
+    }()
+    
+    
+    lazy var segmentedView: BetterSegmentedControl = {
+        let segmentedView = BetterSegmentedControl(
+            frame: .zero,
+            segments:
+                LabelSegment.segments(
+                    withTitles: styles,
+                    normalFont: .font(size: 12.0),
+                    normalTextColor: .white.withAlphaComponent(0.4),
+                    selectedFont: .font(size: 12.0),
+                    selectedTextColor: "#111111".uiColor),
+            options:[.backgroundColor(.white.withAlphaComponent(0.1)),
+                     .indicatorViewBackgroundColor(.white),
+                     .indicatorViewInset(2),
+                     .cornerRadius(20.0),
+                     .animationSpringDamping(1.0)]
+        )
+        segmentedView.addTarget(self,action: #selector(segmentedControlValueChanged(_:)),for: .valueChanged)
+        return segmentedView
+    }()
+    
+    @objc func segmentedControlValueChanged(_ sender: BetterSegmentedControl) {
+        selectedStyle = styles.safeObj(At: sender.index)
+    }
+    
+    override func creatUI() {
+
+        contentView.addSubview(titleLabel)
+        titleLabel.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.top.equalTo(18)
+        }
+        
+        contentView.addSubview(segmentedView)
+        segmentedView.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.height.equalTo(40)
+            make.top.equalTo(titleLabel.snp.bottom).offset(8)
+            make.bottom.equalTo(0)
+        }
+        
+    }
+    
+
+
+}

+ 176 - 0
AIEmoji/Business/VIewTool/TSAISmallUploadView/TSAISmallUploadView.swift

@@ -0,0 +1,176 @@
+//
+//  TSAISmallUploadView.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+import Combine
+
+class TSAISmallUploadView: TSBaseView {
+    
+    var viewH: CGFloat = 220.0+44.0
+    @Published var upLoadImage:UIImage? = nil {
+        didSet{
+            if let image = upLoadImage {
+                upLoadView.isHidden = true
+                uploadImageView.isHidden = false
+                deleteBtn.isHidden = false
+                uploadImageView.image = image
+            }else {
+                upLoadView.isHidden = false
+                uploadImageView.isHidden = true
+                deleteBtn.isHidden = true
+                uploadImageView.image = nil
+            }
+        }
+    }
+    var hintKey:String = ""
+    var config:TSAIListHintBaseVC.Config = .defaultConfig
+    var clickHandel:((Int)->Void)?
+    weak var targetVC:UIViewController?
+    lazy var titleLab : UILabel = {
+        let titleLab = UILabel.createLabel(font: .font(size: 16),textColor: .white.withAlphaComponent(0.6))
+        return titleLab
+    }()
+    
+    lazy var upLoadView: UIView = {
+        let bgView = UIView()
+        
+        let addImageView = UIImageView.createImageView(imageName: "add")
+        bgView.addSubview(addImageView)
+        addImageView.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+            make.width.height.equalTo(24)
+        }
+        
+        let textLabel = UILabel.createLabel(text: "Upload Photo".localized,font: .font(size: 16),textColor: .white)
+        bgView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.equalTo(addImageView.snp.bottom).offset(16)
+            make.centerX.equalToSuperview()
+            make.bottom.equalToSuperview()
+        }
+        
+        return bgView
+    }()
+
+    lazy var uploadImageView: UIImageView = {
+        let uploadImageView = UIImageView()
+        uploadImageView.contentMode = .scaleAspectFit
+        uploadImageView.cornerRadius = 12
+        upLoadView.isHidden = false
+        return uploadImageView
+    }()
+    
+    
+    lazy var bgView: UIView = {
+        
+        let bgView = UIView()
+        bgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action:#selector(clickBgView)))
+        let bgImageView = UIImageView.createImageView(imageName: "ptp_upload_bg")
+        bgImageView.contentMode = .scaleToFill
+        bgView.addSubview(bgImageView)
+        bgImageView.snp.makeConstraints { make in
+            make.leading.bottom.trailing.top.equalTo(0)
+        }
+
+        bgView.addSubview(upLoadView)
+        upLoadView.snp.makeConstraints { make in
+            make.top.equalTo(88)
+            make.centerX.equalToSuperview()
+        }
+
+        bgView.addSubview(uploadImageView)
+        uploadImageView.snp.makeConstraints { make in
+            make.top.leading.equalTo(8)
+            make.bottom.trailing.equalTo(-8)
+        }
+        
+        return bgView
+    }()
+    
+    
+    lazy var deleteBtn: UIButton = {
+        let deleteBtn = UIButton.createButton(backgroundImage: UIImage(named: "delete_redRound")) { [weak self]  in
+            guard let self = self else { return }
+            upLoadImage = nil
+            clickHandel?(0)
+        }
+        deleteBtn.isHidden = true
+        return deleteBtn
+    }()
+    
+    override func creatUI() {
+        
+        contentView.addSubview(titleLab)
+        titleLab.snp.makeConstraints { make in
+            make.leading.equalTo(0)
+            make.top.equalTo(16)
+        }
+   
+        contentView.addSubview(bgView)
+        bgView.snp.makeConstraints { make in
+            make.leading.equalTo(0)
+            make.trailing.equalTo(0)
+            make.bottom.equalTo(0)
+            make.height.equalTo(220.0)
+            make.top.equalTo(titleLab.snp.bottom).offset(12)
+        }
+        
+        bgView.addSubview(deleteBtn)
+        deleteBtn.snp.makeConstraints { make in
+            make.top.equalTo(-8)
+            make.trailing.equalTo(8)
+            make.width.height.equalTo(32)
+        }
+    }
+    
+
+    @objc func clickBgView() {
+        TSAIListHintBaseVC.userDefaultsKey = hintKey
+        if TSAIListHintBaseVC.isShowUploadImageHint{
+            TSAIListHintBaseVC.isShowUploadImageHint = false
+            self.presentModalHintVC(config:config) { [weak self] image in
+                guard let self = self else { return }
+                upLoadImage = image
+            }
+        }else {
+            self.pickSinglePhoto()
+        }
+    }
+    
+    
+    var photoPickerManager: TSPhotoPickerManager!
+    func pickSinglePhoto()  {
+        if let targetVC = targetVC {
+            photoPickerManager = TSPhotoPickerManager(viewController: targetVC)
+            photoPickerManager.pickCustomSinglePhoto() { [weak self] image, errorString in
+                guard let self = self else { return }
+                if let errorString = errorString {
+                    TSToastShared.showToast(text: errorString)
+                }else{
+                    upLoadImage = image
+                }
+            }
+        }
+    }
+    
+    
+    var hintBaseVC:TSAIListHintBaseVC = TSAIListHintBaseVC(config: .defaultConfig)
+    func presentModalHintVC(config:TSAIListHintBaseVC.Config,complete:@escaping (UIImage)->Void){
+        hintBaseVC = TSAIListHintBaseVC(config: config) { [weak self] image in
+            guard let self = self else { return }
+            if let image = image {
+                complete(image)
+            }else{
+                dePrint("图片异常")
+            }
+            kDelayMainShort {
+                self.hintBaseVC.dismissPageVC()
+            }
+        }
+        kPresentModalVC(target: targetVC!, modelVC: hintBaseVC,transitionStyle: .crossDissolve)
+    }
+}

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

@@ -200,9 +200,9 @@ public class PurchaseManager: NSObject {
     }
 
     @objc public var isVip: Bool {
-//#if DEBUG
-//        return vipType != .none
-//#endif
+#if DEBUG
+        return vipType != .none
+#endif
         guard let expiresDate = expiredDate else {
             return false
         }
@@ -214,9 +214,9 @@ public class PurchaseManager: NSObject {
     }
 
     public var vipType: PremiumPeriod {
-//#if DEBUG
-//        return PremiumPeriod.week
-//#endif
+#if DEBUG
+        return PremiumPeriod.week
+#endif
         guard isVip, let type = vipInformation["type"] as? String else {
             return .none
         }

+ 8 - 0
AIEmoji/de.lproj/Localizable.strings

@@ -404,3 +404,11 @@
 "40+ Photo Styles" = "40+ Fotostile";
 "Change Hairstyle & Color" = "Frisur & Farbe ändern";
 "Photo Enhancer & Restore Old Photo" = "Fotoverbesserer & altes Foto wiederherstellen";
+
+"AI Baby Generator" = "KI-Babygenerator";
+"Gender" = "Geschlecht";
+"Age" = "Alter";
+"Future Baby" = "Zukünftiges Baby";
+"Parent1" = "Elternteil1";
+"Parent2" = "Elternteil2";
+"To see what will your future baby look like" = "Um zu sehen, wie Ihr zukünftiges Baby aussehen wird";

+ 8 - 0
AIEmoji/en.lproj/Localizable.strings

@@ -401,3 +401,11 @@
 "40+ Photo Styles" = "40+ Photo Styles";
 "Change Hairstyle & Color" = "Change Hairstyle & Color";
 "Photo Enhancer & Restore Old Photo" = "Photo Enhancer & Restore Old Photo";
+
+"AI Baby Generator" = "AI Baby Generator";
+"Gender" = "Gender";
+"Age" = "Age";
+"Future Baby" = "Future Baby";
+"Parent1" = "Parent1";
+"Parent2" = "Parent2";
+"To see what will your future baby look like" = "To see what will your future baby look like";

+ 8 - 0
AIEmoji/es.lproj/Localizable.strings

@@ -401,3 +401,11 @@
 "40+ Photo Styles" = "Más de 40 estilos de fotos";
 "Change Hairstyle & Color" = "Cambia el peinado y el color";
 "Photo Enhancer & Restore Old Photo" = "Mejora & restaura fotos antiguas";
+
+"AI Baby Generator" = "Generador de bebés con IA";
+"Gender" = "Género";
+"Age" = "Edad";
+"Future Baby" = "Futuro bebé";
+"Parent1" = "Padre1";
+"Parent2" = "Padre2";
+"To see what will your future baby look like" = "Para ver cómo será tu futuro bebé";

+ 8 - 0
AIEmoji/ja.lproj/Localizable.strings

@@ -400,3 +400,11 @@
 "40+ Photo Styles" = "40+写真スタイル";
 "Change Hairstyle & Color" = "ヘアスタイルと髪色を変更する";
 "Photo Enhancer & Restore Old Photo" = "写真の強化&古い写真の修復";
+
+"AI Baby Generator" = "AIベビージェネレーター";
+"Gender" = "性別";
+"Age" = "年";
+"Future Baby" = "未来の赤ちゃん";
+"Parent1" = "親1";
+"Parent2" = "親2";
+"To see what will your future baby look like" = "将来の赤ちゃんがどんな姿になるかを知るために";

+ 8 - 0
AIEmoji/ko.lproj/Localizable.strings

@@ -406,3 +406,11 @@
 "40+ Photo Styles" = "40+ 사진 스타일";
 "Change Hairstyle & Color" = "헤어스타일 및 머리색 변경";
 "Photo Enhancer & Restore Old Photo" = "사진 개선 & 오래된 사진 복구";
+
+"AI Baby Generator" = "AI 베이비 제너레이터";
+"Gender" = "성별";
+"Age" = "나이";
+"Future Baby" = "미래의 아기";
+"Parent1" = "부모1";
+"Parent2" = "부모2";
+"To see what will your future baby look like" = "미래의 아기가 어떻게 생겼는지 보려면";

+ 8 - 0
AIEmoji/pt-BR.lproj/Localizable.strings

@@ -400,3 +400,11 @@
 "40+ Photo Styles" = "Mais de 40 estilos de fotos";
 "Change Hairstyle & Color" = "Altere o penteado e a cor do cabelo";
 "Photo Enhancer & Restore Old Photo" = "Aprimorador de fotos & restauração de fotos antigas";
+
+"AI Baby Generator" = "Gerador de bebês com IA";
+"Gender" = "Gênero";
+"Age" = "Idade";
+"Future Baby" = "Futuro bebê";
+"Parent1" = "Pai 1";
+"Parent2" = "Pai2";
+"To see what will your future baby look like" = "Para ver como será seu futuro bebê";

+ 8 - 0
AIEmoji/pt-PT.lproj/Localizable.strings

@@ -400,3 +400,11 @@
 "40+ Photo Styles" = "Mais de 40 estilos de fotos";
 "Change Hairstyle & Color" = "Altere o penteado e a cor do cabelo";
 "Photo Enhancer & Restore Old Photo" = "Aprimorador de fotos & restauração de fotos antigas";
+
+"AI Baby Generator" = "Gerador de bebês com IA";
+"Gender" = "Gênero";
+"Age" = "Idade";
+"Future Baby" = "Futuro bebê";
+"Parent1" = "Pai 1";
+"Parent2" = "Pai2";
+"To see what will your future baby look like" = "Para ver como será seu futuro bebê";

+ 8 - 0
AIEmoji/zh-Hans.lproj/Localizable.strings

@@ -402,3 +402,11 @@
 "40+ Photo Styles" = "40+ 照片风格";
 "Change Hairstyle & Color" = "更改发型和颜色";
 "Photo Enhancer & Restore Old Photo" = "照片增强&修复老照片";
+
+"AI Baby Generator" = "AI 预测宝宝";
+"Gender" = "性别";
+"Age" = "年龄";
+"Future Baby" = "预测宝宝";
+"Parent1" = "父母1";
+"Parent2" = "父母2";
+"To see what will your future baby look like" = "看看你未来的宝宝长什么样";

+ 8 - 0
AIEmoji/zh-Hant.lproj/Localizable.strings

@@ -392,3 +392,11 @@
 "40+ Photo Styles" = "40+照片樣式";
 "Change Hairstyle & Color" = "更改髮型和髮色";
 "Photo Enhancer & Restore Old Photo" = "照片增强&修復老照片";
+
+"AI Baby Generator" = "AI 預測寶寶";
+"Gender" = "性別";
+"Age" = "年齡";
+"Future Baby" = "預測寶寶";
+"Parent1" = "父母1";
+"Parent2" = "父母2";
+"To see what will your future baby look like" = "看看你未來的寶寶長什麼樣子";