Ver Fonte

feat: 增加游戏过滤面板,以及订单列表

陈文艺 há 4 meses atrás
pai
commit
4d2a178ab0
100 ficheiros alterados com 911 adições e 9 exclusões
  1. 46 1
      Lanu.xcodeproj/project.pbxproj
  2. 10 1
      Lanu.xcworkspace/xcshareddata/swiftpm/Package.resolved
  3. BIN
      Lanu/Assets.xcassets/AppIcon.appiconset/1024x1024.png
  4. 1 0
      Lanu/Assets.xcassets/AppIcon.appiconset/Contents.json
  5. 6 0
      Lanu/Assets.xcassets/Game/Contents.json
  6. 22 0
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/Contents.json
  7. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/ic_game_mate_list_cell_bg@2x.png
  8. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/ic_game_mate_list_cell_bg@3x.png
  9. 22 0
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/Contents.json
  10. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/ic_game_mate_list_cell_bubble@2x.png
  11. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/ic_game_mate_list_cell_bubble@3x.png
  12. 22 0
      Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/Contents.json
  13. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/ic_game_menu_find@2x.png
  14. BIN
      Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/ic_game_menu_find@3x.png
  15. 6 0
      Lanu/Assets.xcassets/Order/Contents.json
  16. 22 0
      Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/Contents.json
  17. BIN
      Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/ic_order_cancelled_bg@2x.png
  18. BIN
      Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/ic_order_cancelled_bg@3x.png
  19. 22 0
      Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/Contents.json
  20. BIN
      Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/ic_order_normal_bg@2x.png
  21. BIN
      Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/ic_order_normal_bg@3x.png
  22. 22 0
      Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/Contents.json
  23. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/ic_order_cancel@2x.png
  24. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/ic_order_cancel@3x.png
  25. 22 0
      Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/Contents.json
  26. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/ic_order_complete@2x.png
  27. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/ic_order_complete@3x.png
  28. 22 0
      Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/Contents.json
  29. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/ic_order_inprogress@2x.png
  30. BIN
      Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/ic_order_inprogress@3x.png
  31. 6 0
      Lanu/Assets.xcassets/common/Check/Contents.json
  32. 22 0
      Lanu/Assets.xcassets/common/Check/ic_check.imageset/Contents.json
  33. BIN
      Lanu/Assets.xcassets/common/Check/ic_check.imageset/ic_check@2x.png
  34. BIN
      Lanu/Assets.xcassets/common/Check/ic_check.imageset/ic_check@3x.png
  35. 22 0
      Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/Contents.json
  36. BIN
      Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/ic_uncheck@2x.png
  37. BIN
      Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/ic_uncheck@3x.png
  38. 6 0
      Lanu/Assets.xcassets/common/Diamond/Contents.json
  39. 22 0
      Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/Contents.json
  40. BIN
      Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/ic_diamond@2x.png
  41. BIN
      Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/ic_diamond@3x.png
  42. 6 0
      Lanu/Assets.xcassets/common/Gender/Contents.json
  43. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/Contents.json
  44. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/ic_gender_female@2x.png
  45. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/ic_gender_female@3x.png
  46. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/Contents.json
  47. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/ic_gender_male@2x.png
  48. 0 0
      Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/ic_gender_male@3x.png
  49. 6 0
      Lanu/Assets.xcassets/common/Sorted/Contents.json
  50. 22 0
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/Contents.json
  51. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/ic_sorted_down@2x.png
  52. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/ic_sorted_down@3x.png
  53. 22 0
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/Contents.json
  54. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/ic_sorted_none@2x.png
  55. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/ic_sorted_none@3x.png
  56. 22 0
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/Contents.json
  57. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/ic_sorted_up@2x.png
  58. BIN
      Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/ic_sorted_up@3x.png
  59. 6 0
      Lanu/Assets.xcassets/common/Star/Contents.json
  60. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star.imageset/Contents.json
  61. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star.imageset/ic_star@2x.png
  62. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star.imageset/ic_star@3x.png
  63. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/Contents.json
  64. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/ic_star_fill@2x.png
  65. 0 0
      Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/ic_star_fill@3x.png
  66. 22 0
      Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/Contents.json
  67. BIN
      Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/ic_star_white_border@2x.png
  68. BIN
      Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/ic_star_white_border@3x.png
  69. 22 0
      Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/Contents.json
  70. BIN
      Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/ic_star_white_border_fill@2x.png
  71. BIN
      Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/ic_star_white_border_fill@3x.png
  72. 22 0
      Lanu/Assets.xcassets/common/ic_location.imageset/Contents.json
  73. BIN
      Lanu/Assets.xcassets/common/ic_location.imageset/ic_location@2x.png
  74. BIN
      Lanu/Assets.xcassets/common/ic_location.imageset/ic_location@3x.png
  75. 6 0
      Lanu/Assets.xcassets/main/GameTab/Contents.json
  76. 22 0
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/Contents.json
  77. BIN
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/ic_main_game_tab_more@2x.png
  78. BIN
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/ic_main_game_tab_more@3x.png
  79. 22 0
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/Contents.json
  80. BIN
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/ic_main_game_tab_selected@2x.png
  81. BIN
      Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/ic_main_game_tab_selected@3x.png
  82. 22 0
      Lanu/Assets.xcassets/main/ic_main_language.imageset/Contents.json
  83. BIN
      Lanu/Assets.xcassets/main/ic_main_language.imageset/ic_main_language@2x.png
  84. BIN
      Lanu/Assets.xcassets/main/ic_main_language.imageset/ic_main_language@3x.png
  85. 22 0
      Lanu/Assets.xcassets/main/ic_main_logo.imageset/Contents.json
  86. BIN
      Lanu/Assets.xcassets/main/ic_main_logo.imageset/ic_main_logo@2x.png
  87. BIN
      Lanu/Assets.xcassets/main/ic_main_logo.imageset/ic_main_logo@3x.png
  88. BIN
      Lanu/Assets.xcassets/main/ic_main_mine.imageset/ic_main_mine@2x.png
  89. BIN
      Lanu/Assets.xcassets/main/ic_main_mine.imageset/ic_main_mine@3x.png
  90. 60 2
      Lanu/Common/Config/LNAppConfig.swift
  91. 1 0
      Lanu/Common/Storage/LNUserDefaultsKey.swift
  92. 57 0
      Lanu/Common/Theme/UIColor+Theme.swift
  93. 39 0
      Lanu/Common/Theme/UIFont+Theme.swift
  94. 40 0
      Lanu/Common/Theme/UIImage+Theme.swift
  95. 6 0
      Lanu/Common/Utils/NSObject+Extension.swift
  96. 3 2
      Lanu/Common/Utils/String+Extension.swift
  97. 62 0
      Lanu/Common/Utils/TimeInterval+Extension.swift
  98. 65 0
      Lanu/Common/Utils/UIImage+Extension.swift
  99. 9 1
      Lanu/Common/Utils/UIView+Extension.swift
  100. 2 2
      Lanu/Common/Views/Gender/LNGenderView.swift

