Pārlūkot izejas kodu

1.去除TSSmalCoacopods
2.ai 生图页面换种写法

100Years 2 mēneši atpakaļ
vecāks
revīzija
bbaeaf3580
51 mainītis faili ar 2553 papildinājumiem un 552 dzēšanām
  1. 120 4
      AICalendarWallpaper.xcodeproj/project.pbxproj
  2. 1 1
      AICalendarWallpaper.xcodeproj/xcuserdata/100years.xcuserdatad/xcschemes/xcschememanagement.plist
  3. 8 21
      AICalendarWallpaper/AppDelegate.swift
  4. 9 3
      AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryCell.swift
  5. 23 0
      AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryVC+View.swift
  6. 61 43
      AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryVC.swift
  7. 1 1
      AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/View/ASAIGenerateCellView.swift
  8. 5 16
      AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/ASAICalendarVC+View.swift
  9. 5 18
      AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/ASAICalendarVC.swift
  10. 1 1
      AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/VM/ASAICalendarVM.swift
  11. 44 40
      AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/View/ASAICalendarStyleView.swift
  12. 2 2
      AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/View/ASPromptTextView.swift
  13. 27 33
      AICalendarWallpaper/Business/ASAIGeneratorVC/ASAIGeneratorVC.swift
  14. 1 1
      AICalendarWallpaper/Business/ASAIGeneratorVC/ASGeneratorView/ASGeneratorErrorView.swift
  15. 1 1
      AICalendarWallpaper/Business/ASAIGeneratorVC/ASGeneratorView/ASGeneratorLoadingView.swift
  16. 2 2
      AICalendarWallpaper/Business/ASCommonView/ASAppBtnView.swift
  17. 2 2
      AICalendarWallpaper/Business/OperationQueue/AIGenerate/ASGenerateBaseOperation.swift
  18. 2 1
      AICalendarWallpaper/Business/OperationQueue/AIGenerate/ASGenerateTTPOperation.swift
  19. 20 6
      AICalendarWallpaper/Business/Setting/APSettingVC+Col.swift
  20. 13 35
      AICalendarWallpaper/Business/Setting/ASSettingVC.swift
  21. 75 69
      AICalendarWallpaper/Business/Tabbar/ASTabBarVC.swift
  22. 85 0
      AICalendarWallpaper/Common/AICustomDialogManager.swift
  23. 45 0
      AICalendarWallpaper/Common/AIKFTool.swift
  24. 78 0
      AICalendarWallpaper/Common/Base/TSBaseCollectionCell.swift
  25. 53 0
      AICalendarWallpaper/Common/Base/TSBaseModel.swift
  26. 173 0
      AICalendarWallpaper/Common/Base/TSBaseNavigationBarView.swift
  27. 233 0
      AICalendarWallpaper/Common/Base/TSBaseVC.swift
  28. 41 0
      AICalendarWallpaper/Common/Base/TSBaseView.swift
  29. 155 2
      AICalendarWallpaper/Common/Common.swift
  30. 3 3
      AICalendarWallpaper/Common/CpuMapManager.swift
  31. 7 0
      AICalendarWallpaper/Common/Ex/Array+Ex.swift
  32. 76 0
      AICalendarWallpaper/Common/Ex/String+Ex.swift
  33. 111 0
      AICalendarWallpaper/Common/Ex/UIButton+Ex.swift
  34. 43 0
      AICalendarWallpaper/Common/Ex/UIColor+Ex.swift
  35. 42 0
      AICalendarWallpaper/Common/Ex/UIFont+Ex.swift
  36. 91 0
      AICalendarWallpaper/Common/Ex/UIImageView+Ex.swift
  37. 68 0
      AICalendarWallpaper/Common/Ex/UILabel+Ex.swift
  38. 49 0
      AICalendarWallpaper/Common/Ex/UIStackView+Ex.swift
  39. 201 0
      AICalendarWallpaper/Common/Ex/UIView+Ex.swift
  40. 62 0
      AICalendarWallpaper/Common/PhotoManager.swift
  41. 23 103
      AICalendarWallpaper/Common/TSNetWork/TSNetWork+Business.swift
  42. 0 86
      AICalendarWallpaper/Common/TSNetWork/TSNetworkManager+Loading.swift
  43. 10 12
      AICalendarWallpaper/Common/TSNetWork/TSNetworkManager.swift
  44. 146 0
      AICalendarWallpaper/Common/TSPlaceholderTextView.swift
  45. 27 0
      AICalendarWallpaper/Common/TSRandomTextTool.swift
  46. 132 0
      AICalendarWallpaper/Common/View/AISaveNotifyManager.swift
  47. 18 0
      AICalendarWallpaper/Common/View/TSUIExpandedTouchButton.swift
  48. 67 0
      AICalendarWallpaper/Common/View/TopLeftLabel.swift
  49. 90 0
      AICalendarWallpaper/Common/WindowHelper.swift
  50. 0 28
      Podfile
  51. 1 18
      Podfile.lock

+ 120 - 4
AICalendarWallpaper.xcodeproj/project.pbxproj

@@ -8,6 +8,30 @@
 
 /* Begin PBXBuildFile section */
 		91224DF1648F5A9681AC6EE7 /* Pods_AICalendarWallpaper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE7FD8DFB70E5765510688C2 /* Pods_AICalendarWallpaper.framework */; };
+		A85421912DEED1D8005D5BA5 /* UILabel+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421902DEED1D2005D5BA5 /* UILabel+Ex.swift */; };
+		A85421932DEED268005D5BA5 /* UIButton+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421922DEED266005D5BA5 /* UIButton+Ex.swift */; };
+		A85421952DEED28A005D5BA5 /* UIView+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421942DEED285005D5BA5 /* UIView+Ex.swift */; };
+		A85421972DEED2A5005D5BA5 /* UIImageView+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421962DEED297005D5BA5 /* UIImageView+Ex.swift */; };
+		A85421992DEED2BC005D5BA5 /* UIFont+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421982DEED2B8005D5BA5 /* UIFont+Ex.swift */; };
+		A854219B2DEEE093005D5BA5 /* String+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A854219A2DEEE088005D5BA5 /* String+Ex.swift */; };
+		A854219D2DEEE0E1005D5BA5 /* UIColor+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A854219C2DEEE0D2005D5BA5 /* UIColor+Ex.swift */; };
+		A85421A02DEEE11F005D5BA5 /* TSBaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A854219F2DEEE11E005D5BA5 /* TSBaseModel.swift */; };
+		A85421A22DEEE159005D5BA5 /* TSBaseNavigationBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421A12DEEE159005D5BA5 /* TSBaseNavigationBarView.swift */; };
+		A85421A42DEEE16E005D5BA5 /* TSBaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421A32DEEE16D005D5BA5 /* TSBaseVC.swift */; };
+		A85421A62DEEE183005D5BA5 /* TSBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421A52DEEE181005D5BA5 /* TSBaseView.swift */; };
+		A85421A82DEEE1B1005D5BA5 /* TSBaseCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421A72DEEE1B0005D5BA5 /* TSBaseCollectionCell.swift */; };
+		A85421AA2DEEE24B005D5BA5 /* Array+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421A92DEEE244005D5BA5 /* Array+Ex.swift */; };
+		A85421AC2DEEE448005D5BA5 /* UIStackView+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421AB2DEEE442005D5BA5 /* UIStackView+Ex.swift */; };
+		A85421B02DEEEA79005D5BA5 /* TSUIExpandedTouchButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421AF2DEEEA76005D5BA5 /* TSUIExpandedTouchButton.swift */; };
+		A85421B42DEEED91005D5BA5 /* WindowHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421B32DEEED88005D5BA5 /* WindowHelper.swift */; };
+		A85421B62DEEEE7C005D5BA5 /* TSRandomTextTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421B52DEEEE7B005D5BA5 /* TSRandomTextTool.swift */; };
+		A85421B82DEEEE8C005D5BA5 /* TSPlaceholderTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421B72DEEEE8B005D5BA5 /* TSPlaceholderTextView.swift */; };
+		A85421BA2DEEEEBB005D5BA5 /* TopLeftLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421B92DEEEEBA005D5BA5 /* TopLeftLabel.swift */; };
+		A85421BC2DEEF244005D5BA5 /* AICustomDialogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421BB2DEEF243005D5BA5 /* AICustomDialogManager.swift */; };
+		A85421BE2DEEF487005D5BA5 /* PhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421BD2DEEF485005D5BA5 /* PhotoManager.swift */; };
+		A85421C02DEEF6AF005D5BA5 /* AISaveNotifyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421BF2DEEF6AE005D5BA5 /* AISaveNotifyManager.swift */; };
+		A85421C22DEEF881005D5BA5 /* AIKFTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421C12DEEF876005D5BA5 /* AIKFTool.swift */; };
+		A85421C62DEF03CD005D5BA5 /* ASAICalendarHistoryVC+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85421C52DEF03C8005D5BA5 /* ASAICalendarHistoryVC+View.swift */; };
 		A8990E3C2DE40B8C00DD55FE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E322DE40B8C00DD55FE /* AppDelegate.swift */; };
 		A8990E3F2DE40B8C00DD55FE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A8990E332DE40B8C00DD55FE /* Assets.xcassets */; };
 		A8990E412DE40B8C00DD55FE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8990E362DE40B8C00DD55FE /* LaunchScreen.storyboard */; };
@@ -23,7 +47,6 @@
 		A8990E632DE41D2D00DD55FE /* APSettingVC+Col.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E622DE41D2C00DD55FE /* APSettingVC+Col.swift */; };
 		A8990E662DE41D9C00DD55FE /* ASTutorialsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E652DE41D9B00DD55FE /* ASTutorialsVC.swift */; };
 		A8990E692DE41DAF00DD55FE /* ASBusinessWebVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E682DE41DAE00DD55FE /* ASBusinessWebVC.swift */; };
-		A8990E6F2DE441AC00DD55FE /* TSNetworkManager+Loading.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E6D2DE441AC00DD55FE /* TSNetworkManager+Loading.swift */; };
 		A8990E702DE441AC00DD55FE /* TSNetWork+Business.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E6C2DE441AC00DD55FE /* TSNetWork+Business.swift */; };
 		A8990E712DE441AC00DD55FE /* TSNetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E6B2DE441AC00DD55FE /* TSNetworkManager.swift */; };
 		A8990E722DE441AC00DD55FE /* TSNetWork+Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8990E6A2DE441AC00DD55FE /* TSNetWork+Error.swift */; };
@@ -60,6 +83,30 @@
 /* Begin PBXFileReference section */
 		196370C145B7644F1420FCEA /* Pods-AICalendarWallpaper.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AICalendarWallpaper.release.xcconfig"; path = "Target Support Files/Pods-AICalendarWallpaper/Pods-AICalendarWallpaper.release.xcconfig"; sourceTree = "<group>"; };
 		82ADFA69D2EFE6049A0D9E82 /* Pods-AICalendarWallpaper.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AICalendarWallpaper.debug.xcconfig"; path = "Target Support Files/Pods-AICalendarWallpaper/Pods-AICalendarWallpaper.debug.xcconfig"; sourceTree = "<group>"; };
+		A85421902DEED1D2005D5BA5 /* UILabel+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Ex.swift"; sourceTree = "<group>"; };
+		A85421922DEED266005D5BA5 /* UIButton+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Ex.swift"; sourceTree = "<group>"; };
+		A85421942DEED285005D5BA5 /* UIView+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Ex.swift"; sourceTree = "<group>"; };
+		A85421962DEED297005D5BA5 /* UIImageView+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Ex.swift"; sourceTree = "<group>"; };
+		A85421982DEED2B8005D5BA5 /* UIFont+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Ex.swift"; sourceTree = "<group>"; };
+		A854219A2DEEE088005D5BA5 /* String+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Ex.swift"; sourceTree = "<group>"; };
+		A854219C2DEEE0D2005D5BA5 /* UIColor+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Ex.swift"; sourceTree = "<group>"; };
+		A854219F2DEEE11E005D5BA5 /* TSBaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBaseModel.swift; sourceTree = "<group>"; };
+		A85421A12DEEE159005D5BA5 /* TSBaseNavigationBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBaseNavigationBarView.swift; sourceTree = "<group>"; };
+		A85421A32DEEE16D005D5BA5 /* TSBaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBaseVC.swift; sourceTree = "<group>"; };
+		A85421A52DEEE181005D5BA5 /* TSBaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBaseView.swift; sourceTree = "<group>"; };
+		A85421A72DEEE1B0005D5BA5 /* TSBaseCollectionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBaseCollectionCell.swift; sourceTree = "<group>"; };
+		A85421A92DEEE244005D5BA5 /* Array+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Ex.swift"; sourceTree = "<group>"; };
+		A85421AB2DEEE442005D5BA5 /* UIStackView+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Ex.swift"; sourceTree = "<group>"; };
+		A85421AF2DEEEA76005D5BA5 /* TSUIExpandedTouchButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSUIExpandedTouchButton.swift; sourceTree = "<group>"; };
+		A85421B32DEEED88005D5BA5 /* WindowHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowHelper.swift; sourceTree = "<group>"; };
+		A85421B52DEEEE7B005D5BA5 /* TSRandomTextTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSRandomTextTool.swift; sourceTree = "<group>"; };
+		A85421B72DEEEE8B005D5BA5 /* TSPlaceholderTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPlaceholderTextView.swift; sourceTree = "<group>"; };
+		A85421B92DEEEEBA005D5BA5 /* TopLeftLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopLeftLabel.swift; sourceTree = "<group>"; };
+		A85421BB2DEEF243005D5BA5 /* AICustomDialogManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AICustomDialogManager.swift; sourceTree = "<group>"; };
+		A85421BD2DEEF485005D5BA5 /* PhotoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoManager.swift; sourceTree = "<group>"; };
+		A85421BF2DEEF6AE005D5BA5 /* AISaveNotifyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AISaveNotifyManager.swift; sourceTree = "<group>"; };
+		A85421C12DEEF876005D5BA5 /* AIKFTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AIKFTool.swift; sourceTree = "<group>"; };
+		A85421C52DEF03C8005D5BA5 /* ASAICalendarHistoryVC+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ASAICalendarHistoryVC+View.swift"; sourceTree = "<group>"; };
 		A8990E1A2DE40B8500DD55FE /* AICalendarWallpaper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AICalendarWallpaper.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		A8990E322DE40B8C00DD55FE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		A8990E332DE40B8C00DD55FE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -80,7 +127,6 @@
 		A8990E6A2DE441AC00DD55FE /* TSNetWork+Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSNetWork+Error.swift"; sourceTree = "<group>"; };
 		A8990E6B2DE441AC00DD55FE /* TSNetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSNetworkManager.swift; sourceTree = "<group>"; };
 		A8990E6C2DE441AC00DD55FE /* TSNetWork+Business.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSNetWork+Business.swift"; sourceTree = "<group>"; };
-		A8990E6D2DE441AC00DD55FE /* TSNetworkManager+Loading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSNetworkManager+Loading.swift"; sourceTree = "<group>"; };
 		A8990E732DE4424A00DD55FE /* CpuMapManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CpuMapManager.swift; sourceTree = "<group>"; };
 		A8990E752DE4430F00DD55FE /* ASAICalendarVC+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ASAICalendarVC+View.swift"; sourceTree = "<group>"; };
 		A8990E782DE4437F00DD55FE /* ASCommonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASCommonView.swift; sourceTree = "<group>"; };
@@ -124,6 +170,44 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		A854218F2DEED07E005D5BA5 /* Ex */ = {
+			isa = PBXGroup;
+			children = (
+				A85421AB2DEEE442005D5BA5 /* UIStackView+Ex.swift */,
+				A85421A92DEEE244005D5BA5 /* Array+Ex.swift */,
+				A854219C2DEEE0D2005D5BA5 /* UIColor+Ex.swift */,
+				A854219A2DEEE088005D5BA5 /* String+Ex.swift */,
+				A85421902DEED1D2005D5BA5 /* UILabel+Ex.swift */,
+				A85421922DEED266005D5BA5 /* UIButton+Ex.swift */,
+				A85421942DEED285005D5BA5 /* UIView+Ex.swift */,
+				A85421962DEED297005D5BA5 /* UIImageView+Ex.swift */,
+				A85421982DEED2B8005D5BA5 /* UIFont+Ex.swift */,
+			);
+			path = Ex;
+			sourceTree = "<group>";
+		};
+		A854219E2DEEE108005D5BA5 /* Base */ = {
+			isa = PBXGroup;
+			children = (
+				A854219F2DEEE11E005D5BA5 /* TSBaseModel.swift */,
+				A85421A12DEEE159005D5BA5 /* TSBaseNavigationBarView.swift */,
+				A85421A32DEEE16D005D5BA5 /* TSBaseVC.swift */,
+				A85421A52DEEE181005D5BA5 /* TSBaseView.swift */,
+				A85421A72DEEE1B0005D5BA5 /* TSBaseCollectionCell.swift */,
+			);
+			path = Base;
+			sourceTree = "<group>";
+		};
+		A85421AE2DEEEA66005D5BA5 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				A85421AF2DEEEA76005D5BA5 /* TSUIExpandedTouchButton.swift */,
+				A85421B92DEEEEBA005D5BA5 /* TopLeftLabel.swift */,
+				A85421BF2DEEF6AE005D5BA5 /* AISaveNotifyManager.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		A8990E112DE40B8500DD55FE = {
 			isa = PBXGroup;
 			children = (
@@ -229,10 +313,19 @@
 		A8990E4E2DE4159300DD55FE /* Common */ = {
 			isa = PBXGroup;
 			children = (
+				A85421AE2DEEEA66005D5BA5 /* View */,
+				A854219E2DEEE108005D5BA5 /* Base */,
+				A854218F2DEED07E005D5BA5 /* Ex */,
 				A8990E6E2DE441AC00DD55FE /* TSNetWork */,
 				A8990E602DE4187700DD55FE /*  Notification+Ex.swift */,
 				A8990E732DE4424A00DD55FE /* CpuMapManager.swift */,
 				A8990E4F2DE4159E00DD55FE /* Common.swift */,
+				A85421B32DEEED88005D5BA5 /* WindowHelper.swift */,
+				A85421B52DEEEE7B005D5BA5 /* TSRandomTextTool.swift */,
+				A85421B72DEEEE8B005D5BA5 /* TSPlaceholderTextView.swift */,
+				A85421BB2DEEF243005D5BA5 /* AICustomDialogManager.swift */,
+				A85421BD2DEEF485005D5BA5 /* PhotoManager.swift */,
+				A85421C12DEEF876005D5BA5 /* AIKFTool.swift */,
 			);
 			path = Common;
 			sourceTree = "<group>";
@@ -267,7 +360,6 @@
 				A8990E6A2DE441AC00DD55FE /* TSNetWork+Error.swift */,
 				A8990E6B2DE441AC00DD55FE /* TSNetworkManager.swift */,
 				A8990E6C2DE441AC00DD55FE /* TSNetWork+Business.swift */,
-				A8990E6D2DE441AC00DD55FE /* TSNetworkManager+Loading.swift */,
 			);
 			path = TSNetWork;
 			sourceTree = "<group>";
