Переглянути джерело

文生图 App 布局 UI 调整完毕

100Years 3 тижнів тому
батько
коміт
9eb8d0089e
33 змінених файлів з 616 додано та 200 видалено
  1. 20 0
      AIEmoji.xcodeproj/project.pbxproj
  2. 22 0
      AIEmoji/Assets.xcassets/Common/blue_down_arrow.imageset/Contents.json
  3. BIN
      AIEmoji/Assets.xcassets/Common/blue_down_arrow.imageset/blue_down_arrow@2x.png
  4. BIN
      AIEmoji/Assets.xcassets/Common/blue_down_arrow.imageset/blue_down_arrow@3x.png
  5. 22 0
      AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/Contents.json
  6. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/nav_title_ttp@2x.png
  7. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/nav_title_ttp@3x.png
  8. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio16_9.imageset/ttp_ratio16_9@2x.png
  9. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio16_9.imageset/ttp_ratio16_9@3x.png
  10. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio1_1.imageset/ttp_ratio1_1@2x.png
  11. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio1_1.imageset/ttp_ratio1_1@3x.png
  12. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio3_4.imageset/ttp_ratio3_4@2x.png
  13. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio3_4.imageset/ttp_ratio3_4@3x.png
  14. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio4_3.imageset/ttp_ratio4_3@2x.png
  15. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio4_3.imageset/ttp_ratio4_3@3x.png
  16. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio9_16.imageset/ttp_ratio9_16@2x.png
  17. BIN
      AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio9_16.imageset/ttp_ratio9_16@3x.png
  18. 0 28
      AIEmoji/Business/Data/TSUserDefaultData.swift
  19. 4 0
      AIEmoji/Business/General/TSAppBtnView/TSAppBtnView.swift
  20. 0 83
      AIEmoji/Business/TSAILIstVC/TSAIExpandImageVC/TSAIExpandImageVM.swift
  21. 60 15
      AIEmoji/Business/TSPTPGeneratorVC/TSGennertatorSelectStyleVC/TSGennertatorSelectStyleVC.swift
  22. 1 0
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/View/TSPTPSelectStyleView.swift
  23. 13 0
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/M/TSPTPStyleModel.swift
  24. 3 2
      AIEmoji/Business/TSTabBarController/TSTabBarController.swift
  25. 68 0
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC+Col.swift
  26. 34 0
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC+Style.swift
  27. 76 38
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC.swift
  28. 50 11
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/VM/TSTTPInputVM.swift
  29. 53 13
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSPromptTextView.swift
  30. 14 7
      AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSTTPStyleView.swift
  31. 38 3
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/TSTextGeneralPictureVC.swift
  32. 41 0
      AIEmoji/Common/NetworkManager/TSNetWork/TSNetWork+Business.swift
  33. 97 0
      AIEmoji/Enums/TSLoadState.swift

+ 20 - 0
AIEmoji.xcodeproj/project.pbxproj

@@ -250,6 +250,9 @@
 		A8FB02B72D3E3A3D0031A396 /* TSEmojisChildViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FB02B62D3E3A3B0031A396 /* TSEmojisChildViewModel.swift */; };
 		A8FB02BA2D3E3BB20031A396 /* TSEmojisCoLItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FB02B92D3E3BB00031A396 /* TSEmojisCoLItemCell.swift */; };
 		A8FB02D12D3E6B2A0031A396 /* Cat🐱.json in Resources */ = {isa = PBXBuildFile; fileRef = A8FB02D02D3E6B240031A396 /* Cat🐱.json */; };
+		A8FDB1712DCC4B1100E9919B /* TSLoadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FDB16F2DCC4B1100E9919B /* TSLoadState.swift */; };
+		A8FDB17C2DCC5A1000E9919B /* TSTTPInputVC+Col.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FDB17B2DCC5A0000E9919B /* TSTTPInputVC+Col.swift */; };
+		A8FDB17E2DCC5D8500E9919B /* TSTTPInputVC+Style.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FDB17D2DCC5D8000E9919B /* TSTTPInputVC+Style.swift */; };
 		D34BB2B8FE0DBF83E06A3FC4 /* Pods_AIEmoji.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86FB4D6AEFDDA7A2017F307C /* Pods_AIEmoji.framework */; };
 /* End PBXBuildFile section */
 
@@ -527,6 +530,9 @@
 		A8FB02B62D3E3A3B0031A396 /* TSEmojisChildViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSEmojisChildViewModel.swift; sourceTree = "<group>"; };
 		A8FB02B92D3E3BB00031A396 /* TSEmojisCoLItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSEmojisCoLItemCell.swift; sourceTree = "<group>"; };
 		A8FB02D02D3E6B240031A396 /* Cat🐱.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "Cat🐱.json"; sourceTree = "<group>"; };
+		A8FDB16F2DCC4B1100E9919B /* TSLoadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSLoadState.swift; sourceTree = "<group>"; };
+		A8FDB17B2DCC5A0000E9919B /* TSTTPInputVC+Col.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSTTPInputVC+Col.swift"; sourceTree = "<group>"; };
+		A8FDB17D2DCC5D8000E9919B /* TSTTPInputVC+Style.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSTTPInputVC+Style.swift"; sourceTree = "<group>"; };
 		CA9B99CBEC45A6004629E790 /* Pods-AIEmoji.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AIEmoji.debug.xcconfig"; path = "Target Support Files/Pods-AIEmoji/Pods-AIEmoji.debug.xcconfig"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
@@ -577,6 +583,8 @@
 				A80327BD2D81576700AF7878 /* View */,
 				A80327B42D813D7900AF7878 /* VM */,
 				A80327B22D813D4800AF7878 /* TSTTPInputVC.swift */,
+				A8FDB17B2DCC5A0000E9919B /* TSTTPInputVC+Col.swift */,
+				A8FDB17D2DCC5D8000E9919B /* TSTTPInputVC+Style.swift */,
 			);
 			path = TSTTPInputVC;
 			sourceTree = "<group>";