+ 46 - 1
Lanu.xcodeproj/project.pbxproj

@@ -8,6 +8,7 @@
 
 /* Begin PBXBuildFile section */
 		0DE4E86CB596C7E4A75DCD81 /* Pods_Lanu.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABE0E79254D94F91C773E929 /* Pods_Lanu.framework */; };
+		FB696C172EC96C0F00FAD639 /* MJRefresh in Frameworks */ = {isa = PBXBuildFile; productRef = FB696C162EC96C0F00FAD639 /* MJRefresh */; };
 		FB9CD1192EC1EEA10033B14B /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = FB9CD1182EC1EEA10033B14B /* FirebaseCore */; };
 		FB9CD11B2EC1EEA10033B14B /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = FB9CD11A2EC1EEA10033B14B /* FirebaseCrashlytics */; };
 		FB9CD11E2EC1EEF30033B14B /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = FB9CD11D2EC1EEF30033B14B /* GoogleSignIn */; };
@@ -40,23 +41,26 @@
 				Common/Storage/LNUserDefaultsKey.swift,
 				"Common/Theme/UIColor+Theme.swift",
 				"Common/Theme/UIFont+Theme.swift",
+				"Common/Theme/UIImage+Theme.swift",
 				Common/Utils/AppUtils.swift,
 				"Common/Utils/Comparable+Extension.swift",
 				"Common/Utils/DispatchQueue+Extension.swift",
 				"Common/Utils/NSObject+Extension.swift",
 				"Common/Utils/String+Extension.swift",
+				"Common/Utils/TimeInterval+Extension.swift",
 				"Common/Utils/UIColor+Extension.swift",
+				"Common/Utils/UIImage+Extension.swift",
 				"Common/Utils/UIView+Extension.swift",
 				Common/Views/Base/LNNavigationController.swift,
 				Common/Views/Base/LNViewController.swift,
 				Common/Views/Gender/LNGenderView.swift,
 				Common/Views/LNAutoSizeTextView.swift,
 				Common/Views/LNPopupViewProtocol.swift,