@@ -384,6 +476,7 @@
 			children = (
 				A8990EB62DE55FC600DD55FE /* View */,
 				A8990EB22DE55CAA00DD55FE /* ASAICalendarHistoryVC.swift */,
+				A85421C52DEF03C8005D5BA5 /* ASAICalendarHistoryVC+View.swift */,
 				A8990EB42DE55F1400DD55FE /* ASAICalendarHistoryCell.swift */,
 			);
 			path = ASAICalendarHistoryVC;
@@ -531,41 +624,64 @@
 			buildActionMask = 2147483647;
 			files = (
 				A8990E9C2DE46E1E00DD55FE /* ASActionInfoModel.swift in Sources */,
+				A85421A62DEEE183005D5BA5 /* TSBaseView.swift in Sources */,
+				A85421C02DEEF6AF005D5BA5 /* AISaveNotifyManager.swift in Sources */,
 				A8990E9E2DE46E4200DD55FE /* ASRealmManager.swift in Sources */,
 				A8990E972DE46D9300DD55FE /* ASAIGeneratorVC+Load.swift in Sources */,
+				A85421B02DEEEA79005D5BA5 /* TSUIExpandedTouchButton.swift in Sources */,
 				A8990E542DE4166E00DD55FE /* ASWallpaperVC.swift in Sources */,
 				A8990E692DE41DAF00DD55FE /* ASBusinessWebVC.swift in Sources */,
 				A8990E832DE452EB00DD55FE /* ASAICalendarStyleView.swift in Sources */,
+				A85421BC2DEEF244005D5BA5 /* AICustomDialogManager.swift in Sources */,
 				A8990E522DE4166600DD55FE /* ASLaunch.swift in Sources */,
+				A85421C62DEF03CD005D5BA5 /* ASAICalendarHistoryVC+View.swift in Sources */,
 				A8990E7E2DE44A6E00DD55FE /* ASPromptTextView.swift in Sources */,
 				A8990E612DE4187800DD55FE /*  Notification+Ex.swift in Sources */,
 				A8990EB32DE55CAB00DD55FE /* ASAICalendarHistoryVC.swift in Sources */,
 				A8990E3C2DE40B8C00DD55FE /* AppDelegate.swift in Sources */,
+				A854219B2DEEE093005D5BA5 /* String+Ex.swift in Sources */,
 				A8990E5F2DE4176C00DD55FE /* ASConfig.swift in Sources */,
+				A85421AC2DEEE448005D5BA5 /* UIStackView+Ex.swift in Sources */,
+				A85421B62DEEEE7C005D5BA5 /* TSRandomTextTool.swift in Sources */,
 				A8990E502DE4159F00DD55FE /* Common.swift in Sources */,
 				A8990EB82DE55FE100DD55FE /* ASAIGenerateCellView.swift in Sources */,
+				A85421B82DEEEE8C005D5BA5 /* TSPlaceholderTextView.swift in Sources */,
 				A8990E632DE41D2D00DD55FE /* APSettingVC+Col.swift in Sources */,
+				A85421AA2DEEE24B005D5BA5 /* Array+Ex.swift in Sources */,
 				A8990EA02DE46E5E00DD55FE /* ASDBHistoryManager.swift in Sources */,
 				A8990E5C2DE4168D00DD55FE /* ASSettingVC.swift in Sources */,
 				A8990E922DE46BFB00DD55FE /* ASGeneratorErrorView.swift in Sources */,
+				A85421972DEED2A5005D5BA5 /* UIImageView+Ex.swift in Sources */,
 				A8990EA52DE4725B00DD55FE /* ASProgressState.swift in Sources */,
+				A85421B42DEEED91005D5BA5 /* WindowHelper.swift in Sources */,
 				A8990EA22DE46E7E00DD55FE /* ASDBActionInfoModel.swift in Sources */,
+				A85421A22DEEE159005D5BA5 /* TSBaseNavigationBarView.swift in Sources */,
+				A85421912DEED1D8005D5BA5 /* UILabel+Ex.swift in Sources */,
 				A8990E902DE46BF400DD55FE /* ASGeneratorLoadingView.swift in Sources */,
 				A8990EA72DE4726500DD55FE /* ASBaseOperation.swift in Sources */,
 				A8990E742DE4424A00DD55FE /* CpuMapManager.swift in Sources */,
 				A8990EB52DE55F1D00DD55FE /* ASAICalendarHistoryCell.swift in Sources */,
 				A8990E5A2DE4168700DD55FE /* ASAICalendarVC.swift in Sources */,
 				A8990EAE2DE47C2200DD55FE /* ASGenerateTTPOperation.swift in Sources */,
+				A85421952DEED28A005D5BA5 /* UIView+Ex.swift in Sources */,
 				A8990E8E2DE46BEA00DD55FE /* ASGeneratorView.swift in Sources */,
 				A8990E8B2DE463CE00DD55FE /* ASAppBtnView.swift in Sources */,
+				A85421C22DEEF881005D5BA5 /* AIKFTool.swift in Sources */,
+				A85421992DEED2BC005D5BA5 /* UIFont+Ex.swift in Sources */,
+				A85421A82DEEE1B1005D5BA5 /* TSBaseCollectionCell.swift in Sources */,
 				A8990E812DE451A600DD55FE /* ASAICalendarVM.swift in Sources */,
+				A85421BA2DEEEEBB005D5BA5 /* TopLeftLabel.swift in Sources */,
 				A8990EAC2DE4778E00DD55FE /* ASGenerateBaseOperation.swift in Sources */,
 				A8990E952DE46D8B00DD55FE /* ASAIGeneratorVC.swift in Sources */,
 				A8990E4D2DE414F600DD55FE /* ASTabBarVC.swift in Sources */,
 				A8990E662DE41D9C00DD55FE /* ASTutorialsVC.swift in Sources */,
 				A8990E7B2DE4438C00DD55FE /* ASLeftHeaderView.swift in Sources */,
-				A8990E6F2DE441AC00DD55FE /* TSNetworkManager+Loading.swift in Sources */,
+				A85421BE2DEEF487005D5BA5 /* PhotoManager.swift in Sources */,
+				A854219D2DEEE0E1005D5BA5 /* UIColor+Ex.swift in Sources */,
+				A85421A42DEEE16E005D5BA5 /* TSBaseVC.swift in Sources */,
+				A85421932DEED268005D5BA5 /* UIButton+Ex.swift in Sources */,
 				A8990E702DE441AC00DD55FE /* TSNetWork+Business.swift in Sources */,
+				A85421A02DEEE11F005D5BA5 /* TSBaseModel.swift in Sources */,
 				A8990EBA2DE592B500DD55FE /* ASPageNullView.swift in Sources */,
 				A8990E712DE441AC00DD55FE /* TSNetworkManager.swift in Sources */,
 				A8990E722DE441AC00DD55FE /* TSNetWork+Error.swift in Sources */,

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

@@ -7,7 +7,7 @@
 		<key>AICalendarWallpaper.xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>15</integer>
+			<integer>13</integer>
 		</dict>
 	</dict>
 </dict>

+ 8 - 21
AICalendarWallpaper/AppDelegate.swift

@@ -32,33 +32,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     }
     
     func goToTab() {
-        window?.rootViewController = ASTabBarVC()
+        window?.rootViewController = AITabBarController()
     }
 
     func JudgmentSkipPage() {
-//        if AppDelegate.isFirstInstallApp() {
-//            let bootPageVC = TSBootPageVC { [weak self] in
-//                guard let self = self else { return }
-//                UserDefaults.standard.set("1", forKey: "isFirstInstallApp")
-//                UserDefaults.standard.synchronize()
-//                goToTab()
-//            }
-//            let navi = TSBaseNavigationC(rootViewController: bootPageVC)
-//            window?.rootViewController = navi
-//        } else {
-            UserDefaults.standard.set("1", forKey: "isFirstInstallApp")
-            UserDefaults.standard.synchronize()
-            goToTab()
-//        }
+        UserDefaults.standard.set("1", forKey: "isFirstInstallApp")
+        UserDefaults.standard.synchronize()
+        goToTab()
     }
 
     func initPlatform() {
-        TSColorConfigShared.naviMianTextColor = .white
-        TSColorConfigShared.mainBg = .mainBg
-        
-//        DispatchQueue.main.async {//先提前调用,启动下数据库.
-//            debugPrint("ASRMShared.ringDBHistory.istModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
-//        }
+
+        DispatchQueue.main.async {//先提前调用,启动下数据库.
+            debugPrint("ASRMShared.ringDBHistory.istModels.count = \(ASRMShared.cWallpaperDBHistory.listModels.count)")
+        }
 
     }
 }

+ 9 - 3
AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryCell.swift

@@ -73,19 +73,25 @@ class ASAICalendarHistoryCell: TSBaseCollectionCell  {
         cornerRadius = 16.0
         backgroundColor = .cardColor
         
-        contentView.addSubview(showImageView)
+        let itemW = (k_ScreenWidth-43.0)/2.0
+        let itemSize = CGSize(width: itemW, height: kGetUIH(designSize: CGSizeMake(166, 314), currentW: itemW))
+        bgContentView.snp.makeConstraints { make in
+            make.size.equalTo(itemSize)
+        }
+        
+        bgContentView.addSubview(showImageView)
         showImageView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
         
-        contentView.addSubview(exampleView)
+        bgContentView.addSubview(exampleView)
         exampleView.snp.makeConstraints { make in
             make.top.equalTo(8)
             make.leading.equalTo(8)
             make.height.equalTo(20)
         }
   
-        contentView.addSubview(generateView)
+        bgContentView.addSubview(generateView)
         generateView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }

+ 23 - 0
AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryVC+View.swift

@@ -0,0 +1,23 @@
+//
+//  ASAICalendarHistoryVC+View.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+extension ASAICalendarHistoryVC {
+    
+    func creatNavBarView()->TSBaseNavContentBarView{
+        let navBarView = TSBaseNavContentBarView()
+        let label = UILabel.createLabel(text: "AI Calendar Wallpaper".localized,font:.font(size: 26,weight: .semibold))
+        navBarView.barView.addSubview(label)
+        label.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.leading.equalTo(16.0)
+        }
+        
+        label.kAddTextGradient()
+        return navBarView
+    }
+    
+}

+ 61 - 43
AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/ASAICalendarHistoryVC.swift

@@ -8,57 +8,66 @@
 class ASAICalendarHistoryVC: TSBaseVC {
     var listModelArray: [ASActionInfoModel] = []
     var dataChangedBlock:(()->Void)?
+    lazy var navBarView: TSBaseNavContentBarView = creatNavBarView()
     
-    lazy var layout: UICollectionViewFlowLayout = {
+    lazy var collectionView: UICollectionView = {
         let layout = UICollectionViewFlowLayout()
         layout.scrollDirection = .vertical
-        
-        let itemW = (k_ScreenWidth-43.0)/2.0
-        layout.itemSize = CGSize(width: itemW, height: kGetScaleHeight(originalSize: CGSizeMake(166, 314), width:itemW))
+        layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
         layout.minimumInteritemSpacing = 14.0
         layout.minimumLineSpacing = 14.0
-        return layout
-    }()
-    private var collectionViewObserver: TSCollectionViewObserver!
-    lazy var collectionView: UICollectionView = {
+        
         let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
         collectionView.delegate = self
         collectionView.dataSource = self
         collectionView.showsVerticalScrollIndicator = false
         collectionView.showsHorizontalScrollIndicator = false
         collectionView.backgroundColor = .clear
-        collectionView.contentInset = UIEdgeInsets(top: 14, left: 14, bottom: 14, right: 14)
+        collectionView.contentInset = UIEdgeInsets(top: 14, left: 0, bottom: 21+k_Height_TabBar+creatBtnView.btnSize.height + 10, right: 0)
         collectionView.register(ASAICalendarHistoryCell.self, forCellWithReuseIdentifier: ASAICalendarHistoryCell.cellID)
+        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "UICollectionViewCell")
         if #available(iOS 11.0, *) {
             collectionView.contentInsetAdjustmentBehavior = .never
         }
-        collectionView.isScrollEnabled = false
+        collectionView.isScrollEnabled = true
         return collectionView
     }()
     
     
-    lazy var pageNullView: ASPageNullView = {
-        let pageNullView = ASPageNullView()
-        pageNullView.isHidden = true
-        return pageNullView
+//    lazy var pageNullView: ASPageNullView = {
+//        let pageNullView = ASPageNullView()
+//        pageNullView.isHidden = true
+//        return pageNullView
+//    }()
+    lazy var creatBtnView = produceVC.creatBtnView
+    lazy var produceVC: ASAICalendarVC = {
+        let produceVC = ASAICalendarVC()
+        return produceVC
     }()
-    
-    
+
     override func createView() {
-        
-        setNavBarViewHidden(true)
-        
-        contentView.addSubview(pageNullView)
-        pageNullView.snp.makeConstraints { make in
+        addChild(produceVC)
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
         
+//        contentView.addSubview(pageNullView)
+//        pageNullView.snp.makeConstraints { make in
+//            make.edges.equalToSuperview()
+//        }
+        
         contentView.addSubview(collectionView)
         collectionView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
-            make.height.equalTo(k_ScreenHeight)
         }
         
+        contentView.addSubview(creatBtnView)
+        creatBtnView.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.bottom.equalTo(-21-k_Height_TabBar)
+            make.size.equalTo(creatBtnView.btnSize)
+        }
     }
     
     override func viewWillAppear(_ animated: Bool) {
@@ -67,19 +76,7 @@ class ASAICalendarHistoryVC: TSBaseVC {
     }
     
     override func dealThings() {
-        
-        // 监听collectionView 的 contentSize
-        collectionViewObserver = TSCollectionViewObserver(collectionView: collectionView)
-        collectionViewObserver.onContentSizeChange = { [weak self] size in
-            guard let self = self else { return }
-            print("collectionViewObserver 内容大小变化: \(size)")
-            collectionView.snp.updateConstraints { make in
-                make.height.equalTo(size.height+20)
-            }
-        }
-        
         updateListView()
-    
         NotificationCenter.default.addObserver(self, selector: #selector(operationChanged(_:)), name: .kGenerateTTPOperationChanged, object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(updateListView), name: .kTextToPhotoDataChanged, object: nil)
     }
@@ -105,8 +102,8 @@ class ASAICalendarHistoryVC: TSBaseVC {
     }
     
     func updateView() {
-        collectionView.reloadData()
-        pageNullView.isHidden = listModelArray.count > 0
+        collectionView.reloadSections(IndexSet(integer: 1))
+//        pageNullView.isHidden = listModelArray.count > 0
     }
 }
 
@@ -114,22 +111,43 @@ class ASAICalendarHistoryVC: TSBaseVC {
 extension ASAICalendarHistoryVC: UICollectionViewDataSource ,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
     
     public func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
+        return 2
     }
     
     public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        if section == 0 {
+            return 1
+        }
         return listModelArray.count
     }
     
     public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ASAICalendarHistoryCell.cellID, for: indexPath) as! ASAICalendarHistoryCell
-        cell.indexPath = indexPath
-        if let model = listModelArray.safeObj(At: indexPath.item){
-            cell.model = model
+        if indexPath.section == 0 {
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UICollectionViewCell", for: indexPath)
+            if cell.contentView.subviews.isEmpty{
+                cell.contentView.addSubview(produceVC.view)
+                produceVC.view.snp.makeConstraints { make in
+                    make.edges.equalToSuperview()
+                }
+            }
+            return cell
+        }else{
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ASAICalendarHistoryCell.cellID, for: indexPath) as! ASAICalendarHistoryCell
+            cell.indexPath = indexPath
+            if let model = listModelArray.safeAny(At: indexPath.item){
+                cell.model = model
+            }
+            return cell
         }
-        return cell
     }
-
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
+          switch section {
+          case 0:
+              return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+          default:
+              return UIEdgeInsets(top: 0, left: 14, bottom: 0, right: 14)
+          }
+      }
     public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
         
     }

+ 1 - 1
AICalendarWallpaper/Business/AICalendar/ASAICalendarHistoryVC/View/ASAIGenerateCellView.swift