@@ -1594,6 +1602,7 @@
 		A8F7748A2D38E8B700AA6E93 /* AIEmoji */ = {
 			isa = PBXGroup;
 			children = (
+				A8FDB1702DCC4B1100E9919B /* Enums */,
 				A8FB02AE2D3E38FA0031A396 /* Res */,
 				A8F7751E2D38ED4500AA6E93 /* DataManger */,
 				A8F774922D38EA8C00AA6E93 /* Business */,
@@ -2002,6 +2011,14 @@
 			path = VIew;
 			sourceTree = "<group>";
 		};
+		A8FDB1702DCC4B1100E9919B /* Enums */ = {
+			isa = PBXGroup;
+			children = (
+				A8FDB16F2DCC4B1100E9919B /* TSLoadState.swift */,
+			);
+			path = Enums;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -2229,6 +2246,7 @@
 				A8BA766C2DA657E8000B6707 /* TSAIListPhotoGeneratorBaseVC.swift in Sources */,
 				A80EDD5C2D6C3F82003CD332 /* MarkdownList.swift in Sources */,
 				A82D607F2DB7772200596190 /* TSAIExpandImageVM.swift in Sources */,
+				A8FDB17E2DCC5D8500E9919B /* TSTTPInputVC+Style.swift in Sources */,
 				A80EDD5D2D6C3F82003CD332 /* MarkdownCodeEscaping.swift in Sources */,
 				A8D638352DB10BAC00A96C0E /* CrashReporter.swift in Sources */,
 				A80EDD5E2D6C3F82003CD332 /* MarkdownLinkElement.swift in Sources */,
@@ -2286,6 +2304,7 @@
 				A8F775452D39347100AA6E93 /* TSSetingViewModel.swift in Sources */,
 				A80E72202D3F3A8600C64288 /* DiyElementBaseView.swift in Sources */,
 				A8F776212D3A3F0200AA6E93 /* TSEmojisChildVC.swift in Sources */,
+				A8FDB1712DCC4B1100E9919B /* TSLoadState.swift in Sources */,
 				A885088D2DBCE7BE000FBCEC /* TSPTPHistoryVC.swift in Sources */,
 				A8F413512DA7B722001E715A /* TSPurchaseManager+DataReport.swift in Sources */,
 				A80E72222D3F3A9200C64288 /* DiyStickerElement.swift in Sources */,
@@ -2327,6 +2346,7 @@
 				A89EA6692D59AA31000EB181 /* CameraInputBarAccessoryView.swift in Sources */,
 				A89EA66B2D59AA31000EB181 /* TSTextMessageContentCell.swift in Sources */,
 				A804B98F2DC0F0F700C494C7 /* TSTTPRatioView.swift in Sources */,
+				A8FDB17C2DCC5A1000E9919B /* TSTTPInputVC+Col.swift in Sources */,
 				A83404D52D9D28D700C140E4 /* TSAIPhotoBrowseVC.swift in Sources */,
 				A89EA66C2D59AA31000EB181 /* TSMessageContentCell.swift in Sources */,
 				A87587122D81702700286A66 /* TSUserDefaultData.swift in Sources */,

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

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

BIN
AIEmoji/Assets.xcassets/Common/blue_down_arrow.imageset/blue_down_arrow@2x.png


BIN
AIEmoji/Assets.xcassets/Common/blue_down_arrow.imageset/blue_down_arrow@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/nav_title_ttp@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/nav_title_ttp.imageset/nav_title_ttp@3x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio16_9.imageset/ttp_ratio16_9@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio16_9.imageset/ttp_ratio16_9@3x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio1_1.imageset/ttp_ratio1_1@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio1_1.imageset/ttp_ratio1_1@3x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio3_4.imageset/ttp_ratio3_4@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio3_4.imageset/ttp_ratio3_4@3x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio4_3.imageset/ttp_ratio4_3@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio4_3.imageset/ttp_ratio4_3@3x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio9_16.imageset/ttp_ratio9_16@2x.png


BIN
AIEmoji/Assets.xcassets/TextGeneralPicture/ratio/ttp_ratio9_16.imageset/ttp_ratio9_16@3x.png


+ 0 - 28
AIEmoji/Business/Data/TSUserDefaultData.swift

@@ -6,34 +6,6 @@
 //
 import ObjectMapper
 
-func getUserInfoJsonString()->String {
-    let uuid: String
-    let uuidUdKey = "my_UUID"
-    if let saved = UserDefaults.standard.string(forKey: uuidUdKey),
-       !saved.isEmpty {
-        uuid = saved
-    } else {
-        let newUuid = UUID().uuidString
-        UserDefaults.standard.set(newUuid, forKey: uuidUdKey)
-        UserDefaults.standard.synchronize()
-        uuid = newUuid
-    }
-    
-    let dic:[String:Any] = [
-        "device":UIDevice.current.modelName,
-        "deviceId":uuid,
-        "iosVersion":UIDevice.current.systemVersion,
-        "appVersion":appShortVersion(),
-        "subscriptionStatus":kPurchaseDefault.isVip ? "active" : "fallow",
-    ]
-    
-    if let jSONString = dic.toJSONString() {
-        return jSONString
-    }
-    
-    return ""
-}
-
 func kHandleDBHistoryOperation(){
     let listModels = TSRMShared.ptpDBHistory.listModels
     for model in listModels {

+ 4 - 0
AIEmoji/Business/General/TSAppBtnView/TSAppBtnView.swift

@@ -110,6 +110,10 @@ extension TSAppBtnView{
 //        button.alpha = isEnabled ? 1.0 : 0.6
     }
     
+    var isEnabled:Bool{
+        return button.isEnabled
+    }
+    
     func setVip(vip:Bool) {
         
         if loading { //loading,正在显示转圈动画

+ 0 - 83
AIEmoji/Business/TSAILIstVC/TSAIExpandImageVC/TSAIExpandImageVM.swift

@@ -8,89 +8,6 @@
 import ObjectMapper
 import Alamofire
 
-
-// MARK: - 比例枚举
-enum AspectRatio: Int ,CaseIterable {
-    case ratio1_1 = 0
-    case ratio16_9
-    case ratio9_16
-    case ratio4_3
-    case ratio3_4
-    case ratio2_3
-    case ratio3_2
-    
-    var value: CGFloat {
-        switch self {
-        case .ratio1_1: return 1.0
-        case .ratio16_9: return 16.0/9.0
-        case .ratio9_16: return 9.0/16.0
-        case .ratio4_3: return 4.0/3.0
-        case .ratio3_4: return 3.0/4.0
-        case .ratio2_3: return 2.0/3.0
-        case .ratio3_2: return 3.0/2.0
-        }
-    }
-    
-    var displayName: String {
-        switch self {
-        case .ratio1_1: return "1:1"
-        case .ratio16_9: return "16:9"
-        case .ratio9_16: return "9:16"
-        case .ratio4_3: return "4:3"
-        case .ratio3_4: return "3:4"
-        case .ratio2_3: return "2:3"
-        case .ratio3_2: return "3:2"
-        }
-    }
-    
-    static func creatAspectRatio(string:String)->AspectRatio{
-        switch string {
-        case "1:1": return .ratio1_1
-        case "16:9": return .ratio16_9
-        case "9:16": return .ratio9_16
-        case "4:3": return .ratio4_3
-        case "3:4": return .ratio3_4
-        case "2:3": return .ratio2_3
-        case "3:2": return .ratio3_2
-        default: return .ratio1_1
-        }
-    }
-    
-
-}
-extension AspectRatio {
-    
-    //ttp文生图比例 size
-    var ttpSize:CGSize{
-        switch self {
-        case .ratio1_1: return CGSize(width: 1440, height: 1440)
-        case .ratio16_9: return CGSize(width: 1440, height: 800)
-        case .ratio9_16: return CGSize(width: 800, height: 1440)
-        case .ratio4_3: return CGSize(width: 1440, height: 1056)
-        case .ratio3_4: return CGSize(width: 1056, height: 1440)
-        case .ratio2_3: return CGSize(width: 960, height: 1440)
-        case .ratio3_2: return CGSize(width: 1440, height: 960)
-        }
-    }
-    
-    //ttp文生图比例 size
-    var ttpImageNamed:String{
-        switch self {
-        case .ratio1_1: return "ttp_ratio1_1"
-        case .ratio16_9: return "ttp_ratio16_9"
-        case .ratio9_16: return "ttp_ratio9_16"
-        case .ratio4_3: return "ttp_ratio4_3"
-        case .ratio3_4: return "ttp_ratio3_4"
-        case .ratio2_3: return "ttp_ratio2_3"
-        case .ratio3_2: return "ttp_ratio3_2"
-        }
-    }
-    
-    static var ttpRatioDataArray:[AspectRatio]{
-        return AspectRatio.allCases
-    }
-}
-
 class TSAIExpandImageVM {
     
     var currentRatio: AspectRatio{

+ 60 - 15
AIEmoji/Business/TSPTPGeneratorVC/TSGennertatorSelectStyleVC/TSGennertatorSelectStyleVC.swift

@@ -7,6 +7,11 @@
 
 class TSGennertatorSelectStyleVC: TSBaseVC {
 
+    enum Style {
+    case ptp
+    case ttp
+    }
+    
     lazy var bottomView: UIView = {
         let bottomView = UIView()
         bottomView.backgroundColor = .popupColor
@@ -23,6 +28,7 @@ class TSGennertatorSelectStyleVC: TSBaseVC {
         return xBtn
     }()
     
+    var style:Style = .ptp
     var selectedValueBlock:((IndexPath,TSGenerateStyleModel)->Void)?
     
     var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
@@ -138,6 +144,7 @@ extension TSGennertatorSelectStyleVC: UICollectionViewDataSource ,UICollectionVi
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TSGennertatorSelectStyleCell.cellID, for: indexPath)
         if let cell = cell as? TSGennertatorSelectStyleCell,let itemModel = dataArray.safeObj(At: indexPath.item){
             cell.itemModel = itemModel
+            cell.style = style
         }
         return cell
     }
@@ -161,12 +168,38 @@ class TSGennertatorSelectStyleCell: TSBaseCollectionCell {
             textLabel.textColor = isSelected ? .themeColor : .white.withAlphaComponent(0.8)
         }
     }
-    
+    var style:TSGennertatorSelectStyleVC.Style = .ptp{
+        
+        didSet{
+            switch style {
+            case .ptp:
+                boardImageView.cornerRadius = 16
+                let w = 78
+                boardImageView.snp.updateConstraints { make in
+                    make.width.height.equalTo(w)
+                }
+                imageView.snp.updateConstraints { make in
+                    make.top.equalTo(4)
+                    make.width.height.equalTo(w-8)
+                }
+            case .ttp:
+                boardImageView.cornerRadius = 34.0
+                let w = 68.0
+                boardImageView.snp.updateConstraints { make in
+                    make.width.height.equalTo(w)
+                }
+                imageView.snp.updateConstraints { make in
+                    make.top.equalTo(0)
+                    make.width.height.equalTo(w)
+                }
+            }
+        }
+    }
     var itemModel:TSGenerateStyleModel = TSGenerateStyleModel(){
         didSet{
             imageView.image = UIImage(named: itemModel.imageName)
             
-            let hotImageNamed = getHotImageNamed(specialStyle: itemModel.specialStyle)
+            let hotImageNamed = getSpecialStyleImageNamed(specialStyle: itemModel.specialStyle)
             if hotImageNamed.count > 0 {
                 hotImageView.image = UIImage(named: hotImageNamed)
                 hotImageView.isHidden = false
@@ -177,13 +210,24 @@ class TSGennertatorSelectStyleCell: TSBaseCollectionCell {
         }
     }
     
-    func getHotImageNamed(specialStyle:Int)->String{
-        if specialStyle == 1 {
-            return "ptp_style_hot"
-        }else if specialStyle == 2 {
-            return "ptp_style_new"
-        }else if specialStyle == 3 {
-            return "ptp_style_max"
+    func getSpecialStyleImageNamed(specialStyle:Int)->String{
+        switch style {
+        case .ptp:
+            if specialStyle == 1 {
+                return "ptp_style_hot"
+            }else if specialStyle == 2 {
+                return "ptp_style_new"
+            }else if specialStyle == 3 {
+                return "ptp_style_max"
+            }
+        case .ttp:
+            if specialStyle == 1 {
+                return "ttp_style_hot"
+            }else if specialStyle == 2 {
+                return "ptp_style_new"
+            }else if specialStyle == 3 {
+                return "ptp_style_max"
+            }
         }
         return ""
     }
@@ -215,12 +259,7 @@ class TSGennertatorSelectStyleCell: TSBaseCollectionCell {
     override func creatUI() {
 //        let w = contentView.width
         let w = 78
-        bgContentView.addSubview(boardImageView)
-        boardImageView.snp.makeConstraints { make in
-            make.top.centerX.equalToSuperview()
-            make.width.height.equalTo(w)
-        }
-        
+
         bgContentView.addSubview(imageView)
         imageView.snp.makeConstraints { make in
             make.top.equalTo(4)
@@ -228,6 +267,12 @@ class TSGennertatorSelectStyleCell: TSBaseCollectionCell {
             make.width.height.equalTo(w-8)
         }
         
+        bgContentView.addSubview(boardImageView)
+        boardImageView.snp.makeConstraints { make in
+            make.top.centerX.equalToSuperview()
+            make.width.height.equalTo(w)
+        }
+        
         imageView.addSubview(hotImageView)
         hotImageView.snp.makeConstraints { make in
             make.leading.equalTo(0)

+ 1 - 0
AIEmoji/Business/TSPTPGeneratorVC/TSPTPInputVC/View/TSPTPSelectStyleView.swift

@@ -53,6 +53,7 @@ class TSPTPSelectStyleView : TSBaseView{
         addSubview(styleCollectionView)
         styleCollectionView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
+            make.height.equalTo(viewH)
         }
     }
     

+ 13 - 0
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/M/TSPTPStyleModel.swift

@@ -40,3 +40,16 @@ class TSGenerateStyleModel: TSBaseModel {
     var generateSize:CGSize?    //生成图片的尺寸
 }
 
+extension TSGenerateStyleModel {
+    
+    var specialStyleImageNamed:String{
+        if specialStyle == 1 {
+            return "ptp_style_hot"
+        }else if specialStyle == 2 {
+            return "ptp_style_new"
+        }else if specialStyle == 3 {
+            return "ptp_style_max"
+        }
+        return ""
+    }
+}

+ 3 - 2
AIEmoji/Business/TSTabBarController/TSTabBarController.swift

@@ -24,12 +24,13 @@ class TSTabBarController: UITabBarController {
     }
 
     @objc private func setUpData() {
-        viewControllerArray = ["TSPTPInputVC","TSAILIstVC","TSChatViewController","TSSetingVC"]
+        viewControllerArray = ["TSPTPInputVC","TSTTPInputVC","TSAILIstVC","TSSetingVC"]
+//        viewControllerArray = ["TSPTPInputVC","TSAILIstVC","TSChatViewController","TSSetingVC"]
 //        viewControllerArray = ["TSPTPInputVC","TSChatViewController","TSEmojisVC","TSSetingVC"]
 //        viewControllerArray = ["TSPhotoToPhotoVC","TSChatViewController","TSEmojisVC","TSSetingVC"]
 //        viewControllerArray = ["TSTTPInputVC","TSChatViewController","TSEmojisVC","TSSetingVC"]
 
-        titleArray = ["Photo","AI","Chat","Setting"]
+        titleArray = ["Photo","Text","AI Store","Setting"]
         selectedImageArray = [
             "tabbar_select_pic",
             "tabbar_select_ailist",

+ 68 - 0
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC+Col.swift

@@ -0,0 +1,68 @@
+//
+//  TSTTPInputVC+Col.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/5/7.
+//
+ 
+extension TSTTPInputVC {
+    func creatCollectionComponent()->TSCollectionViewComponent {
+        let layout = UICollectionViewFlowLayout()
+        let cp = TSCollectionViewComponent(frame: CGRect.zero, layout: layout, attributes: [ :])
+        cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
+        cp.collectionView.isScrollEnabled = 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.updateListDataView()
+                })
+            }
+        }
+        
+        cp.itemDidSelectedHandler = { [weak self] (object, indexPath) in
+            guard let self = self else { return }
+            if indexPath.section == 0{
+                if let sections = viewModel.colDataArray.safeObj(At: indexPath.section) as? TSGenmojiCoLSectionModel{
+                    var dataModelArray:[TSActionInfoModel] = []
+                    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
+    }
+    
+    
+    func observerCollectionView(){
+        //监听collectionView 的 contentSize
+        collectionViewObserver = CollectionViewObserver(collectionView: collectionComponent.collectionView)
+        collectionViewObserver.onContentSizeChange = {[weak self]  size in
+            guard let self = self else { return }
+            print("collectionViewObserver 内容大小变化: \(size)")
+            self.collectionComponent.collectionView.snp.updateConstraints { make in
+               make.height.equalTo(size.height)
+            }
+        }
+    }
+    
+    func updateListDataView(){
+        viewModel.updateRecentData {[weak self]  in
+            guard let self = self else { return }
+            updateListView()
+        }
+    }
+    
+    func     updateListView(){
+        self.collectionComponent.clear()
+        self.collectionComponent.reloadView(with: self.viewModel.colDataArray)
+    }
+    
+}

+ 34 - 0
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC+Style.swift

@@ -0,0 +1,34 @@
+//
+//  TSTTPInputVC+Style.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/5/7.
+//
+
+extension TSTTPInputVC {
+    
+    func creatPromptStyleView()->TSTTPStyleView {
+        let promptStyleView = TSTTPStyleView()
+        promptStyleView.currentIndexPath = IndexPath(item: viewModel.selectedStyleIndex, section: 0)
+        promptStyleView.dataArray = viewModel.ptpStyleModels
+        promptStyleView.selectedValueBlock = { [weak self] model in
+            guard let self = self else { return }
+            viewModel.selectPromptModel = model
+            updateVipView()
+        }
+        promptStyleView.clickMoreBlock = { [weak self]  in
+            guard let self = self else { return }
+            let selectStyleVC = TSGennertatorSelectStyleVC()
+            selectStyleVC.style = .ttp
+            selectStyleVC.currentIndexPath = IndexPath(item: viewModel.selectedStyleIndex, section: 0)
+            selectStyleVC.dataArray = viewModel.ptpStyleModels
+            selectStyleVC.selectedValueBlock = { [weak self] indexPath ,model in
+                guard let self = self else { return }
+                promptStyleView.collectionView(promptStyleView.styleCollectionView, didSelectItemAt: indexPath)
+            }
+            kPresentModalVC(target: self, modelVC: selectStyleVC,transitionStyle: .coverVertical)
+        }
+        return promptStyleView
+
+    }
+}

+ 76 - 38
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/TSTTPInputVC.swift

@@ -26,11 +26,39 @@ class TSTTPInputVC: TSBaseVC {
         }
         return viewModel
     }()
+    //###################################### 导航栏 view ######################################
+
+    lazy var vipBtn: UIButton = {
+       let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self]  in
+           guard let self = self else { return }
+           TSPurchaseVC.show(target: self) {}
+       }
+       return vipBtn
+   }()
     
+
+    lazy var navBarView: TSBaseNavContentBarView = {
+       let navBarView = TSBaseNavContentBarView()
+       
+       let titleImageView = UIImageView.createImageView(imageName: "nav_title_ttp",contentMode: .scaleToFill)
+       navBarView.barView.addSubview(titleImageView)
+       titleImageView.snp.makeConstraints { make in
+           make.centerY.equalToSuperview()
+           make.left.equalTo(16)
+       }
+       
+       navBarView.barView.addSubview(vipBtn)
+       vipBtn.snp.makeConstraints { make in
+           make.centerY.equalToSuperview()
+           make.trailing.equalTo(-16)//(-60)
+           make.width.height.equalTo(24)
+       }
+       
+       return navBarView
+   }()
     //###################################### cusStackView ######################################
     lazy var cusStackView: TSCustomStackView = {
         let cusStackView = TSCustomStackView(axis: .vertical,spacing: 0)
-        cusStackView.scrollView.isScrollEnabled = false
         return cusStackView
     }()
     
@@ -42,7 +70,7 @@ class TSTTPInputVC: TSBaseVC {
         }
         promptTextView.sendBolck = { [weak self] text in
             guard let self = self else { return }
-            if creatBtnView.creatBtn.isEnabled {
+            if creatBtnView.isEnabled {
                 generateImage()
             }
         }
@@ -50,17 +78,7 @@ class TSTTPInputVC: TSBaseVC {
     }()
     
     //###################################### Prompt类型 ######################################
-    lazy var promptStyleView: TSTTPStyleView = {
-        let promptStyleView = TSTTPStyleView()
-        promptStyleView.currentIndexPath = IndexPath(item: viewModel.selectedStyleIndex, section: 0)
-        promptStyleView.dataArray = viewModel.ptpStyleModels
-        promptStyleView.selectedValueBlock = { [weak self] model in
-            guard let self = self else { return }
-            viewModel.selectPromptModel = model
-            updateVipView()
-        }
-        return promptStyleView
-    }()
+    lazy var promptStyleView: TSTTPStyleView = creatPromptStyleView()
     
     //###################################### 尺寸类型 ######################################
     lazy var ratioStyleView: TSTTPRatioView = {
@@ -74,26 +92,48 @@ class TSTTPInputVC: TSBaseVC {
         }
         return ratioStyleView
     }()
+    //###################################### collectionComponent ######################################
+    var collectionViewObserver: CollectionViewObserver!
+    let collectionViewBtootm:CGFloat = 80
+    lazy var collectionComponent: TSCollectionViewComponent = creatCollectionComponent()
+    
     //###################################### Button ######################################
-    lazy var creatBtnView:TSGeneralBtnView  = {
-        let creatBtnView = TSGeneralBtnView {[weak self] in
+    lazy var creatBtnView:TSAppBtnView  = {
+        let creatBtnView = TSAppBtnView()
+        creatBtnView.setUpButton(style: .generate, vipFreeNumType: .textGeneratePic) { [weak self] in
             guard let self = self else { return }
             generateImage()
         }
         creatBtnView.setBtnEnabled(isEnabled: false)
+        creatBtnView.isIconVipBlock = { [weak self]  in
+            guard let self = self else { return false}
+            var showVip = kPurchaseDefault.generateVipShow(type: .picToPic)
+            if showVip == false {
+                showVip = self.viewModel.selectPromptModel.isVip
+            }
+            return showVip
+        }
+        creatBtnView.isClickVipBlock = { [weak self]  in
+            guard let self = self else { return false}
+            var isVip = kPurchaseDefault.freeNumAvailable(type: .picToPic) == false
+            if viewModel.selectPromptModel.isVip == true {
+                isVip = true
+            }
+            return isVip
+        }
         return creatBtnView
     }()
     
-
     override func createView() {
-        view.backgroundColor = .clear
-        
-        setNavBarViewHidden(true)
-    
         let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickView))
         tapGesture.cancelsTouchesInView = false
         view.addGestureRecognizer(tapGesture)
         
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
         contentView.addSubview(cusStackView)
         cusStackView.snp.makeConstraints { make in
             make.top.leading.bottom.trailing.equalTo(0)
@@ -102,17 +142,23 @@ class TSTTPInputVC: TSBaseVC {
         cusStackView.addSubviewToStack(promptTextView)
         cusStackView.addSubviewToStack(promptStyleView)
         cusStackView.addSubviewToStack(ratioStyleView)
-        cusStackView.addSpacing(length: 16)//增加 16 的间隔
-        cusStackView.addSubviewToStack(creatBtnView)
+        cusStackView.addSubviewToStack(collectionComponent.collectionView, length: 0)
+        cusStackView.addSpacing(length: collectionViewBtootm)
+        
+        contentView.addSubview(creatBtnView)
         creatBtnView.snp.makeConstraints { make in
-            make.height.equalTo(creatBtnView.viewH)
-            make.width.equalTo(k_ScreenWidth)
+            make.bottom.equalTo(-16)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.height.equalTo(48)
         }
     }
     
     override func dealThings() {
         updateVipView()
         NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
+        observerCollectionView()
+        updateListDataView()
     }
     
     @objc func vipInfoChanged() {
@@ -123,39 +169,31 @@ class TSTTPInputVC: TSBaseVC {
         view.endEditing(true)
     }
 
-    @objc func clickCollectionView() {
-        view.endEditing(true)
-    }
-    
     func updateVipView() {
         kExecuteOnMainThread {
-            var showVip = kPurchaseDefault.generateVipShow(type: .textGeneratePic)
-            if showVip == false {
-                showVip = self.viewModel.selectPromptModel?.isVip ?? false
-            }
-            kSetBtnVipIcon(btn: self.creatBtnView.creatBtn, show: showVip)
+            self.vipBtn.isHidden = PurchaseManager.default.isVip
+            self.creatBtnView.updateVipView()
         }
     }
-    
+
 }
 
 extension TSTTPInputVC {
     func generateImage() {
         
-        guard let generateStyleModel = viewModel.generateStyleModel else { return }
-        
         var isVip = kPurchaseDefault.freeNumAvailable(type: .textGeneratePic) == false
-        if viewModel.selectPromptModel?.isVip == true {
+        if viewModel.selectPromptModel.isVip == true {
             isVip = true
         }
         
         if kJudgeVip(externalBool: isVip, vc: self) { return } //判断 vip
-        let gennerateVC = TSTextPicGennerateVC(generateStyleModel: generateStyleModel) {[weak self] model in
+        let gennerateVC = TSTextPicGennerateVC(generateStyleModel: viewModel.generateStyleModel) {[weak self] model in
             guard let self = self else { return }
             model.request.promptSort = viewModel.promptText
             viewModel.saveModel(model: model)
             updateVipView()
             reloadUIBlock?()
+            updateListDataView()
         }
         
         kPresentModalVC(target: self, modelVC: gennerateVC,transitionStyle: .crossDissolve)

+ 50 - 11
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/VM/TSTTPInputVM.swift

@@ -21,10 +21,20 @@ let kRandomTextToRintone:[String] = [
 ]
 
 class TSTTPInputVM {
+    //###################################### 历史记录 ######################################
+    var colDataArray:[TSComponent] = [TSComponent]()
+
+    lazy var enmojiHistorySeciton: TSGenmojiCoLSectionModel = {
+        let sectionModel = TSGenmojiCoLSectionModel()
+        sectionModel.style = .textPicHistory
+        sectionModel.name = "History".localized
+        return sectionModel
+    }()
+    
     //###################################### 样式选择 ######################################
     var selectedStyleIndex:Int = 0
     //选择的 prompt 类型
-    var selectPromptModel:TSGenerateStyleModel?{
+    var selectPromptModel:TSGenerateStyleModel = TSGenerateStyleModel(){
         didSet{
             isCanGennerateBlock?(isCanGennerate)
         }
@@ -68,13 +78,10 @@ class TSTTPInputVM {
     
     
     //用户生成图片的TSGenerateStyleModel
-    var generateStyleModel:TSGenerateStyleModel?{
-        if let selectPromptModel = selectPromptModel {
-            selectPromptModel.generateSize = selectRatio.ttpSize
-            selectPromptModel.prompt = prompt
-            return selectPromptModel
-        }
-        return nil
+    var generateStyleModel:TSGenerateStyleModel{
+        selectPromptModel.generateSize = selectRatio.ttpSize
+        selectPromptModel.prompt = prompt
+        return selectPromptModel
     }
 }
 
@@ -82,8 +89,7 @@ class TSTTPInputVM {
 extension TSTTPInputVM {
     //是否满足生成条件
     var isCanGennerate:Bool {
-        if  selectPromptModel != nil ,
-            promptText.replacingOccurrences(of: " ", with: "").count > 0
+        if  promptText.replacingOccurrences(of: " ", with: "").count > 0
         {
             return true
         }
@@ -94,7 +100,7 @@ extension TSTTPInputVM {
     var prompt:String{
         var prompt = promptText
 
-        if let selectPromptModel = selectPromptModel,selectPromptModel.prompt.count > 0 {
+        if selectPromptModel.prompt.count > 0 {
             prompt = "\(selectPromptModel.prompt)," + prompt
         }
         return prompt
@@ -106,3 +112,36 @@ extension TSTTPInputVM {
 }
 
 
+
+extension TSTTPInputVM {
+    func updateRecentData(completion:@escaping ()->Void) {
+        TSRMShared.ttpDBHistory.getModelList {[weak self] array in
+            guard let self = self else { return }
+            setRecentData(listModelArray: array)
+            completion()
+        }
+    }
+    
+    func setRecentData(listModelArray:[TSActionInfoModel]) {
+        if listModelArray.count == 0 {
+            colDataArray = []
+        }else{
+            var array = [TSGenmojiCoLItemModel]()
+            listModelArray.forEach { model in
+                let itemModel = TSGenmojiCoLItemModel()
+                itemModel.dataModel = model
+                itemModel.style = .textPicHistory
+                array.append(itemModel)
+            }
+            enmojiHistorySeciton.items = array
+            
+            colDataArray = [enmojiHistorySeciton]
+        }
+    }
+}
+extension TSTTPInputVM {
+    func removeAllHistoryList(){
+        TSRMShared.ttpDBHistory.delete()
+    }
+}
+

+ 53 - 13
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSPromptTextView.swift

@@ -52,7 +52,7 @@ class TSPromptTextView : TSBaseView{
     
     lazy var inspirationBtn: UIButton = {
         let inspirationBtn = UIButton.createButton(
-            title: "Hint Inspiration".localized,
+            //title: "Hint Inspiration".localized,
             image: UIImage(named: "inspiration_yellow"),
             backgroundColor:"#FECB34".uiColor.withAlphaComponent(0.1),
             font: .font(size: 12),
@@ -64,11 +64,46 @@ class TSPromptTextView : TSBaseView{
             textViewDidChange(customTextView)
         }
         inspirationBtn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 7, bottom: 4, right: 7)
-        inspirationBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
+//        inspirationBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
         inspirationBtn.isHidden = false
         return inspirationBtn
     }()
     
+    
+    lazy var AIView: UIView = {
+        let AIView = UIView()
+        AIView.backgroundColor = "#4D6BFE".uiColor.withAlphaComponent(0.1)
+        AIView.cornerRadius = 8
+        AIView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickAIView)))
+        
+        let iconImageView = UIImageView.createImageView(imageName: "deepseek_icon")
+        let aiInfoLabel = UILabel.createLabel(text: "DeepSeek-R1",font: .font(size: 14), textColor: "#4D6BFE".uiColor, textAlignment: .left, numberOfLines: 1)
+        let arrowImageView = UIImageView.createImageView(imageName: "blue_down_arrow")
+        
+        AIView.addSubview(iconImageView)
+        iconImageView.snp.makeConstraints { make in
+            make.leading.equalTo(8)
+            make.centerY.equalToSuperview()
+            make.width.height.equalTo(20)
+        }
+        
+        AIView.addSubview(aiInfoLabel)
+        aiInfoLabel.snp.makeConstraints { make in
+            make.leading.equalTo(iconImageView.snp.trailing).offset(4)
+            make.centerY.equalToSuperview()
+        }
+        
+        AIView.addSubview(arrowImageView)
+        arrowImageView.snp.makeConstraints { make in
+            make.leading.equalTo(aiInfoLabel.snp.trailing).offset(4)
+            make.trailing.equalTo(-8)
+            make.centerY.equalToSuperview()
+            make.width.height.equalTo(16)
+        }
+        
+        return AIView
+    }()
+    
     lazy var clearBtn: UIButton = {
         let clearBtn = UIButton.createButton(
             image: UIImage(named: "clear_text")
@@ -118,6 +153,13 @@ class TSPromptTextView : TSBaseView{
             make.leading.equalTo(16)
         }
         
+        textBgView.addSubview(AIView)
+        AIView.snp.makeConstraints { make in
+            make.height.equalTo(28)
+            make.bottom.equalTo(-16)
+            make.leading.equalTo(inspirationBtn.snp.trailing).offset(8)
+        }
+        
         textBgView.addSubview(clearBtn)
         clearBtn.snp.makeConstraints { make in
             make.width.height.equalTo(16)
@@ -129,33 +171,31 @@ class TSPromptTextView : TSBaseView{
 
     func getVipText()->String{
         return "Generate".localized
-//        if kPurchaseDefault.isVip {
-//            return "Generate"
-//        }
-//        return "Generate (\(kPurchaseDefault.freeNum(type: .generatePic)))"
     }
     
 }
 
 extension TSPromptTextView: UITextViewDelegate{
-    
-//    func textViewDidBeginEditing(_ textView: UITextView) {
-//        self.colComponent?.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredVertically, animated: true)
-//    }
-    
+
     func textViewDidChange(_ textView: UITextView) {
         let text = textView.text.replacingOccurrences(of: " ", with: "")
         clearBtn.isHidden = text.count > 0 ? false : true
         textChangedBlock(textView.text)
     }
     
-    // 实现 UITextViewDelegate 协议方法,控制 return 键行为
     func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
         if text == "\n" {
-            // 当输入为换行符(即按下 return 键)时,执行相应操作
             sendBolck?(textView.text)
             return false
         }
         return true
     }
 }
+
+
+extension TSPromptTextView {
+    
+    @objc func clickAIView(){
+
+    }
+}

+ 14 - 7
AIEmoji/Business/TSTextGeneralPictureVC/TSTTPInputVC/View/TSTTPStyleView.swift

@@ -8,6 +8,11 @@
 class TSTTPStyleView:TSBaseView {
     
     var selectedValueBlock:((TSGenerateStyleModel)->Void)?
+    var clickMoreBlock:(()->Void)?{
+        didSet{
+            titleView.clickMoreBlock = clickMoreBlock
+        }
+    }
     
     var dataArray: [TSGenerateStyleModel] = [TSGenerateStyleModel](){
         didSet{
@@ -21,7 +26,8 @@ class TSTTPStyleView:TSBaseView {
     lazy var layout: UICollectionViewFlowLayout = {
         let layout = UICollectionViewFlowLayout()
         layout.scrollDirection = .horizontal
-        layout.itemSize = CGSize(width: 100, height: 110)
+        let w = (k_ScreenWidth-32.0-30.0-2.0)/4.0
+        layout.itemSize = CGSize(width: w, height: 108)
         layout.minimumInteritemSpacing = 0.0
         layout.minimumLineSpacing = 0.0
         layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
@@ -36,7 +42,7 @@ class TSTTPStyleView:TSBaseView {
         collectionView.showsVerticalScrollIndicator = false
         collectionView.showsHorizontalScrollIndicator = false
         collectionView.backgroundColor = .clear
-        collectionView.register(TSPromptStyleViewCell.self, forCellWithReuseIdentifier: TSPromptStyleViewCell.cellID)
+        collectionView.register(TSGennertatorSelectStyleCell.self, forCellWithReuseIdentifier: TSGennertatorSelectStyleCell.cellID)
         if #available(iOS 11.0, *) {
             collectionView.contentInsetAdjustmentBehavior = .never
         }
@@ -46,9 +52,9 @@ class TSTTPStyleView:TSBaseView {
     var currentIndexPath:IndexPath = IndexPath(item: 0, section: 0)
     
     
-    lazy var titleView: TSTitleView = {
-        let titleView = TSTitleView()
-        titleView.titleLab.text = "Select Style".localized
+    lazy var titleView: TSTitleMoreView = {
+        let titleView = TSTitleMoreView()
+        titleView.setTitle(title: "Select Style".localized, clickMoreBlock: nil)
         return titleView
     }()
     
@@ -91,8 +97,9 @@ extension TSTTPStyleView: UICollectionViewDataSource ,UICollectionViewDelegate {
     
     public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
         
-        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TSPromptStyleViewCell.cellID, for: indexPath)
-        if let cell = cell as? TSPromptStyleViewCell,let itemModel = dataArray.safeObj(At: indexPath.item){
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TSGennertatorSelectStyleCell.cellID, for: indexPath)
+        if let cell = cell as? TSGennertatorSelectStyleCell,let itemModel = dataArray.safeObj(At: indexPath.item){
+            cell.style = .ttp
             cell.itemModel = itemModel
         }
         return cell

+ 38 - 3
AIEmoji/Business/TSTextGeneralPictureVC/TSTextGeneralPictureVC/TSTextGeneralPictureVC.swift

@@ -9,6 +9,35 @@ class TSTextGeneralPictureVC: TSBaseVC {
     
     var viewModel:TSTextGeneralPictureVM = TSTextGeneralPictureVM()
     
+    //###################################### 导航栏 view ######################################
+    lazy var vipBtn: UIButton = {
+       let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self]  in
+           guard let self = self else { return }
+           TSPurchaseVC.show(target: self) {}
+       }
+       return vipBtn
+   }()
+    
+    lazy var navBarView: TSBaseNavContentBarView = {
+       let navBarView = TSBaseNavContentBarView()
+       
+       let titleImageView = UIImageView.createImageView(imageName: "nav_title_ttp",contentMode: .scaleToFill)
+       navBarView.barView.addSubview(titleImageView)
+       titleImageView.snp.makeConstraints { make in
+           make.centerY.equalToSuperview()
+           make.left.equalTo(16)
+       }
+       
+       navBarView.barView.addSubview(vipBtn)
+       vipBtn.snp.makeConstraints { make in
+           make.centerY.equalToSuperview()
+           make.trailing.equalTo(-16)//(-60)
+           make.width.height.equalTo(24)
+       }
+       
+       return navBarView
+   }()
+    
     lazy var collectionComponent: TSCollectionViewComponent = {
         let layout = UICollectionViewFlowLayout()
         let cp = TSCollectionViewComponent(frame: CGRect.zero, layout: layout, attributes: [ :])
@@ -55,8 +84,10 @@ class TSTextGeneralPictureVC: TSBaseVC {
     
     override func createView() {
 
-        addNormalNavBarView()
-        setPageTitle("AI Text to Photo".localized)
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
         
         contentView.addSubview(collectionComponent.collectionView)
         collectionComponent.collectionView.snp.makeConstraints { make in
@@ -92,8 +123,12 @@ class TSTextGeneralPictureVC: TSBaseVC {
     }
     
     @objc func vipInfoChanged() {
+        updateVipView()
+    }
+    
+    func updateVipView() {
         kExecuteOnMainThread {
-            self.collectionComponent.reloadData()
+            self.vipBtn.isHidden = PurchaseManager.default.isVip
         }
     }
     

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

@@ -17,6 +17,7 @@ enum TSNeURLType:String {
     case textPicCreate = "/api/image/create"     //文生图
     case upload = "/api/upload"                  //上传图片
     case imageRewrite = "/api/image/rewrite"     //图生图
+    case imageToImageStyle = "/api/ops/aichat-img2img-config"     //图生图 风格列表
     case chatV2 = "/api/text/chat/v2"             //AI 对话接口V2,扩展了 DeepSeek 深度思考
     
     case config = "/api/ops/aichat-config"       //App配置
@@ -44,6 +45,46 @@ enum TSNeURLType:String {
     }
 }
 
+func getUserInfoJsonString()->String {
+    let uuid: String
+    let uuidUdKey = "my_UUID"
+    if let saved = UserDefaults.standard.string(forKey: uuidUdKey),
+       !saved.isEmpty {
+        uuid = saved
+    } else {
+        let newUuid = UUID().uuidString
+        UserDefaults.standard.set(newUuid, forKey: uuidUdKey)
+        UserDefaults.standard.synchronize()
+        uuid = newUuid
+    }
+    
+    let dic:[String:Any] = [
+        "device":UIDevice.current.modelName,
+        "deviceId":uuid,
+        "iosVersion":UIDevice.current.systemVersion,
+        "appVersion":appShortVersion(),
+        "subscriptionStatus":kPurchaseDefault.isVip ? "active" : "fallow",
+    ]
+    
+    if let jSONString = dic.toJSONString() {
+        return jSONString
+    }
+    
+    return ""
+}
+
+
+func getLanguageCode()->String{
+    if Locale.current.identifier.contains("zh-Hant"){
+        return "zh-Hant"
+    }
+    if let languageCode = Locale.current.languageCode {
+//        print("当前设备语言简写: \(languageCode)") // 输出如 "en", "ja", "zh" 等
+        return languageCode
+    }
+    return "en"
+}
+
 
 extension TSNetworkManager {
     

+ 97 - 0
AIEmoji/Enums/TSLoadState.swift

@@ -0,0 +1,97 @@
+//
+//  TSLoadState.swift
+//  AIEmoji
+//
+//  Created by nkl on 2025/4/29.
+//
+
+import Foundation
+
+
+public enum TSLoadState {
+    case idle //啥也没做的情况下
+    case loading //开始加载
+    case success(Any?) // 成功,可以向外传递数据
+    case failed(Any?) // 失败,可以向外传递数据
+}
+
+// MARK: - 比例枚举
+enum AspectRatio: Int,CaseIterable {
+    case ratio1_1 = 0
+    case ratio16_9
+    case ratio9_16
+    case ratio4_3
+    case ratio3_4
+    case ratio2_3
+    case ratio3_2
+    
+    var value: CGFloat {
+        switch self {
+        case .ratio1_1: return 1.0
+        case .ratio16_9: return 16.0/9.0
+        case .ratio9_16: return 9.0/16.0
+        case .ratio4_3: return 4.0/3.0
+        case .ratio3_4: return 3.0/4.0
+        case .ratio2_3: return 2.0/3.0
+        case .ratio3_2: return 3.0/2.0
+        }
+    }
+    
+    var displayName: String {
+        switch self {
+        case .ratio1_1: return "1:1"
+        case .ratio16_9: return "16:9"
+        case .ratio9_16: return "9:16"
+        case .ratio4_3: return "4:3"
+        case .ratio3_4: return "3:4"
+        case .ratio2_3: return "2:3"
+        case .ratio3_2: return "3:2"
+        }
+    }
+    
+    static func creatAspectRatio(string:String)->AspectRatio{
+        switch string {
+        case "1:1": return .ratio1_1
+        case "16:9": return .ratio16_9
+        case "9:16": return .ratio9_16
+        case "4:3": return .ratio4_3
+        case "3:4": return .ratio3_4
+        case "2:3": return .ratio2_3
+        case "3:2": return .ratio3_2
+        default: return .ratio1_1
+        }
+    }
+}
+
+extension AspectRatio {
+    
+    //ttp文生图比例 size
+    var ttpSize:CGSize{
+        switch self {
+        case .ratio1_1: return CGSize(width: 1440, height: 1440)
+        case .ratio16_9: return CGSize(width: 1440, height: 800)
+        case .ratio9_16: return CGSize(width: 800, height: 1440)
+        case .ratio4_3: return CGSize(width: 1440, height: 1056)
+        case .ratio3_4: return CGSize(width: 1056, height: 1440)
+        case .ratio2_3: return CGSize(width: 960, height: 1440)
+        case .ratio3_2: return CGSize(width: 1440, height: 960)
+        }
+    }
+    
+    //ttp文生图比例 size
+    var ttpImageNamed:String{
+        switch self {
+        case .ratio1_1: return "ttp_ratio1_1"
+        case .ratio16_9: return "ttp_ratio16_9"
+        case .ratio9_16: return "ttp_ratio9_16"
+        case .ratio4_3: return "ttp_ratio4_3"
+        case .ratio3_4: return "ttp_ratio3_4"
+        case .ratio2_3: return "ttp_ratio2_3"
+        case .ratio3_2: return "ttp_ratio3_2"
+        }
+    }
+    
+    static var ttpRatioDataArray:[AspectRatio]{
+        return AspectRatio.allCases
+    }
+}