+				Common/Views/LNSortedEditView.swift,
 				Common/Views/StarScore/LNFiveStarScoreView.swift,
 				Common/Views/StarScore/LNStarScoreView.swift,
 				Config_Debug.xcconfig,
 				Config_Release.xcconfig,
-				"Files/Font/Poppins-Regular.ttf",
 				"Files/Font/Poppins-SemiBold.ttf",
 				"GoogleService-Info-Debug.plist",
 				"GoogleService-Info-Release.plist",
@@ -64,6 +68,9 @@
 				Manager/Account/LNAccountManager.swift,
 				"Manager/Account/Network/LNHttpManager+Login.swift",
 				Manager/Account/Network/LNLoginResponse.swift,
+				Manager/GameMate/LNGameMateManager.swift,
+				Manager/GameMate/Network/LNGameMateResponse.swift,
+				"Manager/GameMate/Network/LNHttpManager+GameMate.swift",
 				Manager/IM/GenerateTestUserSig.m,
 				Manager/IM/LNIMManager.swift,
 				Manager/LNDelayTask.swift,
@@ -74,18 +81,41 @@
 				Manager/Network/Response/LNHttpEmptyResponse.swift,
 				Manager/Network/Response/LNHttpResponse.swift,
 				Manager/Order/LNOrderManager.swift,
+				"Manager/Order/Network/LNHttpManager+Order.swift",
+				Manager/Order/Network/LNOrderResponse.swift,
 				Manager/Profile/LNProfileManager.swift,
 				Manager/Profile/LNUserProfileInfo.swift,
 				"Manager/Profile/Network/LNHttpManager+Profile.swift",
 				Manager/Profile/Network/LNProfileResponse.swift,
 				Manager/Purchase/LNPurchaseManager.swift,
 				SceneDelegate.swift,
+				Views/Game/Category/LNGameCategoryListView.swift,
+				Views/Game/Category/LNGameCategoryListViewController.swift,
+				Views/Game/Category/LNGameCategoryTabItemView.swift,
+				Views/Game/Category/LNGameCategoryTabView.swift,
+				Views/Game/MateFilter/LNGameMateFilterDetailView.swift,
+				Views/Game/MateFilter/LNGameMateFilterPanel.swift,
+				Views/Game/MateFilter/LNGameMateGameTabView.swift,
+				Views/Game/MateList/LNGameMateListCell.swift,
+				Views/Game/MateList/LNGameMateListMenuView.swift,
+				Views/Game/MateList/LNGameMateListView.swift,
+				Views/Game/MateList/LNGameMateListViewController.swift,
 				Views/IM/LNIMViewController.swift,
 				Views/Login/LNLoginViewController.swift,
 				Views/Login/LNPrivacyTextView.swift,
+				Views/Main/GameTab/LNMainGameTabItemView.swift,
+				Views/Main/GameTab/LNMainGameTabView.swift,
+				Views/Main/LNLanguageSettingPanel.swift,
+				Views/Main/LNMainGamePanel.swift,
 				Views/Main/LNMainTopMenuView.swift,
 				Views/Main/LNMainTopTabView.swift,
 				Views/Main/LNMainViewController.swift,
+				Views/Order/LNOrderCommentPanel.swift,
+				Views/Order/LNOrderDetailViewController.swift,
+				Views/Order/OrderList/LNOrderListItemCell.swift,
+				Views/Order/OrderList/LNOrderListViewController.swift,
+				Views/Profile/LNMineViewController.swift,
+				Views/Profile/LNTestViewController.swift,
 			);
 			target = FBFE13BF2EBC39B000DCE6E9 /* Lanu */;
 		};
@@ -117,6 +147,7 @@
 				FBECAA1D2EC1C8860013A5E6 /* CocoaLumberjackSwiftLogBackend in Frameworks */,
 				FBECA9CA2EC1C8240013A5E6 /* CocoaLumberjackSwift in Frameworks */,
 				FB9CD1192EC1EEA10033B14B /* FirebaseCore in Frameworks */,
+				FB696C172EC96C0F00FAD639 /* MJRefresh in Frameworks */,
 				FB9CD11B2EC1EEA10033B14B /* FirebaseCrashlytics in Frameworks */,
 				FBECA9C42EC1C5250013A5E6 /* AutoCodable in Frameworks */,
 				FBECA9BE2EC1C50F0013A5E6 /* SnapKit in Frameworks */,