@@ -15,7 +15,7 @@ class ASAIGenerateCellView: TSBaseView {
     
     lazy var refreshBtn: TSUIExpandedTouchButton = {
         let refreshBtn = TSUIExpandedTouchButton()
-        refreshBtn.setUpButton(image: UIImage(named: "refresh_white"))
+        refreshBtn.setUpBtn(image: UIImage(named: "refresh_white"))
         {[weak self]  in
             guard let self = self else { return }
             refreshHandel?()

+ 5 - 16
AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/ASAICalendarVC+View.swift

@@ -44,7 +44,7 @@ extension ASAICalendarVC {
     
     func creatCreatBtnView() -> ASAppBtnView{
         let creatBtnView = ASAppBtnView()
-        creatBtnView.setUpButton(style: .generate) { [weak self] in
+        creatBtnView.setUpBtn(style: .generate) { [weak self] in
             guard let self = self else { return }
             generateAI()
         }
@@ -71,21 +71,10 @@ extension ASAICalendarVC {
 
 extension ASAICalendarVC {
     
-    func creatCusStackView() -> TSCustomStackView {
-        let cusStackView = TSCustomStackView(axis: .vertical, spacing: 0)
-        cusStackView.scrollView.isScrollEnabled = true
-        return cusStackView
-    }
-
     func setUpCusStackView() {
-        
-        cusStackView.addSubviewToStack(hintTextView)
-        cusStackView.addSubviewToStack(ASLeftHeaderView.creatTitleView(image: .generateStyle,title: "Select Styles".localized))
-        cusStackView.addSubviewToStack(styleView)
-        cusStackView.addSubviewToStack(ASLeftHeaderView.creatTitleView(image: .generateHistory,title: "Generate History".localized))
-        cusStackView.addSubviewToStack(calendarHistoryVC.view)
-//        cusStackView.addSpacing(length: k_Height_TabBar+88)
-//        cusStackView.addSpacing(length: 88)
+        cusStackView.addArrangedView(hintTextView)
+        cusStackView.addArrangedView(ASLeftHeaderView.creatTitleView(image: .generateStyle,title: "Select Styles".localized))
+        cusStackView.addArrangedView(styleView)
+        cusStackView.addArrangedView(ASLeftHeaderView.creatTitleView(image: .generateHistory,title: "Generate History".localized))
     }
-
 }

+ 5 - 18
AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/ASAICalendarVC.swift

@@ -13,36 +13,23 @@ class ASAICalendarVC: TSBaseVC {
     }()
     
     lazy var navBarView: TSBaseNavContentBarView = creatNavBarView()
-    lazy var cusStackView: TSCustomStackView = creatCusStackView()
+    lazy var cusStackView: UIStackView = UIStackView.creatStackView()
     lazy var hintTextView: ASPromptTextView = creatCustomTextView()
     lazy var styleView: ASAICalendarStyleView = creatStyleView()
     lazy var creatBtnView: ASAppBtnView = creatCreatBtnView()
     
-    lazy var calendarHistoryVC: ASAICalendarHistoryVC = {
-        let calendarHistoryVC = ASAICalendarHistoryVC()
-        return calendarHistoryVC
-    }()
     
     override func createView() {
         
         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()
-        }
+        setNavBarViewHidden(true)
+
         contentView.addSubview(cusStackView)
         cusStackView.snp.makeConstraints { make in
-            make.edges.equalToSuperview()
-        }
-        
-        contentView.addSubview(creatBtnView)
-        creatBtnView.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-            make.bottom.equalTo(-21-k_Height_TabBar)
-            make.size.equalTo(creatBtnView.btnSize)
+            make.top.leading.trailing.bottom.equalToSuperview()
+            make.width.equalTo(k_ScreenWidth)
         }
         
         setUpCusStackView()

+ 1 - 1
AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/VM/ASAICalendarVM.swift

@@ -36,7 +36,7 @@ class ASAICalendarVM {
         if let dataArray = Mapper<ASGenerateStyleModel>().mapArray(JSONfile: "calendar_ttp_style.json"){
             ptpStyleModels = dataArray
             
-            if let model = dataArray.safeObj(At: generateStyleIndex) {
+            if let model = dataArray.safeAny(At: generateStyleIndex) {
                 selectedGenerateModel = model //加上默认的选择
             }
         }

+ 44 - 40
AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/View/ASAICalendarStyleView.swift

@@ -14,7 +14,7 @@ class ASAICalendarStyleView: TSBaseView {
         didSet{
             if generateStyleModels.count <= 0 { return }
             DispatchQueue.main.async {
-                self.colView.collectionView.selectItem(at: IndexPath(item: self.generateStyleIndex, section: 0), animated: true, scrollPosition: .centeredVertically)
+                self.collectionView.selectItem(at: IndexPath(item: self.generateStyleIndex, section: 0), animated: true, scrollPosition: .centeredVertically)
             }
         }
     }
@@ -22,7 +22,7 @@ class ASAICalendarStyleView: TSBaseView {
     var generateStyleModels:[ASGenerateStyleModel] = []
     {
         didSet{
-            colView.reload(with: [TSSimpleSectionData(items: generateStyleModels)])
+            collectionView.reloadData()
             self.generateStyleIndex = abs(generateStyleIndex)
         }
     }
@@ -34,30 +34,31 @@ class ASAICalendarStyleView: TSBaseView {
         }
     }
 
-    lazy var colView: TSSimpleCollectionView = {
-        let identifier = "ASAICalendarStyleCell"
-
+    let identifier = "ASAICalendarStyleCell"
+    lazy var collectionView: UICollectionView = {
         let layout = UICollectionViewFlowLayout()
-        let cp = TSSimpleCollectionView()
-        cp.collectionView.isScrollEnabled = true
-        cp.layout.minimumLineSpacing = 10
-        cp.layout.minimumInteritemSpacing = 10
-        cp.layout.scrollDirection = .horizontal
-        cp.delegate = self
-        let contentInset = UIEdgeInsets(top: 0, left: 14, bottom: 0, right: 14)
-        cp.collectionView.contentInset = contentInset
-        cp.layout.itemSize = CGSize(width: 86, height: 108)
-        cp.registerCell(ASAICalendarStyleCell.self,identifier:identifier)
-        cp.cellIdentifierForItem = { data in
-            return identifier
+        layout.scrollDirection = .horizontal
+        layout.itemSize = CGSize(width: 86, height: 108)
+        layout.minimumInteritemSpacing = 10.0
+        layout.minimumLineSpacing = 10.0
+        
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.backgroundColor = .clear
+        collectionView.contentInset = UIEdgeInsets(top: 0, left: 14, bottom: 0, right: 14)
+        collectionView.register(ASAICalendarStyleCell.self, forCellWithReuseIdentifier: identifier)
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
         }
-
-        return cp
+        return collectionView
     }()
-    
+
     override func creatUI() {
-        contentView.addSubview(colView)
-        colView.snp.makeConstraints { make in
+        contentView.addSubview(collectionView)
+        collectionView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
             make.height.equalTo(108)
         }
@@ -68,34 +69,37 @@ class ASAICalendarStyleView: TSBaseView {
     }
 }
 
-extension ASAICalendarStyleView: TSSimpleCollectionViewDelegate {
+extension ASAICalendarStyleView: UICollectionViewDataSource ,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
+
+    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return generateStyleModels.count
+    }
     
-    func collectionView(didTrigger event: TSSmalCoacopods.TSSimpleCellEvent) {
-        switch event.action {
-        case .tap:
-            generateStyleIndex = event.indexPath.row
-            if let model = generateStyleModels.safeObj(At: generateStyleIndex) {
-                generateStyleModel = model
-            }
-        default:
-            break
+    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! ASAICalendarStyleCell
+        if let model = generateStyleModels.safeAny(At: indexPath.item){
+            cell.model = model
+        }
+        return cell
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        generateStyleIndex = indexPath.row
+        if let model = generateStyleModels.safeAny(At: generateStyleIndex) {
+            generateStyleModel = model
         }
     }
     
 }
 
 
-class ASAICalendarStyleCell: TSBaseCollectionCell ,TSSimpleConfigurableView {
+class ASAICalendarStyleCell: TSBaseCollectionCell {
     
-    weak var delegate: (any TSSmalCoacopods.TSSimpleCollectionViewDelegate)?
-    var indexPath: IndexPath = IndexPath(item: 0, section: 0)
-    var data: Any? {
+    var model: ASGenerateStyleModel = ASGenerateStyleModel() {
         didSet {
-            if let model = data as? ASGenerateStyleModel {
 //                proImageView.isHidden = !model.vip
-                textLab.text = model.imageText.localized
-                imageView.image = UIImage(named: model.imageName)
-            }
+            textLab.text = model.imageText.localized
+            imageView.image = UIImage(named: model.imageName)
         }
     }
     

+ 2 - 2
AICalendarWallpaper/Business/AICalendar/ASAICalendarVC/View/ASPromptTextView.swift

@@ -51,7 +51,7 @@ class ASPromptTextView : TSBaseView{
     }()
     
     lazy var inspirationBtn: UIButton = {
-        let inspirationBtn = UIButton.createButton(
+        let inspirationBtn = UIButton.createBtn(
             title: "Surprise Me".localized,
             image: .textInputHint,
             backgroundColor: .textMain.withAlphaComponent(0.1),
@@ -72,7 +72,7 @@ class ASPromptTextView : TSBaseView{
     
     lazy var clearBtn: TSUIExpandedTouchButton = {
         let clearBtn = TSUIExpandedTouchButton()
-        clearBtn.setUpButton(image: UIImage(named: "clear_text"))
+        clearBtn.setUpBtn(image: UIImage(named: "clear_text"))
         { [weak self]  in
             guard let self = self else { return }
             customTextView.text = ""

+ 27 - 33
AICalendarWallpaper/Business/ASAIGeneratorVC/ASAIGeneratorVC.swift

@@ -29,7 +29,7 @@ class ASAIGeneratorVC: TSBaseVC {
 
     
     lazy var saveBtn: UIButton = {
-        let saveBtn = UIButton.createButton(title:"Save".localized,backgroundImage:.submitBtnBg,font: UIFont.font(size: 14,weight: .medium),titleColor:.white)
+        let saveBtn = UIButton.createBtn(title:"Save".localized,backgroundImage:.submitBtnBg,font: UIFont.font(size: 14,weight: .medium),titleColor:.white)
         { [weak self]  in
             guard let self = self else { return }
             clickSubmitBtn()
@@ -38,7 +38,7 @@ class ASAIGeneratorVC: TSBaseVC {
     }()
     
 //    lazy var xBtn: UIButton = {
-//        let xBtn = UIButton.createButton(image: UIImage(named: "page_x")) { [weak self]  in
+//        let xBtn = UIButton.createBtn(image: UIImage(named: "page_x")) { [weak self]  in
 //            guard let self = self else { return }
 //            closePage()
 //        }
@@ -46,7 +46,7 @@ class ASAIGeneratorVC: TSBaseVC {
 //    }()
     
     lazy var xBtn: UIButton = {
-        let xBtn = UIButton.createButton(image: .navBack,backgroundColor: .black.withAlphaComponent(0.4),corner: 18.0) { [weak self]  in
+        let xBtn = UIButton.createBtn(image: .navBack,backgroundColor: .black.withAlphaComponent(0.4),corner: 18.0) { [weak self]  in
             guard let self = self else { return }
             closePage()
         }
@@ -56,7 +56,7 @@ class ASAIGeneratorVC: TSBaseVC {
     
     lazy var previewImageView = UIImageView.createImageView(image: .preview,contentMode: .scaleAspectFill)
     lazy var previewBtn: UIButton = {
-        let previewBtn = UIButton.createButton(image: .phoneWhite,backgroundColor: .black.withAlphaComponent(0.4),corner: 18.0) { [weak self]  in
+        let previewBtn = UIButton.createBtn(image: .phoneWhite,backgroundColor: .black.withAlphaComponent(0.4),corner: 18.0) { [weak self]  in
             guard let self = self else { return }
             previewImageView.isHidden = !previewImageView.isHidden
             self.previewBtn.setImage(previewImageView.isHidden ? .phoneWhite : .phone, for: .normal)
@@ -96,8 +96,8 @@ class ASAIGeneratorVC: TSBaseVC {
             make.width.equalTo(335)
             make.height.equalTo(48)
         }
-        
-        let top = k_Height_StatusBar + 4.0
+
+        let top = k_StatusBar_H + 4.0
         view.addSubview(xBtn)
         xBtn.snp.makeConstraints { make in
             make.top.equalTo(top)
@@ -125,29 +125,24 @@ class ASAIGeneratorVC: TSBaseVC {
         if progressState.isResult {
             self.dismiss(animated: true, completion: nil)
         }else{
-            TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
-                message: "As you leave, your generation will be interrupted and no result.".localized,
-                messageColor: .white,
-                messageFont: .systemFont(ofSize: 16),
-                
-                cancelTitle: "Leave".localized,
-                cancelColor: .white.withAlphaComponent(0.6),
-                
-                confirmTitle: "Wait".localized,
-                confirmColor: .themeColor,
-                
-                cancelAction: { [weak self]  in
-                    guard let self = self else { return }
-                    print("用户点击了Leave")
-                    operation?.cancel()
-                    if let model = infoModel{
-                        dbHistory.deleteListModel(id: model.id)
-                        NotificationCenter.default.post(name: .kTextToPhotoDataChanged, object: nil)
-                    }
-                    self.dismiss(animated: true, completion: nil)
-                },
-                confirmAction: {
-                    print("用户点击了Stay")
+            AICustomDialogManager.display(in: self, settings: AICustomDialogManager.DialogSettings(
+                contentText: "As you leave, your generation will be interrupted and no result.".localized,
+                textColor: .white,
+                textFont: .systemFont(ofSize: 16),
+                dismissText: "Leave".localized,
+                dismissColor: .white.withAlphaComponent(0.6),
+                approveText: "Wait".localized,
+                approveColor: .themeColor,
+                dismissHandler: {
+                    [weak self]  in
+                        guard let self = self else { return }
+                        print("用户点击了Leave")
+                        operation?.cancel()
+                        if let model = infoModel{
+                            dbHistory.deleteListModel(id: model.id)
+                            NotificationCenter.default.post(name: .kTextToPhotoDataChanged, object: nil)
+                        }
+                        self.dismiss(animated: true, completion: nil)
                 }
             ))
         }
@@ -156,14 +151,13 @@ class ASAIGeneratorVC: TSBaseVC {
 
     func clickSubmitBtn(){
         if let image = getSuccessImage() {
-            PhotoManagerShared.saveImageToAlbum(image) { success, error in
+            AIImageSaver.storePicture(image, resultHandler: { success, error in
                 if success {
-                    kSaveSuccesswShared.show(atView:self.view)
-//                    kFirstSaveRateAction()
+                    kAISaveNotifyShared.displayNotification(in: self.view)
                 }else{
                     debugPrint(error)
                 }
-            }
+            })
         }
     }
     

+ 1 - 1
AICalendarWallpaper/Business/ASAIGeneratorVC/ASGeneratorView/ASGeneratorErrorView.swift

@@ -41,7 +41,7 @@ class ASGeneratorErrorView: TSBaseView {
     
     lazy var submitBtn: UIButton = {
         let textColor = "#B48EFF".uiColor
-        let btn = UIButton.createButton(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
+        let btn = UIButton.createBtn(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
         btn.layer.borderColor = textColor.cgColor
         btn.layer.borderWidth = 1.0
         btn.titleLabel?.adjustsFontSizeToFitWidth = true

+ 1 - 1
AICalendarWallpaper/Business/ASAIGeneratorVC/ASGeneratorView/ASGeneratorLoadingView.swift

@@ -66,7 +66,7 @@ class ASGeneratorLoadingView : TSBaseView {
     
     lazy var backgroundGenerateBtn: UIButton = {
         let textColor = "#B48EFF".uiColor
-        let btn = UIButton.createButton(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
+        let btn = UIButton.createBtn(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
         btn.layer.borderColor = textColor.cgColor
         btn.layer.borderWidth = 1.0
         btn.titleLabel?.adjustsFontSizeToFitWidth = true

+ 2 - 2
AICalendarWallpaper/Business/ASCommonView/ASAppBtnView.swift

@@ -44,7 +44,7 @@ class ASAppBtnView: TSBaseView {
         
     }
 
-    func setUpButton(style:ViewStyle,btnSize:CGSize = .zero,clickBlock: @escaping () -> Void) {
+    func setUpBtn(style:ViewStyle,btnSize:CGSize = .zero,clickBlock: @escaping () -> Void) {
         self.btnSize = btnSize
         self.style = style
 //        self.vipFreeNumType = vipFreeNumType
@@ -175,7 +175,7 @@ extension ASAppBtnView{
 func kCreateNormalSubmitBtn(title:String,frame:CGRect,action: (() -> Void)? = nil) -> UIButton {
     let btn = UIButton()
     btn.frame = frame
-    btn.setUpButton(title:title,font: UIFont.font(size: 18,weight: .medium),titleColor:.textMain,corner: frame.height/2,action: action)
+    btn.setUpBtn(title:title,font: UIFont.font(size: 18,weight: .medium),titleColor:.textMain,corner: frame.height/2,action: action)
     btn.setTitleImageSpace(spacing: 8)
 
     var buttonBgImage = UIImage.submitBtnBg

+ 2 - 2
AICalendarWallpaper/Business/OperationQueue/AIGenerate/ASGenerateBaseOperation.swift

@@ -148,9 +148,9 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                             generatingProgress = 0
                             self.handleGenerateSuccess()
                         }
-                        
+               
                         if URL(string:genmojiModel.response.resultUrl) != nil {
-                            UIImageView.downloadImageWithProgress(urlString: genmojiModel.response.resultUrl) { [weak self]  progress in
+                            AIKFTool.downloadImage(urlString: genmojiModel.response.resultUrl) { [weak self]  progress in
                                 guard let self = self else { return }
                                 let progressInt = Int(progress*10.0)
                                 let progressString = "Generating".localized + " \(Int(kPercentScale*100) + progressInt)%"

+ 2 - 1
AICalendarWallpaper/Business/OperationQueue/AIGenerate/ASGenerateTTPOperation.swift

@@ -94,7 +94,8 @@ class ASGenerateTTPOperation:ASGenerateBaseOperation , @unchecked Sendable{
         if let cyModel = copyModel as?ASActionInfoModel {
             let topY = k_Nav_Height+10
             debugPrint("topY=\(topY)")
-            kSaveSuccesswShared.show(atView: window,text: "Successfully generated".localized,deadline: 5.0,bottom: kSaveSuccesswShared.getBottom(topY: topY)) {
+
+            kAISaveNotifyShared.displayNotification(in: window,message: "Successfully generated".localized,duration: 5.0,bottomOffset: kAISaveNotifyShared.calculateBottomOffset(from: topY)){
                 let gennerateVC = ASAIGeneratorVC(generateStyleModel:ASGenerateStyleModel(),infoModel: cyModel) { model in }
                 gennerateVC.modalPresentationStyle = .overFullScreen
                 gennerateVC.modalTransitionStyle = .crossDissolve

+ 20 - 6
AICalendarWallpaper/Business/Setting/APSettingVC+Col.swift

@@ -5,6 +5,20 @@
 //  Created by 100Years on 2025/5/25.
 //
 
+class ASSectionModel {
+    
+    open var itemsArray: [ASItemModel] = []
+}
+
+class ASItemModel {
+    
+    public var tapBlock: ((ASItemModel, Int, Any?) -> Void)?
+    public var leftImageName: String?
+    public var leftImage: UIImage?
+    public var leftTitle: String?
+    public var rightIsHave: Bool = false
+}
+
 
 extension APSettingVC {
  
@@ -33,8 +47,8 @@ extension APSettingVC {
     func createItemModel(leftImage: UIImage,
                          leftTitle: String,
                          rightIsHave: Bool,
-                        tapBlock: @escaping ((TSBasicItemModel, Int, Any?) -> Void)) -> TSBasicItemModel {
-        let model = TSBasicItemModel()
+                        tapBlock: @escaping ((ASItemModel, Int, Any?) -> Void)) -> ASItemModel {
+        let model = ASItemModel()
         model.leftImage = leftImage
         model.leftTitle = leftTitle
         model.rightIsHave = rightIsHave
@@ -51,7 +65,7 @@ extension APSettingVC: UICollectionViewDataSource ,UICollectionViewDelegate {
     }
     
     public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        if let sectionModel = dataArray.safeObj(At: section){
+        if let sectionModel = dataArray.safeAny(At: section){
             return sectionModel.itemsArray.count
         }
         return 0
@@ -61,7 +75,7 @@ extension APSettingVC: UICollectionViewDataSource ,UICollectionViewDelegate {
         
         let cell = collectionView.dequeueReusableCell(withReuseIdentifier: APSettingCell.cellID, for: indexPath)
         if let cell = cell as? APSettingCell {
-            if let sectionModel = dataArray.safeObj(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeObj(At: indexPath.row){
+            if let sectionModel = dataArray.safeAny(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeAny(At: indexPath.row){
                 cell.itemModel = itemModel
             }
         }
@@ -70,7 +84,7 @@ extension APSettingVC: UICollectionViewDataSource ,UICollectionViewDelegate {
     }
 
     public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if let sectionModel = dataArray.safeObj(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeObj(At: indexPath.row){
+        if let sectionModel = dataArray.safeAny(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeAny(At: indexPath.row){
             itemModel.tapBlock?(itemModel,indexPath.row,nil)
         }
     }
@@ -80,7 +94,7 @@ extension APSettingVC: UICollectionViewDataSource ,UICollectionViewDelegate {
 class APSettingCell: TSBaseCollectionCell {
     
     static let cellID = "APSettingCell"
-    var itemModel:TSBasicItemModel = TSBasicItemModel(){
+    var itemModel:ASItemModel = ASItemModel(){
         didSet{
             leftImageView.image = itemModel.leftImage
             titleLab.text = itemModel.leftTitle

+ 13 - 35
AICalendarWallpaper/Business/Setting/ASSettingVC.swift

@@ -23,23 +23,17 @@ class APSettingVC: TSBaseVC {
         return navBarView
     }()
     
-    lazy var cusStackView: TSCustomStackView = {
-        let cusStackView = TSCustomStackView(axis: .vertical, spacing: 0)
-        return cusStackView
-    }()
-    
-    private var collectionViewObserver: TSCollectionViewObserver!
     lazy var collectionView = creatCollectionView()
     
     
     let appid = "6746234900"
-    lazy var dataArray: [TSBasicSectionModel] = {
-        var dataArray = [TSBasicSectionModel]()
-        let sectionModel = TSBasicSectionModel()
+    lazy var dataArray: [ASSectionModel] = {
+        var dataArray = [ASSectionModel]()
+        let sectionModel = ASSectionModel()
         dataArray.append(sectionModel)
 
         //教程
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconHow,
                 leftTitle: "How to set wallpaper".localized,
@@ -50,7 +44,7 @@ class APSettingVC: TSBaseVC {
         }))
         
         //分享
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconShare,
                 leftTitle: "Share us".localized,
@@ -59,11 +53,9 @@ class APSettingVC: TSBaseVC {
                    guard let self = self else { return }
                     
                     let httpAppStoreLink = "https://apps.apple.com/app/id\(appid)"
-                    let text = "Space"
+                    let final = ShareActivityItemProvider(placeholderItem: UIImage(named: "App-Icon")!.compressSize(to: CGSize(width: 100, height: 100)))
                     let url = URL(string: httpAppStoreLink)!
-                    let image = UIImage(named: "App-Icon")!.compressImageSize(to: CGSize(width: 100, height: 100))
-                    let final = ShareActivityItemProvider(placeholderItem: image)
-                    let vc = UIActivityViewController(activityItems: [url, final, text], applicationActivities: nil)
+                    let vc = UIActivityViewController(activityItems: [url, final], applicationActivities: nil)
                     vc.completionWithItemsHandler = { activity, _, _, _ in
                         if let type = activity, type == .copyToPasteboard {
                             UIPasteboard.general.string = httpAppStoreLink
@@ -75,7 +67,7 @@ class APSettingVC: TSBaseVC {
         }))
         
         //评价
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconRate,
                 leftTitle: "Rate us".localized,
@@ -107,7 +99,7 @@ class APSettingVC: TSBaseVC {
         }))
         
         //服务条框
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconTerms,
                 leftTitle: "User Agreement".localized,
@@ -120,7 +112,7 @@ class APSettingVC: TSBaseVC {
         }))
         
         //隐私协议
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconPrivacy,
                 leftTitle: "Privacy Policy".localized,
@@ -133,7 +125,7 @@ class APSettingVC: TSBaseVC {
         }))
         
         //关于我们
-        sectionModel.addSubItemModel(
+        sectionModel.itemsArray.append(
             createItemModel(
                 leftImage: .settingIconAbout,
                 leftTitle: "About us".localized,
@@ -153,28 +145,14 @@ class APSettingVC: TSBaseVC {
         navBarView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
-        
-        contentView.addSubview(cusStackView)
-        cusStackView.snp.makeConstraints { make in
+        contentView.addSubview(collectionView)
+        collectionView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }
-        
-        cusStackView.addSubviewToStack(collectionView,length: 0)
     }
     
     override func dealThings() {
-
-        // 监听collectionView 的 contentSize
-        collectionViewObserver = TSCollectionViewObserver(collectionView: collectionView)
-        collectionViewObserver.onContentSizeChange = { [weak self] size in
-            guard let self = self else { return }
-            print("collectionViewObserver 内容大小变化: \(size)")
-            self.collectionView.snp.updateConstraints { make in
-                make.height.equalTo(size.height)
-            }
-        }
         collectionView.reloadData()
-        
     }
     
 }

+ 75 - 69
AICalendarWallpaper/Business/Tabbar/ASTabBarVC.swift

@@ -6,83 +6,89 @@
 //
 
 import UIKit
-class ASTabBarVC: UITabBarController {
-  
-    private var viewControllerArray: [String] = []
-    private var titleArray: [String] = []
-    private var selectedImageArray: [String] = []
-    private var unselectedImageArray: [String] = []
-    
-    private var interceptVC: UINavigationController = UINavigationController()
+class AITabBarController: UITabBarController {
     
+    // MARK: - Lifecycle
     override func viewDidLoad() {
         super.viewDidLoad()
-        createUI()
-        setUpData()
+        view.backgroundColor = .clear
+        setupTabs()
+        configureTabBarAppearance()
     }
+    
+    // MARK: - Tab Setup
+    private func setupTabs() {
 
-    @objc private func setUpData() {
-        viewControllerArray = ["ASWallpaperVC","ASTodayVC","ASAICalendarVC","APSettingVC"]
-
-        titleArray = ["Wallpaper","Today","AI Calendar","Setting"]
-        selectedImageArray = [
-            "tabbar_selected_wallpaper",
-            "tabbar_selected_today",
-            "tabbar_selected_ai",
-            "tabbar_selected_setting"
+        viewControllers = [
+            createNavController(
+                viewController: ASWallpaperVC(),
+                title: "Wallpaper".localized,
+                image: .tabbarUnSelectWallpaper,
+                selectedImage: .tabbarSelectedWallpaper
+            ),
+            createNavController(
+                viewController: ASTodayVC(),
+                title: "Today".localized,
+                image: .tabbarUnSelectToday,
+                selectedImage: .tabbarSelectedToday
+            ),
+            createNavController(
+                viewController: ASAICalendarHistoryVC(),//ASAICalendarVC(),
+                title: "AI Calendar".localized,
+                image: .tabbarUnSelectAi,
+                selectedImage: .tabbarSelectedAi
+            ),
+            createNavController(
+                viewController: APSettingVC(),
+                title: "Setting".localized,
+                image: .tabbarUnSelectSetting,
+                selectedImage: .tabbarSelectedSetting
+            )
         ]
-        unselectedImageArray = [
-            "tabbar_unSelect_wallpaper",
-            "tabbar_unSelect_today",
-            "tabbar_unSelect_ai",
-            "tabbar_unSelect_setting"
+    }
+    
+    // MARK: - Helper Methods
+    private func createNavController(
+        viewController: UIViewController,
+        title: String,
+        image: UIImage?,
+        selectedImage: UIImage?
+    ) -> UINavigationController {
+        let navController = AINavigationC(rootViewController: viewController)
+        navController.tabBarItem.title = title
+        navController.tabBarItem.image = image?.withRenderingMode(.alwaysOriginal)
+        navController.tabBarItem.selectedImage = selectedImage?.withRenderingMode(.alwaysOriginal)
+        return navController
+    }
+    
+    private func configureTabBarAppearance() {
+        // 自定义 TabBar 外观
+        let appearance = UITabBarAppearance()
+        appearance.configureWithTransparentBackground()
+        
+        // 设置背景色
+        appearance.backgroundColor = "#1E1D29".uiColor
+        let textColor = UIColor.textMain
+        // 设置选中和未选中的颜色
+        let normalAttributes: [NSAttributedString.Key: Any] = [
+            .foregroundColor: textColor,
+            .font: UIFont.systemFont(ofSize: 10, weight: .medium)
         ]
-
-        var tabArray: [UINavigationController] = []
-
-        for i in 0..<viewControllerArray.count {
-            if let rootViewController = viewControllerArray[i].toInstance(of: UIViewController.self) {
-                let title = titleArray[i]
-                let nav = TSBaseNavigationC(rootViewController: rootViewController)
-                nav.view.backgroundColor = UIColor.black
-                nav.tabBarItem = tabBarItem(
-                    title: title.localized,
-                    image: UIImage(named: unselectedImageArray[i]),
-                    selectedImage: UIImage(named: selectedImageArray[i]),
-                    tag: i
-                )
-                tabArray.append(nav)
-            }
+        
+        let selectedAttributes: [NSAttributedString.Key: Any] = [
+            .foregroundColor: textColor.withAlphaComponent(0.4),
+            .font: UIFont.systemFont(ofSize: 10, weight: .bold)
+        ]
+        
+        appearance.stackedLayoutAppearance.normal.titleTextAttributes = normalAttributes
+        appearance.stackedLayoutAppearance.selected.titleTextAttributes = selectedAttributes
+        
+        // 应用到所有 TabBar 状态
+        tabBar.standardAppearance = appearance
+        if #available(iOS 15.0, *) {
+            tabBar.scrollEdgeAppearance = appearance
         }
-
-        self.viewControllers = tabArray
-        interceptVC = tabArray.last!
-    }
-
-    private func createUI() {
-        tabBar.barStyle = .black
-        tabBar.isTranslucent = true
-//        tabBar.backgroundColor = "#1E1D29".uiColor
-//        tabBar.backgroundImage = UIImage.colorFrom(color: tabBar.backgroundColor!, size: CGSize(width: k_ScreenWidth, height: k_TabBar_Height))
         
-        let textColor = UIColor .textMain
-        UITabBar.appearance().unselectedItemTintColor = textColor.withAlphaComponent(0.4)
-        UITabBar.appearance().tintColor = textColor
-
-    }
-
-    private func tabBarItem(title: String, image: UIImage?, selectedImage: UIImage?, tag: Int) -> UITabBarItem {
-        let tabBarItem = UITabBarItem()
-        tabBarItem.image = image?.withRenderingMode(.alwaysOriginal)
-        tabBarItem.title = title
-        tabBarItem.selectedImage = selectedImage?.withRenderingMode(.alwaysOriginal)
-        return tabBarItem
-    }
-
-    deinit {
-        debugPrint("ASTabBarVC deinit")
-        NotificationCenter.default.removeObserver(self)
+        tabBar.isTranslucent = true
     }
-    
-
 }

+ 85 - 0
AICalendarWallpaper/Common/AICustomDialogManager.swift

@@ -0,0 +1,85 @@
+//
+//  AICustomDialogManager.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+import UIKit
+
+public class AICustomDialogManager {
+    
+    // MARK: - Configuration Model
+    public struct DialogSettings {
+        public var interfaceMode: UIUserInterfaceStyle = .dark
+        public var contentText: String
+        public var textColor: UIColor = .black
+        public var textFont: UIFont = .systemFont(ofSize: 14)
+        
+        public var dismissText: String = "取消"
+        public var dismissColor: UIColor = .gray
+        
+        public var approveText: String = "确定"
+        public var approveColor: UIColor = .blue
+        
+        public var dismissHandler: (() -> Void)?
+        public var approveHandler: (() -> Void)?
+        
+        public init(interfaceMode: UIUserInterfaceStyle = .dark,
+                   contentText: String,
+                   textColor: UIColor,
+                   textFont: UIFont,
+                   dismissText: String,
+                   dismissColor: UIColor,
+                   approveText: String,
+                   approveColor: UIColor,
+                   dismissHandler: (() -> Void)? = nil,
+                   approveHandler: (() -> Void)? = nil) {
+            self.interfaceMode = interfaceMode
+            self.contentText = contentText
+            self.textColor = textColor
+            self.textFont = textFont
+            self.dismissText = dismissText
+            self.dismissColor = dismissColor
+            self.approveText = approveText
+            self.approveColor = approveColor
+            self.dismissHandler = dismissHandler
+            self.approveHandler = approveHandler
+        }
+    }
+    
+    // MARK: - Display Dialog
+    public static func display(in parentVC: UIViewController, settings: DialogSettings) {
+        // 1. Create AlertController (use empty string for title to avoid auto-layout issues)
+        let dialog = UIAlertController(title: "", message: "", preferredStyle: .alert)
+        
+        // 2. Customize message content
+        let formattedMessage = NSAttributedString(
+            string: settings.contentText,
+            attributes: [
+                .foregroundColor: settings.textColor,
+                .font: settings.textFont
+            ]
+        )
+        dialog.setValue(formattedMessage, forKey: "attributedMessage")
+        // Set interface style
+        dialog.overrideUserInterfaceStyle = settings.interfaceMode
+        
+        // 3. Add dismiss button
+        let dismiss = UIAlertAction(title: settings.dismissText, style: .default) { _ in
+            settings.dismissHandler?()
+        }
+        dismiss.setValue(settings.dismissColor, forKey: "titleTextColor")
+        dialog.addAction(dismiss)
+        
+        // 4. Add approve button
+        let approve = UIAlertAction(title: settings.approveText, style: .default) { _ in
+            settings.approveHandler?()
+        }
+        approve.setValue(settings.approveColor, forKey: "titleTextColor")
+        dialog.addAction(approve)
+        
+        // 5. Present dialog
+        parentVC.present(dialog, animated: true)
+    }
+}

+ 45 - 0
AICalendarWallpaper/Common/AIKFTool.swift

@@ -0,0 +1,45 @@
+//
+//  AIKFTool.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+import Kingfisher
+struct AIKFTool {
+    static func retrieveImageInMemoryCache(urlString: String) -> UIImage? {
+        return ImageCache.default.retrieveImageInMemoryCache(forKey: urlString)
+    }
+    
+    static func downloadImage(
+        urlString: String,
+        progressHandler: ((Float) -> Void)? = nil,
+        completion: @escaping (UIImage?) -> Void
+    ) {
+
+        guard let url = URL(string: urlString) else {
+            completion(nil)
+            return
+        }
+        
+        KingfisherManager.shared.retrieveImage(
+            with: url,
+            options: [],
+            progressBlock: { receivedSize, totalSize in
+                let progress = Float(receivedSize) / Float(totalSize)
+                DispatchQueue.main.async {
+                    progressHandler?(progress)
+                }
+            },
+            completionHandler: { result in
+                DispatchQueue.main.async {
+                    switch result {
+                    case .success(let value):
+                        completion(value.image)
+                    case .failure:
+                        completion(nil)
+                    }
+                }
+            }
+        )
+    }
+}

+ 78 - 0
AICalendarWallpaper/Common/Base/TSBaseCollectionCell.swift

@@ -0,0 +1,78 @@
+//
+//  TSBaseCollectionCell.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+open class TSBaseCollectionCell: UICollectionViewCell  {
+
+    public lazy var bgContentView:UIView = {
+        let view = UIView()
+        view.backgroundColor = .clear
+        return view
+    }()
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.backgroundColor = .clear
+        self.addSubview(bgContentView)
+        bgContentView.snp.makeConstraints { make in
+            make.top.leading.trailing.bottom.equalTo(0)
+        }
+        creatUI()
+        dealThings()
+    }
+    
+    required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    open func creatUI(){
+        
+    }
+    
+    open func dealThings(){
+        
+    }
+    
+
+    deinit {
+//        debugPrint("<---deinit \(String(describing: self))")
+    }
+    
+}
+
+
+open class TSBaseCollectionnReusableView : UICollectionReusableView  {
+    
+    public lazy var bgContentView:UIView = {
+        let view = UIView()
+        view.backgroundColor = .clear
+        return view
+    }()
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.backgroundColor = .clear
+        self.addSubview(bgContentView)
+        bgContentView.snp.makeConstraints { make in
+            make.top.leading.trailing.bottom.equalTo(0)
+        }
+        creatUI()
+    }
+    
+    required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    open func creatUI(){
+        
+    }
+
+    
+    deinit {
+//        debugPrint("<---deinit \(String(describing: self))")
+    }
+    
+}

+ 53 - 0
AICalendarWallpaper/Common/Base/TSBaseModel.swift

@@ -0,0 +1,53 @@
+//
+//  TSBaseModel.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+import ObjectMapper
+
+open class TSBaseModel: NSObject, Mappable, NSCopying {
+    public static func model(data: Data) -> TSBaseModel? {
+        do {
+            let object = try JSONSerialization.jsonObject(with: data)
+            if let dict = object as? [String: AnyHashable] {
+                return Self.init(json: dict)
+            }
+        } catch _ {
+            return nil
+        }
+        return nil
+    }
+    
+    open var data: Data? {
+        let json = toJSON()
+        do {
+            let data = try JSONSerialization.data(withJSONObject: json)
+            return data
+        } catch _ {
+            return nil
+        }
+    }
+    
+    required convenience public init?(map: ObjectMapper.Map) {
+        self.init()
+        mapping(map: map)
+    }
+    
+    required convenience public init?(json: [String: Any]) {
+        self.init(JSON: json)
+    }
+    
+    open func mapping(map: ObjectMapper.Map) {}
+    
+    open func copy(with zone: NSZone? = nil) -> Any {
+        let json = toJSON()
+        return Self.init(JSON: json) ?? Self.init(JSON: [:])!
+    }
+    
+//    deinit {
+//        debugPrint("♻️♻️♻️ TGRootViewController -> \(type(of: self)) deinit ♻️♻️♻️")
+//    }
+}

+ 173 - 0
AICalendarWallpaper/Common/Base/TSBaseNavigationBarView.swift

@@ -0,0 +1,173 @@
+//
+//  TSBaseNavigationBarView.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+open class TSBaseNavContentBarView: UIView {
+    
+    open lazy var statuView: UIView = {
+       let view = UIView()
+       return view
+   }()
+
+    open lazy var barView: UIView = {
+       let view = UIView()
+       return view
+   }()
+    
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        
+        addSubview(statuView)
+        addSubview(barView)
+        
+        statuView.snp.makeConstraints { make in
+            make.top.leading.trailing.equalTo(0)
+            make.height.equalTo(k_StatusBar_H)
+        }
+
+        barView.snp.makeConstraints { make in
+            make.leading.trailing.equalTo(0)
+            make.top.equalTo(k_StatusBar_H)
+            make.height.equalTo(k_Height_NavBar)
+        }
+
+    }
+    
+    
+    required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+}
+
+open class TSNormalNavigationBarView: TSBaseNavContentBarView {
+
+    // MARK: - Properties
+     var navBgColor: UIColor!
+     var navTitleColor: UIColor!
+     var navTitleFont: UIFont!
+     var navLeftFont: UIFont!
+     var navRightFont: UIFont!
+
+    public lazy var leftNavBtn: UIButton = {
+        let button = createNavButton()
+        button.contentHorizontalAlignment = .left
+        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+        return button
+    }()
+
+    public lazy var titleNavBtn: UIButton = {
+        let button = createNavButton()
+        button.titleLabel?.font = navTitleFont
+        return button
+    }()
+
+    public lazy var rightNavBtn: UIButton = {
+        let button = createNavButton()
+        button.titleLabel?.font = navRightFont
+        button.titleLabel?.adjustsFontSizeToFitWidth = true
+        button.contentHorizontalAlignment = .right
+        button.setTitleColor(.themeColor, for: .normal)
+        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+        return button
+    }()
+
+    // MARK: - Initializers
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        createData()
+        createView()
+    }
+    
+    @MainActor required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+
+    // MARK: - Setup Methods
+    private func createData() {
+        navBgColor = .clear
+        navTitleColor = "#0E1550".uiColor
+        navTitleFont = .font(size: 18,weight:.medium)
+        navLeftFont = .font(size: 16,weight:.medium)
+        navRightFont = .font(size: 16,weight:.medium)
+    }
+
+    private func createView() {
+//        let space: CGFloat = 10
+        let margins: CGFloat = 16
+
+        backgroundColor = navBgColor
+
+  
+        barView.addSubview(leftNavBtn)
+        barView.addSubview(titleNavBtn)
+        barView.addSubview(rightNavBtn)
+
+        leftNavBtn.snp.makeConstraints { make in
+            make.leading.equalTo(margins)
+            make.centerY.equalToSuperview()
+            make.width.height.equalTo(44.0)
+        }
+        
+        rightNavBtn.snp.makeConstraints { make in
+            make.trailing.equalTo(-margins)
+            make.centerY.equalToSuperview()
+            make.width.height.equalTo(44.0)
+        }
+        
+         titleNavBtn.snp.makeConstraints { make in
+             make.leading.equalTo(leftNavBtn.snp.trailing).offset(margins)
+             make.trailing.equalTo(rightNavBtn.snp.leading).offset(-margins)
+             make.centerY.equalToSuperview()
+             make.height.equalTo(44.0)
+         }
+         
+    }
+
+    // MARK: - Helper Methods
+    public func setTitleName(_ name: String) -> UIButton {
+        titleNavBtn.setTitle(name, for: .normal)
+        return titleNavBtn
+    }
+
+    public func setTitleNavigationItem(name: String, imageName: String, target: Any?, action: Selector) -> UIButton {
+        setNavButton(button: titleNavBtn, name: name, imageName: imageName, target: target, action: action)
+        return titleNavBtn
+    }
+
+    public func setLeftNavigationItem(name: String, imageName: String, target: Any?, action: Selector) -> UIButton {
+        setNavButton(button: leftNavBtn, name: name, imageName: imageName, target: target, action: action)
+        return leftNavBtn
+    }
+
+    public func setRightNavigationItem(name: String, imageName: String, target: Any?, action: Selector) -> UIButton {
+        setNavButton(button: rightNavBtn, name: name, imageName: imageName, target: target, action: action)
+        return rightNavBtn
+    }
+
+    public func setNavButton(button: UIButton, name: String, imageName: String, target: Any?, action: Selector) {
+        button.setTitle(name, for: .normal)
+        
+        if imageName.count > 0 {
+            let image = UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal)
+            if let image = image {
+                button.setImage(image, for: .normal)
+            }
+        }
+
+        button.addTarget(target, action: action, for: .touchUpInside)
+    }
+
+    public func createNavButton() -> UIButton {
+        let button = UIButton()
+        button.setTitleColor(navTitleColor, for: .normal)
+        button.titleLabel?.font = navRightFont
+        button.titleLabel?.adjustsFontSizeToFitWidth = true
+        return button
+    }
+}

+ 233 - 0
AICalendarWallpaper/Common/Base/TSBaseVC.swift

@@ -0,0 +1,233 @@
+//
+//  TSBaseVC.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+import UIKit
+import Combine
+
+class AINavigationC:UINavigationController{
+    open override func viewDidLoad() {
+        super.viewDidLoad()
+        navigationBar.isHidden = true
+        view.backgroundColor = .clear
+        interactivePopGestureRecognizer?.isEnabled = true;
+    }
+}
+
+open class TSBaseVC: UIViewController {
+  
+    public var closePageComplete:(()->Void)?
+    
+    public var cancellable: [AnyCancellable] = []
+    
+    public var blurEffect: UIBlurEffect?
+    public lazy var navBlurView: UIVisualEffectView = {
+        let view = UIVisualEffectView()
+        return view
+    }()
+    
+    public lazy var contentView: UIView = {
+        let view = UIView()
+        return view
+    }()
+    
+    
+    public lazy var navBarContentView: UIView = {
+        let view = UIView()
+        view.backgroundColor = .clear
+        return view
+    }()
+    
+    public lazy var normalNavBarView: TSNormalNavigationBarView = {
+        let view = TSNormalNavigationBarView()
+        return view
+    }()
+    
+    
+    public lazy var viewBgImageView: UIImageView = {
+        let view = UIImageView()
+        view.backgroundColor = .clear
+        return view
+    }()
+
+    public lazy var netWorkView: UIView = {
+        let view = UIView()
+        view.backgroundColor = .clear
+        return view
+    }()
+    
+    
+    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+    }
+
+    required public init?(coder: NSCoder) {
+        super.init(coder: coder)
+    }
+
+    /// 提供一个无参数的默认初始化方法
+    public init() {
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    open override func viewDidLoad() {
+        super.viewDidLoad()
+        setupSuperSomeView()
+        createData()
+        createView()
+        dealThings()
+    }
+    
+    private func setupSuperSomeView() {
+        edgesForExtendedLayout = [.all]
+        
+        view.addSubview(contentView)
+        view.addSubview(navBarContentView)
+        
+        contentView.snp.makeConstraints { make in
+            make.top.equalTo(k_Nav_Height)
+            make.leading.trailing.bottom.equalToSuperview()
+        }
+        
+        navBarContentView.snp.makeConstraints { make in
+            make.leading.top.trailing.equalToSuperview()
+            make.height.equalTo(k_Nav_Height)
+        }
+
+        view.backgroundColor = .mainBg
+        view.layoutIfNeeded()
+    }
+    
+    
+    
+    
+    public func setViewBgImageNamed(named:String){
+        if viewBgImageView.superview == nil {
+            view.insertSubview(viewBgImageView, at: 0)
+            viewBgImageView.snp.makeConstraints { make in
+                make.edges.equalToSuperview()
+            }
+        }
+        viewBgImageView.image = UIImage(named: named)
+    }
+    
+    
+    //子类重写
+    open func createData(){
+        
+        
+    }
+    open func createView(){
+        
+        
+    }
+    
+    open func dealThings(){
+        
+        
+    }
+    
+
+    public func addNormalNavBarView(){
+        navBarContentView.addSubview(normalNavBarView)
+        normalNavBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+    }
+
+
+    open override func viewWillAppear(_ animated: Bool) {
+        debugPrint("进入------>\(String(describing: type(of: self)))")
+    }
+
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+        cancellable.removeAll()
+        closePageComplete?()
+        debugPrint("♻️♻️♻️ TGRootViewController -> \(type(of: self)) deinit ♻️♻️♻️")
+    }
+
+    // MARK: - 导航栏方法
+
+    public func setTitleText(_ title: String) {
+       _ = normalNavBarView.setTitleName(NSLocalizedString(title, comment: ""))
+    }
+
+    public func setPageTitle(_ title: String) {
+        let pageTitle = title
+        let backTitle = " "
+        setTitleText(pageTitle)
+        _ = setNavigationItem(backTitle, imageName: "navi_back_white", direction: .left, action: #selector(navBarClickLeftAction))
+    }
+
+    public func setNavigationItem(_ name: String, imageName: String, direction: NSTextAlignment, action: Selector) -> UIButton {
+        if direction == .left {
+            return normalNavBarView.setLeftNavigationItem(name: name, imageName: imageName, target: self, action: action)
+        } else {
+            return normalNavBarView.setRightNavigationItem(name: name, imageName: imageName, target: self, action: action)
+        }
+    }
+
+    @objc open func navBarClickLeftAction() {
+        debugPrint("navBarClickLeftAction -> \(type(of: self))")
+        pop()
+    }
+
+    public func pop() {
+        if navigationController == nil {
+            dismiss(animated: true, completion: nil)
+        } else if navigationController?.presentingViewController != nil, navigationController?.viewControllers.count == 1 {
+            navigationController?.dismiss(animated: true, completion: nil)
+        } else {
+            navigationController?.popViewController(animated: true)
+        }
+    }
+
+}
+
+
+extension TSBaseVC {
+    
+    public func setNavBarViewHidden(_ isHidden: Bool) {
+        navBarContentView.snp.updateConstraints { make in
+            make.height.equalTo(isHidden ? 0 : k_Nav_Height)
+        }
+        
+        contentView.snp.updateConstraints { make in
+            make.top.equalTo(isHidden ? 0 : k_Nav_Height)
+        }
+    }
+    
+    public var isViewVisible: Bool {
+        return isViewLoaded && view.window != nil && presentedViewController == nil
+    }
+    
+    public func addPullDownClosePage() {
+        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleDismissPan(_:)))
+        view.addGestureRecognizer(panGesture)
+    }
+
+    // 手势处理方法
+     @objc public func handleDismissPan(_ gesture: UIPanGestureRecognizer) {
+        let translation = gesture.translation(in: view)
+        let progress = translation.y / view.bounds.height
+        
+        switch gesture.state {
+        case .changed:
+            view.transform = CGAffineTransform(translationX: 0, y: max(0, translation.y))
+        case .ended:
+            if progress > 0.5 || gesture.velocity(in: view).y > 1000 {
+                dismiss(animated: true)
+            } else {
+                UIView.animate(withDuration: 0.3) {
+                    self.view.transform = .identity
+                }
+            }
+        default:
+            break
+        }
+    }
+}

+ 41 - 0
AICalendarWallpaper/Common/Base/TSBaseView.swift

@@ -0,0 +1,41 @@
+//
+//  TSBaseView.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+open class TSBaseView : UIView {
+
+    public lazy var contentView:UIView = {
+        let view = UIView()
+        view.backgroundColor = .clear
+        return view
+    }()
+    
+    public override init(frame: CGRect) {
+        super.init(frame: frame)
+        self.backgroundColor = .clear
+        self.addSubview(contentView)
+        contentView.snp.makeConstraints { make in
+            make.top.leading.trailing.bottom.equalTo(0)
+        }
+        creatUI()
+        dealThings()
+    }
+    
+    required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    open func creatUI(){
+        
+    }
+    
+    
+    open func dealThings(){
+        
+        
+    }
+    
+}

+ 155 - 2
AICalendarWallpaper/Common/Common.swift

@@ -5,8 +5,9 @@
 //  Created by 100Years on 2025/5/25.
 //
 
-@_exported import TSSmalCoacopods
-
+@_exported import UIKit
+@_exported import SnapKit
+@_exported import Foundation
 
 func createBlurEffectView(style:UIBlurEffect.Style,backgroundColor:UIColor? = nil,alpha:CGFloat = 0.9) -> UIVisualEffectView {
     let blurEffect = UIBlurEffect(style: style)
@@ -20,3 +21,155 @@ func createBlurEffectView(style:UIBlurEffect.Style,backgroundColor:UIColor? = ni
     blurEffectView.alpha = alpha
     return blurEffectView
 }
+
+public let kMainQueue = DispatchQueue.main
+/// 主线程延迟执行回调
+/// - Parameters:
+///   - delay: 延迟时间(秒)
+///   - completion: 延迟后的回调
+public func kDelayOnMainThread(_ delay: TimeInterval, completion: @escaping () -> Void) {
+    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
+        completion()
+    }
+}
+
+public func kDelayMainShort(completion: @escaping () -> Void) {
+    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+        completion()
+    }
+}
+
+/// 在主线程上执行代码
+/// - Parameter block: 要执行的代码块
+public func kExecuteOnMainThread(_ block: @escaping () -> Void) {
+    if Thread.isMainThread {
+        block()
+    } else {
+        DispatchQueue.main.async {
+            block()
+        }
+    }
+}
+
+public func k_StatusBarH() -> CGFloat {
+    let scene = UIApplication.shared.connectedScenes.first;
+    guard let windowScene = scene as? UIWindowScene else {return 0};
+    guard let statusBarManager = windowScene.statusBarManager else {return 0};
+    return statusBarManager.statusBarFrame.height
+}
+
+public func k_Height_safeAreaInsetsBottom() -> CGFloat {
+    let scene = UIApplication.shared.connectedScenes.first;
+    guard let windowScene = scene as? UIWindowScene else {return 0};
+    guard let window = windowScene.windows.first else {return 0};
+    return window.safeAreaInsets.bottom;
+}
+/** 屏幕宽度 */
+public let k_ScreenWidth = UIScreen.main.bounds.size.width
+/** 屏幕高度 */
+public let k_ScreenHeight = UIScreen.main.bounds.size.height
+/* 导航栏高度 固定高度 = 44.0f */
+public let k_Height_NavBar :CGFloat = 44.0
+/** 状态栏高度 */
+public let k_StatusBar_H : CGFloat = k_StatusBarH()
+/** 状态栏+导航栏的高度 */
+public let k_Nav_Height: CGFloat = k_Height_NavBar + k_StatusBar_H
+/** 底部tabBar栏高度(不包含安全区,即:在 iphoneX 之前的手机) */
+public let k_TabBar_Height :CGFloat = 49.0
+/** 底部导航栏高度(包括安全区),一般使用这个值 */
+public let k_Height_TabBar :CGFloat = k_Height_safeAreaInsetsBottom() + k_TabBar_Height
+
+
+//判断是否是 x、及x以上 系列
+public func isIphoneX() -> Bool {
+    return k_Height_safeAreaInsetsBottom() > 0.0; // 底部安全区 > 0 时,
+    
+}
+
+//设计稿为 375*812 比例,所以比例系数为 375.0/kScreenWidth
+public let kDesignScale = k_ScreenWidth/375.0
+
+
+public func kGetUIH(designSize:CGSize,currentW:CGFloat) -> CGFloat {
+    let scale = designSize.width/currentW
+    return designSize.height/scale
+}
+    
+
+public func dePrint<T>(_ messsage: T) {
+    #if DEBUG
+    print(Date.hmsString + " \(messsage)")
+    #endif
+}
+
+public func appShortVersion() ->String{
+    let short = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
+    return short
+}
+
+public func appVersion() ->String{
+    return "V" + appShortVersion()
+}
+
+public func kPresentModalVC(target:UIViewController,
+                     modelVC:UIViewController,
+                       style:UIModalPresentationStyle = .overFullScreen,
+             transitionStyle:UIModalTransitionStyle = .coverVertical,
+                  completion: (() -> Void)? = nil){
+    let navi = AINavigationC(rootViewController: modelVC)
+    navi.modalPresentationStyle = style
+    navi.modalTransitionStyle = transitionStyle
+    target.present(navi, animated: true,completion: completion)
+}
+
+public func kPushVC(target:UIViewController,modelVC:UIViewController){
+    modelVC.hidesBottomBarWhenPushed = true
+    target.navigationController?.pushViewController(modelVC, animated: true)
+}
+
+public func kShowToastDataMissing(){
+    dePrint("参数缺失")
+}
+
+
+public extension Date {
+    static var timestampInt: Int {
+        return Int(Date().timeIntervalSince1970)
+    }
+    
+    static var hmsString: String {
+        let formatter = DateFormatter()
+        formatter.locale = Locale(identifier: "en")
+        formatter.dateFormat = "HH:mm:ss:SSS"
+        return formatter.string(from: Date())
+    }
+}
+
+
+public extension UIImage {
+    // 压缩图片到指定尺寸
+    func compressSize(to size: CGSize) -> UIImage {
+        let targetSize = size
+        if self.size.width > targetSize.width || self.size.height > targetSize.height {
+            return kf.resize(to: targetSize)
+        }
+        return self
+    }
+    
+    var pngImage:UIImage?{
+        guard let pngData = self.pngData() else {
+            print("Failed to convert WebP image to PNG data.")
+            return nil
+        }
+        return UIImage(data: pngData)
+    }
+}
+
+public extension Array {
+    func safeAny(At index: Int) -> Element? {
+        if index >= 0,  index < count {
+            return self[index]
+        }
+        return nil
+    }
+}

+ 3 - 3
AICalendarWallpaper/Common/CpuMapManager.swift

@@ -299,8 +299,8 @@ extension UIDevice {
         }
         
         for idx in 0..<count {
-            if let sv = Int(sysValues.safeObj(At: idx) ?? "0"),
-                let v = Int(values.safeObj(At: idx) ?? "0") {
+            if let sv = Int(sysValues.safeAny(At: idx) ?? "0"),
+                let v = Int(values.safeAny(At: idx) ?? "0") {
                 if sv > v {
                     return true
                 } else if sv < v {
@@ -344,7 +344,7 @@ extension UIDevice {
         if identifier.hasPrefix("iPhone") {
             let digital = identifier.replacingOccurrences(of: "iPhone", with: "")
             let arr = digital.components(separatedBy: ",")
-            if let v1 = arr.safeObj(At: 0),
+            if let v1 = arr.safeAny(At: 0),
                let vv1 = Double(v1) {
                 if vv1 >= 15 {
                     return .island

+ 7 - 0
AICalendarWallpaper/Common/Ex/Array+Ex.swift

@@ -0,0 +1,7 @@
+//
+//  Array+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+

+ 76 - 0
AICalendarWallpaper/Common/Ex/String+Ex.swift

@@ -0,0 +1,76 @@
+//
+//  String+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+public extension String {
+    
+    var uiColor: UIColor {
+        if isEmpty {
+            return .clear
+        }
+        return UIColor.fromHex(self)
+    }
+    
+    var uiCGColor: CGColor {
+        uiColor.cgColor
+    }
+}
+
+public extension String {
+
+    var localized:String {
+        return self
+    }
+        
+}
+
+
+public extension String {
+    
+    var isCachesPath:Bool{
+        return self.contains("/Caches/")
+    }
+    
+    var fillCachePath:String{
+        return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent(self).path
+    }
+    
+    var fillCacheURL:URL{
+        return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent(self)
+    }
+    
+    var cachesLastURLString:String{
+        let parts = self.components(separatedBy: "/Caches/")
+        if let last = parts.last {
+            return last
+        }
+        return self
+    }
+}
+
+public extension String {
+    
+    var isDocumentPath:Bool{
+        return self.contains("/Documents/")
+    }
+    
+    var fillDocumentPath:String{
+        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(self).path
+    }
+    
+    var fillDocumentURL:URL{
+        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent(self)
+    }
+    
+    var documentLastURLString:String{
+        let parts = self.components(separatedBy: "/Documents/")
+        if let last = parts.last {
+            return last
+        }
+        return self
+    }
+}

+ 111 - 0
AICalendarWallpaper/Common/Ex/UIButton+Ex.swift

@@ -0,0 +1,111 @@
+//
+//  Untitled.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+
+public extension UIButton {
+    static func createBtn(title: String? = nil,
+                             image: UIImage? = nil,
+                             backgroundImage: UIImage? = nil,
+                             backgroundColor: UIColor? = nil,
+                             font: UIFont? = nil,
+                             titleColor: UIColor? = nil,
+                             corner:CGFloat = 0,
+                             action: (() -> Void)? = nil) -> UIButton {
+        let button = UIButton(type: .custom)
+        button.setUpBtn(title: title,
+                           image: image,
+                           backgroundImage: backgroundImage,
+                           backgroundColor: backgroundColor,
+                           font: font,
+                           titleColor: titleColor,
+                           corner:corner,
+                           action: action)
+        return button
+    }
+
+    func setUpBtn(title: String? = nil,
+                             image: UIImage? = nil,
+                             backgroundImage: UIImage? = nil,
+                             backgroundColor: UIColor? = nil,
+                             font: UIFont? = nil,
+                             titleColor: UIColor? = nil,
+                             corner:CGFloat = 0,
+                             action: (() -> Void)? = nil){
+
+        if let image = image {
+            setImage(image, for: .normal)
+        }
+        if let title = title {
+            setTitle(title, for: .normal)
+        }
+        
+        if corner > 0 {
+            cornerRadius = corner
+        }
+   
+        if let backgroundImage = backgroundImage {
+            setBackgroundImage(backgroundImage, for: .normal)
+        }
+        if let font = font {
+            titleLabel?.font = font
+        }
+
+        showsTouchWhenHighlighted = false
+        adjustsImageWhenHighlighted = false
+
+        if let titleColor = titleColor {
+            setTitleColor(titleColor, for: .normal)
+        }
+        if let backgroundColor = backgroundColor {
+            self.backgroundColor = backgroundColor
+        }
+    
+        if let action = action {
+            actionClosure = action
+            addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
+        }
+
+    }
+
+    // 按钮点击事件
+    @objc private func buttonTapped() {
+        actionClosure?()
+    }
+}
+public extension UIButton {
+    
+    private struct AssociatedKeys {
+        static var actionKey = "ASButtonActionKey"
+    }
+    
+    private var actionClosure: (() -> Void)? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.actionKey) as? (() -> Void)
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.actionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+}
+
+
+public extension UIButton {
+    
+    func preventMultipleTaps(delay: Double = 0.75) {
+        isEnabled = false
+        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
+            self.isEnabled = true
+        }
+    }
+    
+    public func setTitleImageSpace(spacing:CGFloat = 4){
+//        titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0) // 只调整 title 的 left
+        contentEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0) // 只调整 title 的 left
+        imageEdgeInsets = UIEdgeInsets(top: 0, left: -spacing, bottom: 0, right: 0) // 只调整 image 的 right
+    }
+}

+ 43 - 0
AICalendarWallpaper/Common/Ex/UIColor+Ex.swift

@@ -0,0 +1,43 @@
+//
+//  UIColor+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+public extension UIColor {
+    /// 返回一个随机颜色
+    static var random: UIColor {
+        return UIColor(
+            red: CGFloat.random(in: 0...1),
+            green: CGFloat.random(in: 0...1),
+            blue: CGFloat.random(in: 0...1),
+            alpha: 1.0
+        )
+    }
+    
+    static func fromHex(_ hex: String, alpha: CGFloat = 1.0) -> UIColor {
+        var cleanedHex = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
+        
+        // Remove leading "#" if present
+        if cleanedHex.hasPrefix("#") {
+            cleanedHex.removeFirst()
+        }
+        
+        // Ensure valid hex length
+        guard cleanedHex.count == 6 else {
+            return UIColor.clear // Return clear color for invalid input
+        }
+        
+        // Extract RGB components
+        var rgbValue: UInt64 = 0
+        Scanner(string: cleanedHex).scanHexInt64(&rgbValue)
+        
+        let red = CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0
+        let green = CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0
+        let blue = CGFloat(rgbValue & 0x0000FF) / 255.0
+        
+        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
+    }
+    
+}

+ 42 - 0
AICalendarWallpaper/Common/Ex/UIFont+Ex.swift

@@ -0,0 +1,42 @@
+//
+//  UIFont+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+public extension String {
+    static let PingFangSC   = "PingFangSC"
+    static let PoppinsBoldItalic   = "Poppins-BoldItalic"
+}
+
+public extension UIFont {
+    static func font(name: String = .PingFangSC, size: CGFloat, weight: UIFont.Weight = .regular) -> UIFont {
+        guard !name.isEmpty, UIFont(name: name, size: size) != nil else {
+           return systemFont(ofSize: size, weight: weight)
+       }
+       
+       var selectedFontName = name
+       
+       let availableFonts = UIFont.fontNames(forFamilyName: name)
+       let weightMapping: [UIFont.Weight: [String]] = [
+           .light: ["-light", "_light"],//细体 300
+           .medium: ["-medium", "_medium"],////中黑体 500
+           .bold: ["-bold", "_bold"],//// 粗体 700
+           .semibold: ["-semibold", "_semibold"],//半粗体 600
+           .heavy: ["-heavy", "_heavy"],//粗黑体 800
+           .black: ["-black", "_black"] // 黑体 900
+       ]
+       
+       if let suffixes = weightMapping[weight] {
+           for suffix in suffixes {
+               if let matchedFont = availableFonts.first(where: { $0.lowercased().hasSuffix(suffix) }) {
+                   selectedFontName = matchedFont
+                   break
+               }
+           }
+       }
+       
+       return UIFont(name: selectedFontName, size: size) ?? systemFont(ofSize: size, weight: weight)
+    }
+}

+ 91 - 0
AICalendarWallpaper/Common/Ex/UIImageView+Ex.swift

@@ -0,0 +1,91 @@
+//
+//  Untitled.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+
+import Kingfisher
+
+public extension UIImageView {
+ static func createImageView(
+        image:UIImage? = nil,
+        imageName: String? = nil,
+        contentMode: UIView.ContentMode = .scaleAspectFit,
+        backgroundColor: UIColor = .clear,
+        corner: CGFloat = 0.0)
+    -> UIImageView {
+        let imageView = UIImageView()
+                                    
+        if let image = image{
+            imageView.image = image
+        }
+
+        if let imageName = imageName ,imageName.count > 0 {
+            imageView.image = UIImage(named: imageName)
+        }
+        
+        imageView.contentMode = contentMode
+        imageView.backgroundColor = backgroundColor
+        imageView.cornerRadius = corner
+        return imageView
+    }
+
+    func setAsyncImage(urlString: String?,
+                     placeholder: UIImage? = nil,
+                     contentMode: UIView.ContentMode = .scaleAspectFit,
+                 adaptiveMode:Bool = false,
+                 backgroundColor: UIColor = .clear,
+                      showLoading: Bool = false,
+                        progressBlock: ((Float)->Void)? = nil,
+                      completion: ((UIImage?) -> Void)? = nil){
+        let imageView = self
+        imageView.contentMode = contentMode
+        imageView.backgroundColor = backgroundColor
+        imageView.image = placeholder
+        
+        guard let urlString = urlString else {
+            completion?(nil)
+            return
+        }
+      
+        if urlString.isEmpty{
+            completion?(nil)
+            return
+        }
+        
+        if urlString.contains("http") {
+            guard let url = URL(string: urlString) else {
+                completion?(nil)
+                return
+            }
+            kf.indicatorType = .none
+            imageView.kf.setImage(with: url,
+                 placeholder: placeholder,
+                     options: nil,
+                progressBlock: { receivedSize, totalSize in
+                let progress = receivedSize/totalSize
+                progressBlock?(Float(progress))
+            }){ result in
+                
+                if let image = try? result.get().image {
+                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
+                        completion?(image)
+                    }
+                }else{
+                    completion?(nil)
+                }
+            }
+            
+        }else if urlString.contains("/") {
+            imageView.image = UIImage(contentsOfFile: urlString.fillCachePath)
+            completion?(imageView.image)
+        }else {
+            if let image = UIImage(named: urlString) {
+                imageView.image = image
+                completion?(image)
+            }
+        }
+    }
+}

+ 68 - 0
AICalendarWallpaper/Common/Ex/UILabel+Ex.swift

@@ -0,0 +1,68 @@
+//
+//  UILabel+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+public extension UILabel {
+    static func createLabel(text: String? = nil,
+                            font: UIFont? = nil,
+                            textColor: UIColor? = nil,
+                            textAlignment: NSTextAlignment = .left,
+                            numberOfLines: Int = 0,
+                            backgroundColor: UIColor? = nil,
+                            adjustsFontSizeToFitWidth: Bool = false,
+                            cornerRadius: CGFloat = 0) -> UILabel {
+        let label = UILabel()
+        if let font = font {
+            label.font = font
+        }
+        if let textColor = textColor {
+            label.textColor = textColor
+        }
+        label.numberOfLines = numberOfLines
+        label.text = text
+        label.adjustsFontSizeToFitWidth = adjustsFontSizeToFitWidth
+        label.textAlignment = textAlignment
+        if cornerRadius > 0 {
+            label.layer.cornerRadius = cornerRadius
+            label.layer.masksToBounds = true
+        }
+        if let backgroundColor = backgroundColor {
+            label.backgroundColor = backgroundColor
+        }
+        return label
+    }
+}
+
+public extension UILabel {
+    func applyGradient(colors: [UIColor], locations: [NSNumber]? = nil, startPoint: CGPoint = CGPoint(x: 0.0, y: 0.5), endPoint: CGPoint = CGPoint(x: 1.0, y: 0.5)) {
+        // 创建一个 CAGradientLayer 实例,用于实现渐变色
+        let gradientLayer = CAGradientLayer()
+        // 设置渐变层的大小与 UILabel 的大小一致
+        gradientLayer.frame = bounds
+        // 将 UIColor 数组转换为 CGColor 数组
+        gradientLayer.colors = colors.map { $0.cgColor }
+        // 设置渐变颜色的位置,如果没有提供,则默认均匀分布
+        gradientLayer.locations = locations
+        // 设置渐变的起始点
+        gradientLayer.startPoint = startPoint
+        // 设置渐变的结束点
+        gradientLayer.endPoint = endPoint
+
+        // 创建一个新的图形上下文
+        UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)
+        if let context = UIGraphicsGetCurrentContext() {
+            // 将渐变层渲染到图形上下文中
+            gradientLayer.render(in: context)
+            // 从图形上下文中获取渐变图像
+            if let gradientImage = UIGraphicsGetImageFromCurrentImageContext() {
+                // 结束图形上下文
+                UIGraphicsEndImageContext()
+                // 设置 UILabel 的文本颜色为渐变图像
+                textColor = UIColor(patternImage: gradientImage)
+            }
+        }
+    }
+}

+ 49 - 0
AICalendarWallpaper/Common/Ex/UIStackView+Ex.swift

@@ -0,0 +1,49 @@
+//
+//  UIStackView+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+public extension UIStackView {
+
+    static func creatStackView()->UIStackView{
+        let stackView = UIStackView()
+        stackView.axis = .vertical
+        stackView.spacing = 0
+        stackView.alignment = .fill
+        stackView.distribution = .fill
+        return stackView
+    }
+    
+    func addSpacing(length:CGFloat) {
+        let view = UIView()
+        self.addArrangedSubview(view)
+        view.snp.makeConstraints { make in
+            if axis == .vertical {
+                make.width.equalToSuperview()
+                make.height.equalTo(length)
+            } else {
+                make.width.equalTo(length)
+                make.height.equalToSuperview()
+            }
+        }
+    }
+
+    func addArrangedView(_ view: UIView,length:CGFloat? = nil) {
+        addArrangedSubview(view)
+        view.snp.makeConstraints { make in
+            if axis == .vertical {
+                make.width.equalTo(self)
+                if let length = length {
+                    make.height.equalTo(length)
+                }
+            } else {
+                make.height.equalTo(self)
+                if let length = length {
+                    make.width.equalTo(length)
+                }
+            }
+        }
+    }
+}

+ 201 - 0
AICalendarWallpaper/Common/Ex/UIView+Ex.swift

@@ -0,0 +1,201 @@
+//
+//  UIView+Ex.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/2.
+//
+
+
+public extension UIView {
+
+    var borderColor: UIColor? {
+        set {
+            layer.borderColor = newValue?.cgColor
+        }
+        get {
+            if let cgColor = layer.borderColor {
+                return UIColor(cgColor: cgColor)
+            }
+            return nil
+        }
+    }
+    
+    
+    var x: CGFloat {
+        set {
+            frame.origin.x = newValue
+        }
+        get {
+            return frame.origin.x
+        }
+    }
+    
+    var y: CGFloat {
+        set {
+            frame.origin.y = newValue
+        }
+        get {
+            return frame.origin.y
+        }
+    }
+    
+    var width: CGFloat {
+        set {
+            frame.size.width = newValue
+        }
+        get {
+            return frame.size.width
+        }
+    }
+    
+    var height: CGFloat {
+        set {
+            frame.size.height = newValue
+        }
+        get {
+            return frame.size.height
+        }
+    }
+    
+    var size: CGSize {
+        get { frame.size }
+        set {
+            var rect = frame
+            rect.size = newValue
+            frame = rect
+        }
+    }
+    
+    var centerX: CGFloat {
+        set {
+            let newCenter = CGPoint(x: newValue, y: center.y)
+            center = newCenter
+        }
+        get {
+            return center.x
+        }
+    }
+    
+    var centerY: CGFloat {
+        set {
+            let newCenter = CGPoint(x: center.x, y: newValue)
+            center = newCenter
+        }
+        get {
+            return center.y
+        }
+    }
+    
+    var bottom: CGFloat {
+        get {
+            return frame.origin.y + frame.size.height
+        }
+    }
+    
+    var cornerRadius: CGFloat {
+        set {
+            clipsToBounds = true
+            layer.cornerRadius = newValue
+        }
+        get {
+            layer.cornerRadius
+        }
+    }
+
+    var borderWidth: CGFloat {
+        set {
+            layer.borderWidth = newValue
+        }
+        get {
+            layer.borderWidth
+        }
+    }
+    
+}
+
+public extension UIView {
+    func removeAllSubViews() {
+        subviews.forEach { subview in
+            subview.removeFromSuperview()
+        }
+    }
+
+    // 部分圆角(必须Frame已知)
+    func maskCorner(_ corners: UIRectCorner, radius: CGFloat) {
+        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
+        let maskLayer = CAShapeLayer()
+        maskLayer.frame = bounds
+        maskLayer.path = path.cgPath
+        layer.mask = maskLayer
+    }
+    
+    func addGradientBorder(
+        colors: [UIColor],
+        width: CGFloat = 2,
+        radius: CGFloat? = nil,
+        startPoint: CGPoint = CGPoint(x: 0, y: 0.5),
+        endPoint: CGPoint = CGPoint(x: 1, y: 0.5)
+    ) {
+        let gradientLayer = CAGradientLayer()
+        gradientLayer.name = "GradientBorder"
+        gradientLayer.endPoint = endPoint
+        gradientLayer.colors = colors.map { $0.cgColor }
+        gradientLayer.startPoint = startPoint
+        gradientLayer.frame = bounds
+        
+        let cornerRadius = radius ?? layer.cornerRadius
+        let path = UIBezierPath(
+            roundedRect: bounds.insetBy(dx: width/2, dy: width/2),
+            cornerRadius: cornerRadius
+        )
+        
+        let shapeLayer = CAShapeLayer()
+        shapeLayer.name = "GradientBorderMask"
+        shapeLayer.path = path.cgPath
+        shapeLayer.lineWidth = width
+        shapeLayer.fillColor = nil
+        shapeLayer.strokeColor = UIColor.black.cgColor
+        
+        gradientLayer.mask = shapeLayer
+        layer.addSublayer(gradientLayer)
+    }
+    
+    func addGradientBg(colors: [CGColor],
+                       startPoint: CGPoint = .zero,
+                       endPoint: CGPoint = CGPoint(x: 1, y: 1),
+                       layerSize: CGSize? = nil) {
+        let gl = CAGradientLayer()
+        gl.colors = colors
+        gl.zPosition = -1
+        gl.startPoint = startPoint
+        gl.endPoint = endPoint
+        gl.frame = CGRect(origin: .zero, size: layerSize ?? self.bounds.size)
+        layer.insertSublayer(gl, at: 0)
+    }
+    
+    func startRotating(duration: CFTimeInterval = 1.0,
+                     clockwise: Bool = true,
+                     repeatCount: Float = .greatestFiniteMagnitude) {
+
+        self.stopRotating()
+        
+        DispatchQueue.main.async {
+            let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
+            rotation.repeatCount = repeatCount
+            rotation.toValue = clockwise ? CGFloat.pi * 2.0 : -CGFloat.pi * 2.0
+            rotation.isCumulative = true
+            rotation.timingFunction = CAMediaTimingFunction(name: .linear)
+            rotation.fromValue = 0
+            rotation.duration = duration
+            rotation.fillMode = .forwards
+            rotation.isRemovedOnCompletion = false
+            self.layer.add(rotation, forKey: "rotation")
+        }
+    }
+    
+    func stopRotating() {
+        DispatchQueue.main.async {
+            self.layer.removeAnimation(forKey: "rotation")
+        }
+    }
+}

+ 62 - 0
AICalendarWallpaper/Common/PhotoManager.swift

@@ -0,0 +1,62 @@
+//
+//  PhotoManager.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+import Photos
+class AIImageSaver {
+    
+    /// 存储图片到相册
+    /// - Parameters:
+    ///   - targetImage: 需要保存的图片
+    ///   - resultHandler: 保存完成后的回调,返回是否成功和可能的错误
+    static func storePicture(_ targetImage: UIImage, resultHandler: @escaping (Bool, Error?) -> Void) {
+        // 请求相册权限
+        PHPhotoLibrary.requestAuthorization { authStatus in
+            DispatchQueue.main.async {
+                switch authStatus {
+                case .authorized, .limited:
+                    // 有权限或受限权限,尝试保存
+                    self.executeSaveOperation(image: targetImage, completion: resultHandler)
+                case .denied, .restricted:
+                    // 无权限或受限
+                    let accessError = NSError(
+                        domain: "AIImageStorage",
+                        code: 403,
+                        userInfo: [NSLocalizedDescriptionKey: "Access to photo library was denied."]
+                    )
+                    resultHandler(false, accessError)
+                case .notDetermined:
+                    // 理论上不会执行到这里
+                    let undeterminedError = NSError(
+                        domain: "AIImageStorage",
+                        code: 401,
+                        userInfo: [NSLocalizedDescriptionKey: "Authorization status not determined."]
+                    )
+                    resultHandler(false, undeterminedError)
+                @unknown default:
+                    let unknownError = NSError(
+                        domain: "AIImageStorage",
+                        code: 500,
+                        userInfo: [NSLocalizedDescriptionKey: "Unknown authorization status."]
+                    )
+                    resultHandler(false, unknownError)
+                }
+            }
+        }
+    }
+
+    /// 实际执行图片保存操作
+    private static func executeSaveOperation(image: UIImage, completion: @escaping (Bool, Error?) -> Void) {
+        PHPhotoLibrary.shared().performChanges({
+            let creationRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
+            creationRequest.creationDate = Date()
+        }) { didSucceed, possibleError in
+            DispatchQueue.main.async {
+                completion(didSucceed, possibleError)
+            }
+        }
+    }
+}

+ 23 - 103
AICalendarWallpaper/Common/TSNetWork/TSNetWork+Business.swift

@@ -64,11 +64,16 @@ extension TSNetworkManager {
         urlType: TSNeURLType,
         parameters: [String: Any]? = nil,
         responseType: T.Type? = nil,
-        completion: @escaping (Result<Any, Error>) -> Void
+        completion: @escaping (Any?, Error?) -> Void
     ) -> Request  {
         let urlString = urlType.getUrlString()
         return request(method: .get, urlString: urlString, parameters:parameters) { result in
-            completion(result)
+            switch result {
+            case .success(let data):
+                completion(data,nil)
+            case .failure(let error):
+                completion(nil,error)
+            }
         }
     }
 
@@ -83,31 +88,18 @@ extension TSNetworkManager {
         urlType: TSNeURLType,
         parameters: [String: Any]? = nil,
         responseType: T.Type? = nil,
-        completion: @escaping (Result<Any, Error>) -> Void
+        completion: @escaping (Any?, Error?) -> Void
     ) -> Request {
         let urlString = urlType.getUrlString()
         return request(method: .post, urlString: urlString, parameters:parameters) { result in
-            completion(result)
+            switch result {
+            case .success(let data):
+                completion(data,nil)
+            case .failure(let error):
+                completion(nil,error)
+            }
         }
     }
-    
-    /// 通用 POST Stream 请求
-    /// - Parameters:
-    ///   - endpoint: 接口路径
-    ///   - parameters: 请求参数
-    ///   - responseType: 响应数据模型(可选)
-    ///   - completion: 请求完成的回调
-    func postStream<T: TSBaseModel>(
-        urlType: TSNeURLType,
-        parameters: [String: Any]? = nil,
-        responseType: T.Type? = nil,
-        streamHandler:@escaping (String) -> Void,
-        completion: @escaping (Result<Any, Error>) -> Void
-    ) -> Request?{
-        let urlString = urlType.getUrlString()
-        let streamRequest = postStreamRequest(urlString: urlString, parameters: parameters, streamHandler: streamHandler, completion: completion)
-        return streamRequest
-    }
 
     
     /// 上传多个 Data 数据
@@ -123,12 +115,19 @@ extension TSNetworkManager {
         parameters: [String: Any]? = nil,
         responseType: T.Type? = nil,
         progressHandler: @escaping (Float) -> Void, // 上传进度回调
-        completion: @escaping (Result<Any, Error>) -> Void
+        completion: @escaping (Any?, Error?) -> Void
     ) -> Request?{
         let urlString = urlType.getUrlString()
         let request = uploadData(urlString: urlString,dataArray:dataArray, parameters: parameters, progressHandler: { progress in
             progressHandler(Float(progress.fractionCompleted))
-        },completion: completion)
+        }) { result in
+            switch result {
+            case .success(let data):
+                completion(data,nil)
+            case .failure(let error):
+                completion(nil,error)
+            }
+        }
         return request
     }
     
@@ -160,82 +159,3 @@ extension TSNetworkManager {
     }
 
 }
-
-extension TSNetworkManager {
-    
-//    func uploadAudio(
-//        fileURL:URL,
-//        progressHandler: @escaping (Float) -> Void, // 上传进度回调
-//        completion: @escaping (Any?, Error?) -> Void)
-//    -> Request?{
-//
-//        let urlString = TSNeURLType.upload.getUrlString()
-//        
-//        let request = uploadFile(urlString: urlString, fileURL: fileURL, multipartBuilder: { multipart in
-//            multipart.append(fileURL, withName: "file", fileName: "audio.mp3", mimeType: "audio/mp3")
-//        }) { progress in
-//            progressHandler(Float(progress.fractionCompleted))
-//        } completion: { [weak self] result in
-//            guard let self = self else { return }
-//            switch result {
-//            case .success(let data):
-//                if let dataDict = kNetWorkCodeSuccess(data: data),
-//                   let picUrl = dataDict["result"] as? String{
-//                    completion(picUrl,nil)
-//                }else{
-//                    let error = NSError(domain: "Service exception", code: 0)
-//                    completion(nil,error)
-//                }
-//            case .failure(let error):
-//                completion(nil,error)
-//            }
-//        }
-//        
-//        return request
-//    }
-    
-    
-//    func uploadAudio(
-//        fileURL:URL,
-//        progressHandler: @escaping (Float) -> Void, // 上传进度回调
-//        completion: @escaping (Any?, Error?) -> Void)
-//    -> Request?{
-//
-//        let urlString = TSNeURLType.upload.getUrlString()
-//        
-//        
-//        dePrint("✈️✈️✈️网络请求:\(urlString)")
-//        guard let url = URL(string: urlString) else {
-//            completion(nil,NSError(domain: "url nil", code: 0))
-//            return nil
-//        }
-//        return AF.upload(
-//            multipartFormData: { multipart in
-//                multipart.append(fileURL, withName: "file", fileName: "audio.mp3", mimeType: "audio/mp3")
-//            },
-//            to: url
-//        )
-//        .uploadProgress { progress in
-//            dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
-//            progressHandler(Float(progress.fractionCompleted))
-//        }
-//        .responseString { response in
-//            self.handleResponse(response) { [weak self] result in
-//                guard let self = self else { return }
-//                switch result {
-//                case .success(let data):
-//                    if let dataDict = kNetWorkCodeSuccess(data: data),
-//                       let picUrl = dataDict["result"] as? String{
-//                        completion(picUrl,nil)
-//                    }else{
-//                        let error = NSError(domain: "Service exception", code: 0)
-//                        completion(nil,error)
-//                    }
-//                case .failure(let error):
-//                    completion(nil,error)
-//                }
-//            }
-//        }
-//    }
-}
-

+ 0 - 86
AICalendarWallpaper/Common/TSNetWork/TSNetworkManager+Loading.swift

@@ -1,86 +0,0 @@
-//
-//  TSNetworkManager+Loading.swift
-//  AIEmoji
-//
-//  Created by 100Years on 2025/1/16.
-//
-import Alamofire
-extension TSNetworkManager {
-    
-    /// 通用 get 请求
-    func get<T: TSBaseModel>(
-        urlType: TSNeURLType,
-        parameters: [String: Any]? = nil,
-        responseType: T.Type? = nil,
-        animationView:UIView? = nil,
-        completion: @escaping (Any?, Error?) -> Void
-    ) -> Request {
-        
-        var isShowAnimation = false
-        if animationView != nil {
-            isShowAnimation = true
-        }
-        
-        if isShowAnimation,let view = animationView {
-            TSToastShared.showLoading(containerView: view)
-        }
-
-        return get(urlType: urlType, parameters:parameters,responseType:responseType) { result in
-            
-            if isShowAnimation {
-                TSToastShared.hideLoading()
-            }
-    
-            switch result {
-            case .success(let data):
-//                print("Response data: \(data)")
-                completion(data,nil)
-            case .failure(let error):
-//                print("Error: \(error)")
-                completion(nil,error)
-            }
-        }
-    }
-
-
-    /// 通用 POST 请求
-    /// - Parameters:
-    ///   - endpoint: 接口路径
-    ///   - parameters: 请求参数
-    ///   - responseType: 响应数据模型(可选)
-    ///   - completion: 请求完成的回调
-    func post<T: TSBaseModel>(
-        urlType: TSNeURLType,
-        parameters: [String: Any]? = nil,
-        responseType: T.Type? = nil,
-        animationView:UIView? = nil,
-        completion: @escaping (Any?, Error?) -> Void
-    ) -> Request {
-        var isShowAnimation = false
-        if animationView != nil {
-            isShowAnimation = true
-        }
-        
-        if isShowAnimation,let view = animationView {
-            TSToastShared.showLoading(containerView: view)
-        }
-
-        return post(urlType: urlType, parameters:parameters,responseType:responseType){ result in
-            
-            if isShowAnimation {
-                TSToastShared.hideLoading()
-            }
-    
-            switch result {
-            case .success(let data):
-//                print("Response data: \(data)")
-                completion(data,nil)
-            case .failure(let error):
-//                print("Error: \(error)")
-                completion(nil,error)
-            }
-        }
-    
-    }
-    
-}

+ 10 - 12
AICalendarWallpaper/Common/TSNetWork/TSNetworkManager.swift

@@ -374,17 +374,14 @@ extension TSNetworkManager {
 
 
 
+
 func kNetWorkCodeSuccess(data:Any?) -> [String:Any]? {
     guard let data = data else { return nil }
-    if let dataDict = data as? [String:Any]{
-        let code = dataDict.safeInt(forKey: "code")
-        
+    if let dataDict = data as? [String:Any],
+        let code = dataDict["code"] as? Int{
         switch code {
-        case 200://成功
+        case 200://成功®
             return dataDict
-//        case 400://机器人提示
-//            TSAbnormalPopUpAlertVC.showRobotWarning()
-//            return nil
         default:
             return nil
         }
@@ -395,8 +392,8 @@ func kNetWorkCodeSuccess(data:Any?) -> [String:Any]? {
 
 
 func kNetWorkResultSuccess(data:Any?) -> [String:Any]? {
-    guard let dataDict = kNetWorkCodeSuccess(data: data) else { return nil }
-    if let result = dataDict["result"] as? [String:Any]{
+    guard let dict = kNetWorkCodeSuccess(data: data) else { return nil }
+    if let result = dict["result"] as? [String:Any]{
         return result
     }
     return nil
@@ -404,14 +401,15 @@ func kNetWorkResultSuccess(data:Any?) -> [String:Any]? {
 
 func kNetWorkMessage(data:Any?) -> String? {
     guard let data = data else { return nil }
-    if let dataDict = data as? [String:Any] ,
-       let message = dataDict["message"] as? String{
-        return message
+    if let dict = data as? [String:Any] ,
+       let msg = dict["message"] as? String{
+        return msg
     }
     return nil
 }
 
   
+  
 
 class JsonStringTransform<T:Mappable>: TransformType {
     typealias Object = T

+ 146 - 0
AICalendarWallpaper/Common/TSPlaceholderTextView.swift

@@ -0,0 +1,146 @@
+//
+//  TSPlaceholderTextView.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+open class TSPlaceholderTextView: UITextView {
+    
+    // Placeholder Label
+    public lazy var placeholderLabel: TopLeftLabel = {
+        let placeholderLabel = TopLeftLabel()
+        placeholderLabel.font = font
+        placeholderLabel.textColor = placeholderColor
+        placeholderLabel.text = placeholder
+        placeholderLabel.numberOfLines = 0
+        placeholderLabel.isUserInteractionEnabled = false
+        placeholderLabel.textAlignment = .left
+        return placeholderLabel
+    }()
+    
+    public var maxLength:Int = 1000 {
+        didSet {
+            handleTextViewTextCount(textView: self)
+        }
+    }
+    // Placeholder Text
+    public  var placeholder: String? {
+        didSet {
+            placeholderLabel.text = placeholder
+        }
+    }
+    
+    // Placeholder Color
+    public var placeholderColor: UIColor = .lightGray {
+        didSet {
+            placeholderLabel.textColor = placeholderColor
+        }
+    }
+    
+    // Placeholder Insets
+    public var textInsets: UIEdgeInsets = .zero {
+        didSet {
+            updateTextContainerInset()
+        }
+    }
+    
+    // Override text property to manage placeholder visibility
+    open override var text: String! {
+        didSet {
+            updatePlaceholderVisibility()
+        }
+    }
+    
+    public var textViewTextChanged:(()->Void)?
+    
+    // Initializer
+    public init(placeholder: String? = nil,
+         text: String? = nil,
+         font: UIFont? = nil,
+         textColor: UIColor = .black,
+         backgroundColor: UIColor = .white,
+         textInsets: UIEdgeInsets = .zero) {
+        super.init(frame: .zero, textContainer: nil)
+        
+        self.placeholder = placeholder
+        self.font = font
+        self.textColor = textColor
+        self.backgroundColor = backgroundColor
+        self.textInsets = textInsets
+        
+        setupPlaceholder()
+        self.text = text
+    }
+    
+    required public init?(coder: NSCoder) {
+        super.init(coder: coder)
+        setupPlaceholder()
+    }
+    
+    // Setup placeholder label
+    private func setupPlaceholder() {
+ 
+        addSubview(placeholderLabel)
+        updatePlaceholderVisibility()
+        
+        // Observe text changes to update placeholder
+        NotificationCenter.default.addObserver(self,
+                                               selector: #selector(textDidChange(_:)),
+                                               name: UITextView.textDidChangeNotification,
+                                               object: self)
+        
+        // Update text container insets
+        updateTextContainerInset()
+    }
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+    
+    // Update placeholder visibility
+    private func updatePlaceholderVisibility() {
+        placeholderLabel.isHidden = !text.isEmpty
+    }
+    
+    
+    @objc private func textDidChange(_ notification: Notification) {
+        if let textView = notification.object as? UITextView {
+            handleTextViewTextCount(textView: textView)
+            textViewTextChanged?()
+        }
+        updatePlaceholderVisibility()
+    }
+    
+    open func handleTextViewTextCount(textView:UITextView) {
+        if textView.text.count > maxLength {
+            textView.text = String(textView.text.prefix(maxLength))
+        }
+    }
+    
+    // Update textContainerInset and placeholder frame
+    private func updateTextContainerInset() {
+        textContainerInset = textInsets
+        setNeedsLayout()
+    }
+
+    
+    // Layout placeholder
+    open override func layoutSubviews() {
+        super.layoutSubviews()
+
+        let placeholderX = textInsets.left + 5 // Add padding for placeholder
+        let placeholderY = textInsets.top
+        let placeholderWidth = bounds.width - textInsets.left - textInsets.right - 10 // Adjust for padding
+        let placeholderHeight = bounds.height - textInsets.top - textInsets.bottom
+        
+        placeholderLabel.frame = CGRect(x: placeholderX,
+                                        y: placeholderY,
+                                        width: placeholderWidth,
+                                        height: placeholderHeight)
+    }
+
+}
+
+

+ 27 - 0
AICalendarWallpaper/Common/TSRandomTextTool.swift

@@ -0,0 +1,27 @@
+//
+//  TSRandomTextTool.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+public class TSRandomTextTool {
+    private var texts: [String]
+    private var lastIndex: Int?
+
+    public init(texts: [String]) {
+        self.texts = texts
+    }
+    
+    public func getRandomText() -> String? {
+        guard !texts.isEmpty else { return nil }
+        
+        var randomIndex: Int
+        repeat {
+            randomIndex = Int.random(in: 0..<texts.count)
+        } while randomIndex == lastIndex
+        
+        lastIndex = randomIndex
+        return texts[randomIndex]
+    }
+}

+ 132 - 0
AICalendarWallpaper/Common/View/AISaveNotifyManager.swift

@@ -0,0 +1,132 @@
+//
+//  AISaveNotifyManager.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+public let kAISaveNotifyShared = AISaveNotifyManager.globalInstance
+
+open class AISaveNotifyManager {
+    
+    static let globalInstance = AISaveNotifyManager()
+    
+    public var onViewAction: (() -> Void)?
+    
+    private lazy var messageLabel: UILabel = {
+        let label = UILabel()
+        label.textColor = .white
+        label.text = "Save Successfully".localized
+        label.font = .systemFont(ofSize: 14)
+        return label
+    }()
+    
+    private lazy var notificationPanel: UIView = {
+        return generateNotificationUI()
+    }()
+    
+    private lazy var actionButton: UIView = {
+        let tint = "4FEA9D".uiColor
+        let btn = UIButton.createBtn(
+            title: "View".localized,
+            backgroundColor: tint.withAlphaComponent(0.1),
+            font: .systemFont(ofSize: 12),
+            titleColor: tint,
+            corner: 14
+        ) { [weak self] in
+            self?.handleButtonAction()
+        }
+        btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
+        return btn
+    }()
+    
+    private func handleButtonAction() {
+        if let action = onViewAction {
+            action()
+        } else {
+            if let url = URL(string: "photos-redirect://"),
+               UIApplication.shared.canOpenURL(url) {
+                UIApplication.shared.open(url)
+            }
+        }
+        DispatchQueue.main.async {
+            self.notificationPanel.removeFromSuperview()
+        }
+    }
+    
+    private func generateNotificationUI() -> UIView {
+        let container = UIView(frame: CGRect(x: 0, y: 0, width: 288, height: 48))
+        container.backgroundColor = .clear
+        container.layer.shadowColor = UIColor.black.cgColor
+        container.layer.shadowOffset = CGSize(width: 0, height: 2)
+        container.layer.shadowOpacity = 0.1
+        
+        let background = UIView()
+        background.backgroundColor = "333333".uiColor
+        background.layer.cornerRadius = 8
+        background.clipsToBounds = true
+        
+        container.addSubview(background)
+        background.snp.makeConstraints { $0.edges.equalToSuperview() }
+        
+        let icon = UIImageView(image: UIImage(named: "success_icon"))
+        container.addSubview(icon)
+        icon.snp.makeConstraints {
+            $0.size.equalTo(24)
+            $0.centerY.equalToSuperview()
+            $0.leading.equalTo(12)
+        }
+        
+        container.addSubview(actionButton)
+        container.addSubview(messageLabel)
+        
+        actionButton.snp.makeConstraints {
+            $0.width.equalTo(actionButton.intrinsicContentSize.width)
+            $0.height.equalTo(28)
+            $0.trailing.equalTo(-8)
+            $0.centerY.equalToSuperview()
+        }
+        
+        messageLabel.snp.makeConstraints {
+            $0.leading.equalTo(icon.snp.trailing).offset(8)
+            $0.trailing.equalTo(actionButton.snp.leading).offset(-8)
+            $0.centerY.equalToSuperview()
+        }
+        
+        return container
+    }
+    
+    public func calculateBottomOffset(from topPosition: CGFloat) -> CGFloat {
+        let offset = -(UIScreen.main.bounds.height - 48 - topPosition)
+        debugPrint("Calculated offset: \(offset)")
+        return offset
+    }
+    
+    public func displayNotification(
+        in view: UIView,
+        message: String = "Save Successfully".localized,
+        duration: Double = 2.0,
+        bottomOffset: CGFloat = -112,
+        showActionButton: Bool = true,
+        viewAction: (() -> Void)? = nil
+    ) {
+        self.onViewAction = viewAction
+        DispatchQueue.main.async {
+            self.messageLabel.text = message
+            self.actionButton.isHidden = !showActionButton
+            view.addSubview(self.notificationPanel)
+            
+            self.notificationPanel.snp.remakeConstraints {
+                $0.width.greaterThanOrEqualTo(288)
+                $0.width.lessThanOrEqualTo(UIScreen.main.bounds.width - 32)
+                $0.height.equalTo(48)
+                $0.centerX.equalToSuperview()
+                $0.bottom.equalTo(bottomOffset)
+            }
+        }
+        
+        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
+            self.notificationPanel.removeFromSuperview()
+        }
+    }
+}

+ 18 - 0
AICalendarWallpaper/Common/View/TSUIExpandedTouchButton.swift

@@ -0,0 +1,18 @@
+//
+//  Untitled.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+public class TSUIExpandedTouchButton: UIButton {
+    public var indexPath: IndexPath = IndexPath(item: 0, section: 0)
+    
+    override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        let buttonBounds = self.bounds
+        let widthDelta = self.width * 0.5 // 增加点击区域的比例,这里增加了50%
+        let heightDelta = self.height * 0.5
+        let expandedBounds = buttonBounds.insetBy(dx: -widthDelta, dy: -heightDelta)
+        return expandedBounds.contains(point)
+    }
+}

+ 67 - 0
AICalendarWallpaper/Common/View/TopLeftLabel.swift

@@ -0,0 +1,67 @@
+//
+//  TopLeftLabel.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+import UIKit
+open class TopLeftLabel: UILabel {
+    
+    // 设置内间距
+    var textInsets: UIEdgeInsets = .zero {
+        didSet {
+            setNeedsDisplay()
+        }
+    }
+    
+    open override func drawText(in rect: CGRect) {
+        // 根据内间距调整绘制区域
+        let insetRect = rect.inset(by: textInsets)
+        
+        // 获取文本实际大小
+        guard let text = text else { return }
+        let textSize = (text as NSString).boundingRect(
+            with: CGSize(width: insetRect.width, height: .greatestFiniteMagnitude),
+            options: [.usesLineFragmentOrigin, .usesFontLeading],
+            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
+            context: nil
+        ).size
+        
+        // 重新定义绘制区域,使文本始终靠左上角
+        var adjustedRect = insetRect
+        adjustedRect.size.height = min(textSize.height, insetRect.height)
+        
+        // 调用父类的绘制方法
+        super.drawText(in: adjustedRect)
+    }
+    
+    open override var intrinsicContentSize: CGSize {
+        // 根据内容大小和内间距调整固有内容大小
+        guard let text = text else { return .zero }
+        let textSize = (text as NSString).boundingRect(
+            with: CGSize(width: bounds.width - textInsets.left - textInsets.right, height: .greatestFiniteMagnitude),
+            options: [.usesLineFragmentOrigin, .usesFontLeading],
+            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
+            context: nil
+        ).size
+        let width = textSize.width + textInsets.left + textInsets.right
+        let height = textSize.height + textInsets.top + textInsets.bottom
+        return CGSize(width: width, height: height)
+    }
+    
+    open override func sizeThatFits(_ size: CGSize) -> CGSize {
+        // 调整 `sizeThatFits` 的结果以包含内间距
+        guard let text = text else { return .zero }
+        let textSize = (text as NSString).boundingRect(
+            with: CGSize(width: size.width - textInsets.left - textInsets.right, height: .greatestFiniteMagnitude),
+            options: [.usesLineFragmentOrigin, .usesFontLeading],
+            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
+            context: nil
+        ).size
+        let width = textSize.width + textInsets.left + textInsets.right
+        let height = textSize.height + textInsets.top + textInsets.bottom
+        return CGSize(width: width, height: height)
+    }
+}

+ 90 - 0
AICalendarWallpaper/Common/WindowHelper.swift

@@ -0,0 +1,90 @@
+//
+//  WindowHelper.swift
+//  AICalendarWallpaper
+//
+//  Created by 100Years on 2025/6/3.
+//
+
+
+import UIKit
+
+class WindowHelper {
+    
+    /// 获取当前的 keyWindow
+    static func getKeyWindow() -> UIWindow? {
+        // 在 iOS 13 及以上,SceneDelegate 管理窗口
+        if #available(iOS 13.0, *) {
+            return UIApplication.shared.connectedScenes
+                .compactMap { $0 as? UIWindowScene }
+                .flatMap { $0.windows }
+                .first { $0.isKeyWindow }
+        } else {
+            // iOS 13 以下直接获取 keyWindow
+            return UIApplication.shared.keyWindow
+        }
+    }
+    
+    /// 获取当前窗口,兼容 iOS 13 及以上版本
+    static func getCurrentWindow() -> UIWindow? {
+        if #available(iOS 13.0, *) {
+            // iOS 13 及以上使用 `scene` 获取当前 window
+            guard let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene else {
+                return nil
+            }
+            return scene.windows.first { $0.isKeyWindow }
+        } else {
+            // iOS 12 及以下直接从 keyWindow 获取
+            return UIApplication.shared.keyWindow
+        }
+    }
+    
+    /// 获取当前根视图控制器
+    static func getRootViewController() -> UIViewController? {
+        guard let window = getCurrentWindow() else {
+            return nil
+        }
+        return window.rootViewController
+    }
+    
+    /// 获取当前的视图控制器
+    static func getCurrentViewController() -> UIViewController? {
+        var currentViewController = getRootViewController()
+        
+        while let presentedViewController = currentViewController?.presentedViewController {
+            currentViewController = presentedViewController
+        }
+        debugPrint("getCurrentViewController VC 是: \(currentViewController)")
+        return currentViewController
+    }
+    
+    
+    static func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
+        if let nav = base as? UINavigationController {
+            return topViewController(base: nav.visibleViewController)
+        } else if let tab = base as? UITabBarController {
+            return topViewController(base: tab.selectedViewController)
+        } else if let presented = base?.presentedViewController {
+            return topViewController(base: presented)
+        }
+        debugPrint("当前顶层 VC 是: \(String(describing: base))")
+        return base
+    }
+    
+    static func resetToTabBarController(at index: Int) {
+        guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }),
+              let tabBarController = window.rootViewController as? UITabBarController else {
+            return
+        }
+
+        // 关闭所有模态视图
+        window.rootViewController?.dismiss(animated: false) {
+            // 获取当前选中的 navigationController
+            if let nav = tabBarController.selectedViewController as? UINavigationController {
+                nav.popToRootViewController(animated: false)
+            }
+
+            // 切换到目标 tab
+            tabBarController.selectedIndex = index
+        }
+    }
+}

+ 0 - 28
Podfile

@@ -1,41 +1,13 @@
-#source 'https://github.com/CocoaPods/Specs.git'
-
 project 'AICalendarWallpaper.xcodeproj'
 platform :ios, '14.0'
 
 inhibit_all_warnings!
 
-
 target 'AICalendarWallpaper' do
   use_frameworks!
   pod 'ObjectMapper'
   pod 'SnapKit'
   pod 'Kingfisher', '7.10.0'
   pod 'Alamofire'
-  pod 'TSSmalCoacopods', :path => '../TSSmalCoacopods'
   pod 'RealmSwift', '~>10'
 end
-
-
-post_install do |installer|
-  installer.pods_project.targets.each do |target|
-    target.build_configurations.each do |config|
-      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.0'
-#      config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
-    end
-  end
-  installer.aggregate_targets.each do |target|
-    target.xcconfigs.each do |variant, xcconfig|
-      xcconfig_path = target.client_root + target.xcconfig_relative_path(variant)
-      IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR"))
-    end
-  end
-  installer.pods_project.targets.each do |target|
-    target.build_configurations.each do |config|
-      if config.base_configuration_reference.is_a? Xcodeproj::Project::Object::PBXFileReference
-        xcconfig_path = config.base_configuration_reference.real_path
-        IO.write(xcconfig_path, IO.read(xcconfig_path).gsub("DT_TOOLCHAIN_DIR", "TOOLCHAIN_DIR"))
-      end
-    end
-  end
-end

+ 1 - 18
Podfile.lock

@@ -8,15 +8,6 @@ PODS:
   - RealmSwift (10.54.2):
     - Realm (= 10.54.2)
   - SnapKit (5.7.1)
-  - SVProgressHUD (2.3.1):
-    - SVProgressHUD/Core (= 2.3.1)
-  - SVProgressHUD/Core (2.3.1)
-  - TSSmalCoacopods (1.0.0):
-    - Alamofire
-    - Kingfisher (= 7.10.0)
-    - ObjectMapper (~> 4.2)
-    - SnapKit
-    - SVProgressHUD
 
 DEPENDENCIES:
   - Alamofire
@@ -24,7 +15,6 @@ DEPENDENCIES:
   - ObjectMapper
   - RealmSwift (~> 10)
   - SnapKit
-  - TSSmalCoacopods (from `../TSSmalCoacopods`)
 
 SPEC REPOS:
   trunk:
@@ -34,11 +24,6 @@ SPEC REPOS:
     - Realm
     - RealmSwift
     - SnapKit
-    - SVProgressHUD
-
-EXTERNAL SOURCES:
-  TSSmalCoacopods:
-    :path: "../TSSmalCoacopods"
 
 SPEC CHECKSUMS:
   Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
@@ -47,9 +32,7 @@ SPEC CHECKSUMS:
   Realm: 16852517a207e98cc6acba9336b56c30d06d84ad
   RealmSwift: bca777b3904ee58a9b16036e1840012f03348060
   SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
-  SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22
-  TSSmalCoacopods: 6aa97167f0c76b16fc7d1fd1eb198bb6aece4f68
 
-PODFILE CHECKSUM: 7f2d634b57df6778cd355829f8b48ec12b4e10f5
+PODFILE CHECKSUM: 416afa5c73c2343230fae7fac7a1c42db885e619
 
 COCOAPODS: 1.16.2