@@ -220,6 +251,7 @@
 				FBECAA192EC1C8860013A5E6 /* XCRemoteSwiftPackageReference "CocoaLumberjack" */,
 				FB9CD1172EC1EEA10033B14B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
 				FB9CD11C2EC1EEF30033B14B /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */,
+				FB696C152EC96C0F00FAD639 /* XCRemoteSwiftPackageReference "MJRefresh" */,
 			);
 			preferredProjectObjectVersion = 77;
 			productRefGroup = FBFE13C12EBC39B000DCE6E9 /* Products */;
@@ -543,6 +575,14 @@
 /* End XCConfigurationList section */
 
 /* Begin XCRemoteSwiftPackageReference section */
+		FB696C152EC96C0F00FAD639 /* XCRemoteSwiftPackageReference "MJRefresh" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "http://8.134.139.102:10880/chenwenyi/MJRefresh.git";
+			requirement = {
+				kind = upToNextMajorVersion;
+				minimumVersion = 3.7.9;
+			};
+		};
 		FB9CD1172EC1EEA10033B14B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "http://8.134.139.102:10880/chenwenyi/firebase-ios-sdk.git";
@@ -602,6 +642,11 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
+		FB696C162EC96C0F00FAD639 /* MJRefresh */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = FB696C152EC96C0F00FAD639 /* XCRemoteSwiftPackageReference "MJRefresh" */;
+			productName = MJRefresh;
+		};
 		FB9CD1182EC1EEA10033B14B /* FirebaseCore */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = FB9CD1172EC1EEA10033B14B /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;

+ 10 - 1
Lanu.xcworkspace/xcshareddata/swiftpm/Package.resolved

@@ -1,5 +1,5 @@
 {
-  "originHash" : "de0a7a7e6e2a3430fde50ddae06bb86a39d9e3ca9ed59c860b19e9108bd5ca3f",
+  "originHash" : "2167cacf2f7b65373b0205ee4ab56af4f3573059e1e1f2cf36ccf0fbf081f9ed",
   "pins" : [
     {
       "identity" : "abseil-cpp-binary",
@@ -145,6 +145,15 @@
         "version" : "1.22.5"
       }
     },
+    {
+      "identity" : "mjrefresh",
+      "kind" : "remoteSourceControl",
+      "location" : "http://8.134.139.102:10880/chenwenyi/MJRefresh.git",
+      "state" : {
+        "revision" : "535d39c86e592d73f8b8e75f9bf1eda62ca4a4ce",
+        "version" : "3.7.9"
+      }
+    },
     {
       "identity" : "nanopb",
       "kind" : "remoteSourceControl",

BIN
Lanu/Assets.xcassets/AppIcon.appiconset/1024x1024.png


+ 1 - 0
Lanu/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,6 +1,7 @@
 {
   "images" : [
     {
+      "filename" : "1024x1024.png",
       "idiom" : "universal",
       "platform" : "ios",
       "size" : "1024x1024"

+ 6 - 0
Lanu/Assets.xcassets/Game/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/ic_game_mate_list_cell_bg@2x.png


BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bg.imageset/ic_game_mate_list_cell_bg@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/ic_game_mate_list_cell_bubble@2x.png


BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_cell_bubble.imageset/ic_game_mate_list_cell_bubble@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/ic_game_menu_find@2x.png


BIN
Lanu/Assets.xcassets/Game/ic_game_mate_list_menu_find.imageset/ic_game_menu_find@3x.png


+ 6 - 0
Lanu/Assets.xcassets/Order/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/ic_order_cancelled_bg@2x.png


BIN
Lanu/Assets.xcassets/Order/ic_order_cancelled_bg.imageset/ic_order_cancelled_bg@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/ic_order_normal_bg@2x.png


BIN
Lanu/Assets.xcassets/Order/ic_order_normal_bg.imageset/ic_order_normal_bg@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/ic_order_cancel@2x.png


BIN
Lanu/Assets.xcassets/Order/ic_order_status_cancel.imageset/ic_order_cancel@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/ic_order_complete@2x.png


BIN
Lanu/Assets.xcassets/Order/ic_order_status_complete.imageset/ic_order_complete@3x.png


+ 22 - 0
Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/ic_order_inprogress@2x.png


BIN
Lanu/Assets.xcassets/Order/ic_order_status_in_progress.imageset/ic_order_inprogress@3x.png


+ 6 - 0
Lanu/Assets.xcassets/common/Check/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/common/Check/ic_check.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Check/ic_check.imageset/ic_check@2x.png


BIN
Lanu/Assets.xcassets/common/Check/ic_check.imageset/ic_check@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/ic_uncheck@2x.png


BIN
Lanu/Assets.xcassets/common/Check/ic_uncheck.imageset/ic_uncheck@3x.png


+ 6 - 0
Lanu/Assets.xcassets/common/Diamond/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/ic_diamond@2x.png


BIN
Lanu/Assets.xcassets/common/Diamond/ic_diamond.imageset/ic_diamond@3x.png


+ 6 - 0
Lanu/Assets.xcassets/common/Gender/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_female.imageset/Contents.json → Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/Contents.json


+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_female.imageset/ic_gender_female@2x.png → Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/ic_gender_female@2x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_female.imageset/ic_gender_female@3x.png → Lanu/Assets.xcassets/common/Gender/ic_gender_female.imageset/ic_gender_female@3x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_male.imageset/Contents.json → Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/Contents.json


+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_male.imageset/ic_gender_male@2x.png → Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/ic_gender_male@2x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_gender_male.imageset/ic_gender_male@3x.png → Lanu/Assets.xcassets/common/Gender/ic_gender_male.imageset/ic_gender_male@3x.png


+ 6 - 0
Lanu/Assets.xcassets/common/Sorted/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/ic_sorted_down@2x.png


BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_down.imageset/ic_sorted_down@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/ic_sorted_none@2x.png


BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_none.imageset/ic_sorted_none@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/ic_sorted_up@2x.png


BIN
Lanu/Assets.xcassets/common/Sorted/ic_sorted_up.imageset/ic_sorted_up@3x.png


+ 6 - 0
Lanu/Assets.xcassets/common/Star/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 0 - 0
Lanu/Assets.xcassets/common/ic_star.imageset/Contents.json → Lanu/Assets.xcassets/common/Star/ic_star.imageset/Contents.json


+ 0 - 0
Lanu/Assets.xcassets/common/ic_star.imageset/ic_star@2x.png → Lanu/Assets.xcassets/common/Star/ic_star.imageset/ic_star@2x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_star.imageset/ic_star@3x.png → Lanu/Assets.xcassets/common/Star/ic_star.imageset/ic_star@3x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_star_fill.imageset/Contents.json → Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/Contents.json


+ 0 - 0
Lanu/Assets.xcassets/common/ic_star_fill.imageset/ic_star_fill@2x.png → Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/ic_star_fill@2x.png


+ 0 - 0
Lanu/Assets.xcassets/common/ic_star_fill.imageset/ic_star_fill@3x.png → Lanu/Assets.xcassets/common/Star/ic_star_fill.imageset/ic_star_fill@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/ic_star_white_border@2x.png


BIN
Lanu/Assets.xcassets/common/Star/ic_star_white_border.imageset/ic_star_white_border@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/ic_star_white_border_fill@2x.png


BIN
Lanu/Assets.xcassets/common/Star/ic_star_white_border_fill.imageset/ic_star_white_border_fill@3x.png


+ 22 - 0
Lanu/Assets.xcassets/common/ic_location.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/common/ic_location.imageset/ic_location@2x.png


BIN
Lanu/Assets.xcassets/common/ic_location.imageset/ic_location@3x.png


+ 6 - 0
Lanu/Assets.xcassets/main/GameTab/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/ic_main_game_tab_more@2x.png


BIN
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_more.imageset/ic_main_game_tab_more@3x.png


+ 22 - 0
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/ic_main_game_tab_selected@2x.png


BIN
Lanu/Assets.xcassets/main/GameTab/ic_main_game_tab_selected.imageset/ic_main_game_tab_selected@3x.png


+ 22 - 0
Lanu/Assets.xcassets/main/ic_main_language.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/main/ic_main_language.imageset/ic_main_language@2x.png


BIN
Lanu/Assets.xcassets/main/ic_main_language.imageset/ic_main_language@3x.png


+ 22 - 0
Lanu/Assets.xcassets/main/ic_main_logo.imageset/Contents.json

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

BIN
Lanu/Assets.xcassets/main/ic_main_logo.imageset/ic_main_logo@2x.png


BIN
Lanu/Assets.xcassets/main/ic_main_logo.imageset/ic_main_logo@3x.png


BIN
Lanu/Assets.xcassets/main/ic_main_mine.imageset/ic_main_mine@2x.png


BIN
Lanu/Assets.xcassets/main/ic_main_mine.imageset/ic_main_mine@3x.png


+ 60 - 2
Lanu/Common/Config/LNAppConfig.swift

@@ -6,14 +6,72 @@
 //
 
 import Foundation
+import Combine
 
 enum LNAppEnvType: Codable {
     case test
     case official
 }
 
+enum LNAppLanguage: Codable {
+    case chiness
+    case english
+    case indonesian
+    
+    var text: String {
+        switch self {
+        case .chiness: "中文"
+        case .english: "English"
+        case .indonesian: "Indonesian"
+        }
+    }
+    
+    var bundleName: String {
+        switch self {
+        case .chiness: "zh-Hans"
+        case .english: "en"
+        case .indonesian: "indonesian"
+        }
+    }
+    
+    var isSelected: Bool {
+        self == LNAppConfig.shared.curLang
+    }
+    
+    static var available: [LNAppLanguage] {
+        [.chiness, .english, .indonesian]
+    }
+}
+
 class LNAppConfig {
-    static var curEnv: LNAppEnvType = LNUserDefaults[.appEnv, .official] {
-        didSet { LNUserDefaults[.appEnv] = curEnv }
+    static var shared = LNAppConfig()
+    
+    @Published
+    var curEnv: LNAppEnvType = LNUserDefaults[.appEnv, .official] {
+        didSet {
+            LNUserDefaults[.appEnv] = curEnv
+        }
+    }
+    
+    @Published
+    var curLang: LNAppLanguage = LNUserDefaults[.appLanguage, .english] {
+        didSet {
+            LNUserDefaults[.appLanguage] = curLang
+        }
+    }
+    
+    var languageBundleMap: [LNAppLanguage: Bundle] = {
+        LNAppLanguage.available.reduce(into: [LNAppLanguage: Bundle](), { result, language in
+            let bundle = if let path = Bundle.main.path(forResource: language.bundleName, ofType: "lproj"),
+                  let bundle = Bundle(path: path) {
+                bundle
+            } else {
+                Bundle.main
+            }
+            result[language] = bundle
+        })
+    }()
+    var languageBundle: Bundle {
+        languageBundleMap[curLang] ?? Bundle.main
     }
 }

+ 1 - 0
Lanu/Common/Storage/LNUserDefaultsKey.swift

@@ -9,6 +9,7 @@ import Foundation
 
 enum LNUserDefaultsKey: String {
     case appEnv
+    case appLanguage
     
     case token
     case uid

+ 57 - 0
Lanu/Common/Theme/UIColor+Theme.swift

@@ -6,3 +6,60 @@
 //
 
 import Foundation
+
+
+extension UIColor {
+    static let text_6: UIColor = {
+        .init(hex: "#3FBFBD")
+    }()
+    static let text_5: UIColor = {
+        .init(hex: "#1D2129")
+    }()
+    static let text_4: UIColor = {
+        .init(hex: "#4E5969")
+    }()
+    static let text_3: UIColor = {
+        .init(hex: "#86909C")
+    }()
+    static let text_2: UIColor = {
+        .init(hex: "#CDCFD9")
+    }()
+    static let text_1: UIColor = {
+        .init(hex: "#CDCFD9")
+    }()
+    
+    static let primary_1: UIColor = {
+        .init(hex: "#F1F2F5")
+    }()
+    static let primary_2: UIColor = {
+        .init(hex: "#BCE7F4")
+    }()
+    static let primary_3: UIColor = {
+        .init(hex: "#15E5E2")
+    }()
+    static let primary_4: UIColor = {
+        .init(hex: "#7CDFFF")
+    }()
+    static let primary_5: UIColor = {
+        .init(hex: "#1789FF")
+    }()
+    
+    static let fill: UIColor = {
+        .init(hex: "#FFFFFF")
+    }()
+    static let fill_1: UIColor = {
+        .init(hex: "#F9FAFB")
+    }()
+    static let fill_2: UIColor = {
+        .init(hex: "#F2F3F5")
+    }()
+    static let fill_3: UIColor = {
+        .init(hex: "#E5E6EB")
+    }()
+    static let fill_4: UIColor = {
+        .init(hex: "#C9CDD4")
+    }()
+    static let fill_5: UIColor = {
+        .init(hex: "#E6FFFA")
+    }()
+}

+ 39 - 0
Lanu/Common/Theme/UIFont+Theme.swift

@@ -6,3 +6,42 @@
 //
 
 import Foundation
+
+extension UIFont {
+    private static let boldFontName = "Poppins-SemiBold"
+    
+    static let heading_h1: UIFont = {
+        .init(name: boldFontName, size: 24)!
+    }()
+    static let heading_h1_5: UIFont = {
+        .init(name: boldFontName, size: 22)!
+    }()
+    static let heading_h2: UIFont = {
+        .init(name: boldFontName, size: 18)!
+    }()
+    static let heading_h3: UIFont = {
+        .init(name: boldFontName, size: 16)!
+    }()
+    static let heading_h4: UIFont = {
+        .init(name: boldFontName, size: 14)!
+    }()
+    static let heading_h5: UIFont = {
+        .init(name: boldFontName, size: 12)!
+    }()
+    
+    static let body_xl: UIFont = {
+        .systemFont(ofSize: 24)
+    }()
+    static let body_x: UIFont = {
+        .systemFont(ofSize: 16)
+    }()
+    static let body_m: UIFont = {
+        .systemFont(ofSize: 14)
+    }()
+    static let body_s: UIFont = {
+        .systemFont(ofSize: 12)
+    }()
+    static let body_xs: UIFont = {
+        .systemFont(ofSize: 11)
+    }()
+}

+ 40 - 0
Lanu/Common/Theme/UIImage+Theme.swift

@@ -0,0 +1,40 @@
+//
+//  UIImage+Theme.swift
+//  Lanu
+//
+//  Created by OneeChan on 2025/11/20.
+//
+
+import Foundation
+
+extension UIImage {
+    static let primary_6: UIImage? = {
+        generateLinearGradientImage(
+            colors: [.init(hex: "#B7EEFF"), .init(hex: "#DDFFB7"), .init(hex: "#FFFFFF")],
+            size: .init(width: 10, height: 10),
+            location: [0, 0.36, 1],
+            startPoint: .init(x: 0.25, y: 0.5),
+            endPoint: .init(x: 0.75, y: 0.5)
+        )
+    }()
+    
+    static let primary_7: UIImage? = {
+        generateLinearGradientImage(
+            colors: [.init(hex: "#4ED2FF"), .init(hex: "#B1EF5D")],
+            size: .init(width: 10, height: 10),
+            location: [0, 1],
+            startPoint: .init(x: 0.25, y: 0.5),
+            endPoint: .init(x: 0.75, y: 0.5)
+        )
+    }()
+    
+    static let primary_8: UIImage? = {
+        generateLinearGradientImage(
+            colors: [.init(hex: "#2F95FF"), .init(hex: "primary8")],
+            size: .init(width: 10, height: 10),
+            location: [0, 1],
+            startPoint: .init(x: 0.25, y: 0.5),
+            endPoint: .init(x: 0.75, y: 0.5)
+        )
+    }()
+}

+ 6 - 0
Lanu/Common/Utils/NSObject+Extension.swift

@@ -30,3 +30,9 @@ extension NSObject {
         }
     }
 }
+
+extension NSObject {
+    static var className: String {
+        String(describing: Self.self)
+    }
+}

+ 3 - 2
Lanu/Common/Utils/String+Extension.swift

@@ -11,11 +11,12 @@ import CommonCrypto
 
 extension String {
     init(key: String) {
-        self = NSLocalizedString(key, comment: "")
+        self = LNAppConfig.shared.languageBundle.localizedString(forKey: key, value: key, table: nil)
     }
     
     init(key: String, _ with: any CVarArg...) {
-        self = String(format: NSLocalizedString(key, comment: ""), with)
+        let format = LNAppConfig.shared.languageBundle.localizedString(forKey: key, value: key, table: nil)
+        self = String(format: format, with)
     }
 }
 

+ 62 - 0
Lanu/Common/Utils/TimeInterval+Extension.swift

@@ -0,0 +1,62 @@
+//
+//  TimeInterval+Extension.swift
+//  Lanu
+//
+//  Created by OneeChan on 2025/11/20.
+//
+
+import Foundation
+
+
+extension TimeInterval {
+    // 辅助方法:格式化 "时:分"(补零,如 09:05)
+    func formattedTime() -> String {
+        let formatter = DateFormatter()
+        formatter.dateFormat = "HH:mm"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "星期一"
+    func formattedWeek() -> String {
+        let formatter = DateFormatter()
+        formatter.locale = Locale.current
+        formatter.dateFormat = "EEEE"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "星期 时:分"(如 星期一 09:30)
+    func formattedWeekWithTime() -> String {
+        let formatter = DateFormatter()
+        formatter.locale = Locale.current
+        formatter.dateFormat = "EEEE HH:mm"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "月/日"(如 10/23)
+    func formattedDate() -> String {
+        let formatter = DateFormatter()
+        formatter.dateFormat = "MM/dd"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "月/日 时:分"(如 10/23 14:30)
+    func formattedDateWithTime() -> String {
+        let formatter = DateFormatter()
+        formatter.dateFormat = "MM/dd HH:mm"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "年/月/日"(如 2025/10/23)
+    func formattedFullDate() -> String {
+        let formatter = DateFormatter()
+        formatter.dateFormat = "yyyy/MM/dd"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+    
+    // 辅助方法:格式化 "年/月/日 时:分"(如 2025/10/23 14:30)
+    func formattedFullDateWithTime() -> String {
+        let formatter = DateFormatter()
+        formatter.dateFormat = "yyyy/MM/dd HH:mm"
+        return formatter.string(from: Date(timeIntervalSince1970: self))
+    }
+}

+ 65 - 0
Lanu/Common/Utils/UIImage+Extension.swift

@@ -0,0 +1,65 @@
+//
+//  UIImage+Extension.swift
+//  Lanu
+//
+//  Created by OneeChan on 2025/11/16.
+//
+
+import Foundation
+
+
+extension UIImage {
+    static let commonGradientBg: UIImage? = {
+        generateLinearGradientImage(
+            colors: [.init(hex: "#4ED2FF"), .init(hex: "#B1EF5D")],
+            size: .init(width: 10, height: 10),
+            location: [0, 1],
+            startPoint: .init(x: 0.25, y: 0.5),
+            endPoint: .init(x: 0.75, y: 0.5)
+        )
+    }()
+    
+    static let commonButtonGradientBg: UIImage? = {
+        generateLinearGradientImage(
+            colors: [.init(hex: "#2F95FF"), .init(hex: "#50FFD8")],
+            size: .init(width: 10, height: 10),
+            location: [0, 1],
+            startPoint: .init(x: 0.25, y: 0.5),
+            endPoint: .init(x: 0.75, y: 0.5)
+        )
+    }()
+
+    /// 生成线性渐变图片
+    /// - Parameters:
+    ///   - colors: 渐变颜色数组(至少两种)
+    ///   - size: 图片尺寸
+    ///   - startPoint: 渐变起点(坐标系:左上角(0,0),右下角(1,1))
+    ///   - endPoint: 渐变终点
+    /// - Returns: 生成的渐变图片(nil 表示参数无效)
+    static func generateLinearGradientImage(
+        colors: [UIColor],
+        size: CGSize,
+        location: [NSNumber],
+        startPoint: CGPoint = CGPoint(x: 0, y: 0),
+        endPoint: CGPoint = CGPoint(x: 1, y: 0)
+    ) -> UIImage? {
+        // 校验参数有效性
+        guard colors.count >= 2, size.width > 0, size.height > 0 else {
+            return nil
+        }
+        
+        // 创建渐变图层
+        let gradientLayer = CAGradientLayer()
+        gradientLayer.frame = CGRect(origin: .zero, size: size)
+        gradientLayer.colors = colors.map { $0.cgColor } // 转换为 CGColor
+        gradientLayer.locations = location
+        gradientLayer.startPoint = startPoint
+        gradientLayer.endPoint = endPoint
+        
+        // 渲染图层为图片
+        let renderer = UIGraphicsImageRenderer(size: size)
+        return renderer.image { _ in
+            gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
+        }
+    }
+}

+ 9 - 1
Lanu/Common/Utils/UIView+Extension.swift

@@ -25,7 +25,11 @@ extension UIView {
         return nil
     }
     
-    var appKeyWindow: UIWindow {
+    var topView: UIView? {
+        viewController?.view
+    }
+    
+    static var appKeyWindow: UIWindow {
         // 从当前活跃的场景中获取窗口
         (UIApplication.shared.connectedScenes
             .filter { $0.activationState == .foregroundActive }
@@ -42,6 +46,10 @@ extension UIView {
         }
         return windowScene.statusBarManager?.statusBarFrame.height ?? 0
     }()
+    
+    var safeBottomInset: CGFloat {
+        Self.appKeyWindow.safeAreaInsets.bottom
+    }
 }
 
 // MARK: 点击响应

+ 2 - 2
Lanu/Common/Views/Gender/LNGenderView.swift

@@ -48,8 +48,8 @@ extension LNGenderView {
             make.height.equalTo(0).priority(.low)
         }
         
-        ageLabel.font = .systemFont(ofSize: 11)
-        ageLabel.textColor = .white
+        ageLabel.font = .body_xs
+        ageLabel.textColor = .text_1
         addSubview(ageLabel)
         ageLabel.snp.makeConstraints { make in
             make.centerY.equalToSuperview()

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff