运动功能开发
authorliangzhenying <867174124@qq.com>
Fri, 6 Feb 2026 10:44:18 +0000 (18:44 +0800)
committerliangzhenying <867174124@qq.com>
Fri, 6 Feb 2026 10:44:18 +0000 (18:44 +0800)
58 files changed:
DeepChordsSdk_iOS/DeepChordsSdk/Example/Example.xcodeproj/project.pbxproj
DeepChordsSdk_iOS/DeepChordsSdk/Example/Example/Info.plist
ShenYin/ShenYin.xcodeproj/project.pbxproj
ShenYin/ShenYin/Api/HttpClient.swift
ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@2x.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@3x.png [new file with mode: 0644]
ShenYin/ShenYin/Cache/UserInfo.swift
ShenYin/ShenYin/Cache/UserModel.swift
ShenYin/ShenYin/Launch/AppLaunch.swift
ShenYin/ShenYin/Launch/AppManager.swift
ShenYin/ShenYin/Launch/SceneDelegate.swift
ShenYin/ShenYin/Sdk/DcSdk/VC/HomeDeviceVC.swift
ShenYin/ShenYin/Sdk/DcSdk/tool/CCBleManager.swift
ShenYin/ShenYin/Sdk/DcSdk/tool/CCConfig.swift
ShenYin/ShenYin/Sdk/JoySdk/VC/HomeDeviceVC.swift
ShenYin/ShenYin/Sdk/LogManager.swift
ShenYin/ShenYin/UI/Base/BaseTC.swift
ShenYin/ShenYin/UI/Mine/AccountSetVC.swift
ShenYin/ShenYin/UI/Mine/Root/MineHeaderView.swift
ShenYin/ShenYin/UI/Mine/UserInfo/UserInfoCell.swift
ShenYin/ShenYin/UI/Mine/UserInfo/UserInfoVC.swift
ShenYin/ShenYin/UI/Sport/Sport/Group/Create/AddGroupHeader.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Create/CreateGroupVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportInputItem.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSelectItem.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSwitchItem.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupCell.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupModel.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupView.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupRoleVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupTypeVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Group/add/AddGroupVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Ready/CountdownView.swift
ShenYin/ShenYin/UI/Sport/Sport/Ready/FooterView.swift
ShenYin/ShenYin/UI/Sport/Sport/Root/DataView.swift
ShenYin/ShenYin/UI/Sport/Sport/Root/GroupView.swift
ShenYin/ShenYin/UI/Sport/Sport/Root/PlanView.swift
ShenYin/ShenYin/UI/Sport/Sport/Root/RouteView.swift
ShenYin/ShenYin/UI/Sport/Sport/Root/SportTypeView.swift
ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailBoard.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Sport/Sport/Sporting/DetailBoard.swift
ShenYin/ShenYin/UI/Sport/Sport/Sporting/SportingVC.swift
ShenYin/ShenYin/UI/Sport/Sport/Tools/MapManager.swift

index f73584e..b99cdee 100644 (file)
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = Example/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = "骨传导sdk";
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "使用蓝牙哦";
+                               INFOPLIST_KEY_NSMicrophoneUsageDescription = "使用麦克风哦";
                                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                                INFOPLIST_KEY_UIMainStoryboardFile = Main;
                                        "\"UIKit\"",
                                        "-ObjC",
                                );
-                               PRODUCT_BUNDLE_IDENTIFIER = deepchords.guchuandao.Example;
+                               PRODUCT_BUNDLE_IDENTIFIER = deepchords.ai.Example;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SWIFT_EMIT_LOC_STRINGS = YES;
                                SWIFT_OBJC_BRIDGING_HEADER = "Example/VC/Example-Bridging-Header.h";
                                );
                                GENERATE_INFOPLIST_FILE = YES;
                                INFOPLIST_FILE = Example/Info.plist;
+                               INFOPLIST_KEY_CFBundleDisplayName = "骨传导sdk";
                                INFOPLIST_KEY_NSBluetoothAlwaysUsageDescription = "使用蓝牙哦";
+                               INFOPLIST_KEY_NSMicrophoneUsageDescription = "使用麦克风哦";
                                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                                INFOPLIST_KEY_UIMainStoryboardFile = Main;
                                        "\"UIKit\"",
                                        "-ObjC",
                                );
-                               PRODUCT_BUNDLE_IDENTIFIER = deepchords.guchuandao.Example;
+                               PRODUCT_BUNDLE_IDENTIFIER = deepchords.ai.Example;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                SWIFT_EMIT_LOC_STRINGS = YES;
                                SWIFT_OBJC_BRIDGING_HEADER = "Example/VC/Example-Bridging-Header.h";
index b571c8d..c0ae0b4 100644 (file)
@@ -2,6 +2,11 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+       <key>NSAppTransportSecurity</key>
+       <dict>
+               <key>NSAllowsArbitraryLoads</key>
+               <true/>
+       </dict>
        <key>UIApplicationSceneManifest</key>
        <dict>
                <key>UIApplicationSupportsMultipleScenes</key>
                        </array>
                </dict>
        </dict>
-       <key>NSAppTransportSecurity</key>
-       <dict>
-               <key>NSAllowsArbitraryLoads</key>
-               <true/>
-       </dict>
-       <key>CFBundleDisplayName</key>
-       <string>骨传导sdk</string>
-       <key>NSMicrophoneUsageDescription</key>
-       <string>使用麦克风哦</string>
 </dict>
 </plist>
index a9c06e7..9de0b86 100644 (file)
                                UI/Sleep/SleepVM.swift,
                                UI/Sport/MusicRootView.swift,
                                UI/Sport/RecordRootView.swift,
+                               UI/Sport/Sport/Light/BrightnessView.swift,
+                               UI/Sport/Sport/Light/LightSetVC.swift,
+                               UI/Sport/Sport/Light/ModeView.swift,
+                               UI/Sport/Sport/Light/StateView.swift,
                                UI/Sport/Sport/Ready/CountdownView.swift,
                                UI/Sport/Sport/Ready/CustomMapView.swift,
                                UI/Sport/Sport/Ready/FooterView.swift,
                                UI/Sport/Sport/Set/SportSetCell.swift,
                                UI/Sport/Sport/Set/SportSetModel.swift,
                                UI/Sport/Sport/Set/SportSetVC.swift,
+                               UI/Sport/Sport/SportDetail/SportDetailBoard.swift,
+                               UI/Sport/Sport/SportDetail/SportDetailVC.swift,
+                               UI/Sport/Sport/Sporting/DetailBoard.swift,
+                               UI/Sport/Sport/Sporting/SimpleBoard.swift,
+                               UI/Sport/Sport/Sporting/SportingVC.swift,
+                               UI/Sport/Sport/Target/CalorieView.swift,
+                               UI/Sport/Sport/Target/DistanceView.swift,
+                               UI/Sport/Sport/Target/DurationView.swift,
+                               UI/Sport/Sport/Target/SportTargetVC.swift,
                                UI/Sport/Sport/Tools/MapManager.swift,
                                UI/Sport/SportHomeVC.swift,
                                UI/Sport/TranslateRootView.swift,
                                Sdk/JoySdk/VC/ModeVC.swift,
                                UI/Sport/MusicRootView.swift,
                                UI/Sport/RecordRootView.swift,
+                               UI/Sport/Sport/Light/BrightnessView.swift,
+                               UI/Sport/Sport/Light/LightSetVC.swift,
+                               UI/Sport/Sport/Light/ModeView.swift,
+                               UI/Sport/Sport/Light/StateView.swift,
                                UI/Sport/Sport/Ready/CountdownView.swift,
                                UI/Sport/Sport/Ready/CustomMapView.swift,
                                UI/Sport/Sport/Ready/FooterView.swift,
                                UI/Sport/Sport/Set/SportSetCell.swift,
                                UI/Sport/Sport/Set/SportSetModel.swift,
                                UI/Sport/Sport/Set/SportSetVC.swift,
+                               UI/Sport/Sport/SportDetail/SportDetailBoard.swift,
+                               UI/Sport/Sport/SportDetail/SportDetailVC.swift,
+                               UI/Sport/Sport/Sporting/DetailBoard.swift,
+                               UI/Sport/Sport/Sporting/SimpleBoard.swift,
+                               UI/Sport/Sport/Sporting/SportingVC.swift,
+                               UI/Sport/Sport/Target/CalorieView.swift,
+                               UI/Sport/Sport/Target/DistanceView.swift,
+                               UI/Sport/Sport/Target/DurationView.swift,
+                               UI/Sport/Sport/Target/SportTargetVC.swift,
                                UI/Sport/Sport/Tools/MapManager.swift,
                                UI/Sport/SportHomeVC.swift,
                                UI/Sport/TranslateRootView.swift,
index 1187a97..c611c63 100644 (file)
@@ -54,6 +54,8 @@ enum CommomApi
     case updatePhone(param:[String:Any])
     /// 更新邮箱
     case updateEmail(param:[String:Any])
+    /// 获取用户信息
+    case getUserInfo
     /// 更新用户信息
     case updateUserInfo(param:[String:Any])
     /// 获取用户存储空间
@@ -124,6 +126,13 @@ enum CommomApi
     case voiceRecordCollection(param:[String:Any])
     /// 获取背景图
     case backgroundList
+    
+    /// 创建团队
+    case createSportGroup(param:[String:Any])
+    /// 获取团队
+    case getSportGroupList(param:[String:Any])
+    /// 申请加入团队
+    case applyJoinGroup(param:[String:Any])
 }
 
 // 实现TargetType协议
@@ -179,17 +188,32 @@ extension CommomApi{
             return "/uc/phone/bind?smsCode=\(param["smsCode"]!)&phone=\(param["phone"]!)"
         case .updateEmail(let param):
             return "/uc/email?emailCode=\(param["emailCode"]!)&email=\(param["email"]!)"
+        case .getUserInfo:
+            return "/uc/userinfo"
         case .updateUserInfo(let param):
             var path = "/uc/userinfo?"
-            if let username = param["username"]{
-                path += "username=\(username)&"
+            if let text = param["username"]{
+                path += "username=\(text)&"
+            }
+            if let text = param["gender"]{
+                path += "gender=\(text)&"
+            }
+            if let text = param["tall"]{
+                path += "tall=\(text)&"
             }
-            if let gender = param["gender"]{
-                path += "gender=\(gender)&"
+            if let text = param["weight"]{
+                path += "weight=\(text)&"
             }
-            if let countyId = param["countryId"]{
-                path += "countyId=\(countyId)"
+            if let text = param["birthday"]{
+                path += "birthday=\(text)&"
             }
+            if let text = param["preference"]{
+                path += "preference=\(text)&"
+            }
+            if let text = param["countryId"]{
+                path += "countyId=\(text)"
+            }
+            Logger.debug("path => ",path)
             return path
         case .storageSize:
             return "/res/voice-file/storage-size"
@@ -266,12 +290,22 @@ extension CommomApi{
             
         case .backgroundList:
             return "/dev/devBg/list"
+            
+            
+        case .createSportGroup(_):
+            return "/sp/sport-group"
+        case .getSportGroupList(_):
+            return "/sp/sport-group/list"
+        case .applyJoinGroup(let param):
+            return "/sp/sport-group/\(param["id"]!)/apply"
+            
+            
         }
     }
     
     var method:RequestMethod{
         switch self {
-        case .register(_),.phoneCodeLogin(_),.emailCodeLogin(_),.appleLogin(_),.login(_),.commitFeedback(_),.voiceRecord(_),.voiceRecordText(_):
+        case .register(_),.phoneCodeLogin(_),.emailCodeLogin(_),.appleLogin(_),.login(_),.commitFeedback(_),.voiceRecord(_),.voiceRecordText(_),.createSportGroup(_),.applyJoinGroup(_):
             return .post
         case .updatePwd(_),.updateUserInfo(_),.updatePhone(_),.bindPhone(_),.updateEmail(_),.bindDevice(_),.otaUpdateVersion(_),.voiceRecordCollection(_),.updateVoiceRecord(_):
             return .put
@@ -351,6 +385,12 @@ extension CommomApi{
             params += para
         case let .updateVoiceRecord(para):
             params += para
+        case let .createSportGroup(para):
+            params += para
+        case let .getSportGroupList(para):
+            params += para
+        case let .applyJoinGroup(para):
+            params += para
         default:
             break
         }
@@ -363,6 +403,7 @@ extension CommomApi{
             "devtype": "iOS",
             "devid": UIDevice().identifierForVendor?.uuidString ?? "unknow",
             //            "Content - Type": "application/json"
+            "dc-ut":CacheManager.shared.user.token ?? ""
         ]
     }
 }
@@ -372,26 +413,26 @@ class HttpClient{
     static func request<T: HandyJSON>(_ target: CommomApi,completionHandler:@escaping ((T, String) -> Void)){
         let url = target.url
         let params = target.param
-        Logger.debug("request => ",url)
-        Logger.debug(YLToos.jsonToString(params))
+        Logger.debug("request => ",url,YLToos.jsonToString(params))
+//        Logger.debug("header =>",YLToos.jsonToString(target.headers!))
         
         if target.method == .get {
-            HTTP.GET(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in
+            HTTP.GET(url,parameters: params,headers: target.headers,requestSerializer: JSONParameterSerializer()){ response in
                 handleResponse(response, completionHandler: completionHandler)
             }
         }
         else if target.method == .post{
-            HTTP.POST(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in
+            HTTP.POST(url,parameters: params,headers: target.headers,requestSerializer: JSONParameterSerializer()){ response in
                 handleResponse(response, completionHandler: completionHandler)
             }
         }
         else if target.method == .put{
-            HTTP.PUT(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in
+            HTTP.PUT(url,parameters: params,headers: target.headers,requestSerializer: JSONParameterSerializer()){ response in
                 handleResponse(response, completionHandler: completionHandler)
             }
         }
         else if target.method == .delete{
-            HTTP.DELETE(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in
+            HTTP.DELETE(url,parameters: params,headers: target.headers,requestSerializer: JSONParameterSerializer()){ response in
                 handleResponse(response, completionHandler: completionHandler)
             }
         }
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..71dfb63
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 137@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 137@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@2x.png b/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@2x.png
new file mode 100644 (file)
index 0000000..9e0e80c
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@3x.png b/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@3x.png
new file mode 100644 (file)
index 0000000..8a3667d
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/add_2.imageset/Slice 137@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Contents.json
new file mode 100644 (file)
index 0000000..68cd0ef
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 156@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 156@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@2x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@2x.png
new file mode 100644 (file)
index 0000000..e7bd624
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@3x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@3x.png
new file mode 100644 (file)
index 0000000..9dc4350
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_lock.imageset/Slice 156@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Contents.json
new file mode 100644 (file)
index 0000000..df62631
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 42@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 42@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@2x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@2x.png
new file mode 100644 (file)
index 0000000..7c44451
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@3x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@3x.png
new file mode 100644 (file)
index 0000000..c28d3ef
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_pause.imageset/Slice 42@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Contents.json
new file mode 100644 (file)
index 0000000..078cd1b
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 157@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 157@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@2x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@2x.png
new file mode 100644 (file)
index 0000000..6ce9d45
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@3x.png b/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@3x.png
new file mode 100644 (file)
index 0000000..89f5013
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/btn_set.imageset/Slice 157@3x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Contents.json
new file mode 100644 (file)
index 0000000..2b86952
--- /dev/null
@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Slice 205@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Slice 205@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@2x.png b/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@2x.png
new file mode 100644 (file)
index 0000000..511476f
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@2x.png differ
diff --git a/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@3x.png b/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@3x.png
new file mode 100644 (file)
index 0000000..ee95729
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/sport/group_avatar.imageset/Slice 205@3x.png differ
index 8d61a2f..e54c4c2 100644 (file)
@@ -7,8 +7,8 @@
 import HandyJSON
 
 enum GenderType:String,HandyJSONEnum{
-    case man = "1"
     case female = "0"
+    case man = "1"
     case unnkown = "2"
     var title:String{
         switch self {
@@ -28,15 +28,33 @@ class UserInfoRoot:ResponseBaseModel {
 }
 
 class UserInfo:ResponseBaseModel {
+    /// 用户id
     var id = ""
+    /// 头像
     var avatar = ""
+    /// 昵称
     var userName = ""
+    /// 创建时间
     var createTime = ""
+    /// 手机号码
     var phone = ""
+    /// 邮箱
     var email = ""
+    /// 性别
     var gender = GenderType.unnkown
+    /// 国家
     var countryName = ""
+    /// 国家id
     var countryId = ""
+    /// 生日
+    var birthday:String = ""
+    /// 身高
+    var tall:String = ""
+    ///体重
+    var weight:String = ""
+    /// 偏好
+    var preference:String = ""
+    
     
     var cacheCountryName:String{
         for item in LoginVM.shared.countryList {
index 72b217c..d9ca19e 100644 (file)
@@ -21,10 +21,6 @@ class UserModel {
         if let cache = UserCache.shared.get(){
             self.info = cache
         }
-        
-        if self.token != nil {
-            tokenIsValid()
-        }
     }
     
     var storageSize = 0
@@ -72,6 +68,38 @@ extension UserModel{
             
         }
     }
+    func getUserInfo(finished: ((Bool) -> Void)? = nil){
+        if CCDevice.isJoy {
+            HttpClient.request(CommomApi.getUserInfo) { [weak self](model:UserInfoRoot,res) in
+                guard let self = self else{return}
+                if model.isSuccess{
+                    self.info = model.data
+                    UserCache.shared.save(self.info)
+                    finished?(true)
+                }
+                else{
+                    if let dict = YLToos.stringToJson(res),let code = dict["code"] as? Int{
+                        if code == 50000{
+                            logout()
+                        }
+                        else if code == 50022{
+                            if let vc = App.shared.topVC() as? BindingPhoneVC{
+                                
+                            }
+                            else{
+                                App.shared.goToPage(BindingPhoneVC())
+                            }
+                        }
+                    }
+                    finished?(false)
+                }
+                
+            }
+        }
+        else{
+            tokenIsValid(finished: finished)
+        }
+    }
     
     func getStorageSize(completion:@escaping (_ result:CommonDataIntModel) ->Void){
         HttpClient.request(.storageSize) { [weak self](result:CommonDataIntModel,res) in
index 977eae8..76b0ce5 100644 (file)
@@ -31,6 +31,7 @@ class AppLaunch:NSObject{
     }
     static func loadCache(){
         if CacheManager.shared.user.isLogin {
+            CacheManager.shared.user.tokenIsValid()
             App.shared.didLogin()
         }
         else{
index 9000a42..740b4d9 100644 (file)
@@ -19,7 +19,7 @@ class App{
     }
 
     func willLogin(){
-        CacheManager.shared.user.tokenIsValid {[weak self] success in
+        CacheManager.shared.user.getUserInfo {[weak self] success in
             guard let self = self else{return}
             if success {
                 didLogin()
index e4b59b1..fd80973 100644 (file)
@@ -19,8 +19,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
         App.shared.window = window
         AppLaunch.start()
 //        MapManager.shared.setupSdk()
-//        window?.rootViewController = UINavigationController(rootViewController: SportingVC())
-        
+//        window?.rootViewController = UINavigationController(rootViewController: CreateGroupVC())
+//        
     }
 
     func sceneDidDisconnect(_ scene: UIScene) {
index b2d414b..0f24292 100644 (file)
@@ -90,7 +90,7 @@ class HomeDeviceVC:BaseVC{
                 self?.startConectBle(model)
             }
         }
-        CacheManager.shared.user.tokenIsValid(){[weak self] sucess in
+        CacheManager.shared.user.getUserInfo{[weak self] sucess in
             self?.collectionView.reloadData()
         }
     }
index a89ee81..ab99e56 100644 (file)
@@ -109,7 +109,7 @@ extension CCBleManager:CBCentralManagerDelegate{
         conetedFailureCallback?(connectPeripheral!)
     }
     func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
-        Logger.debug("蓝牙已断开 \(peripheral)")
+        Logger.debug("蓝牙已断开 \(peripheral)",error?.localizedDescription ?? "",error.debugDescription)
         YLprogressHUD.showAutoHiden("蓝牙已断开".l10n)
         self.isConnetd = false
         if CCDevice.isJoy{
index 52dcfb3..7feb772 100644 (file)
@@ -5,41 +5,37 @@
 //  Created by liangshi on 2026/1/28.
 //
 
-class CCConfig{
-    static var appLanguage = AppSupportLanguage.english
-    
-    static let wxAppID = "wxd9d677e0024caa90"
-    static let wxUniversalLink = "https://dc-cloud-pub.tos-cn-guangzhou.volces.com/app/"
-    static let appStoreLink = "https://itunes.apple.com/cn/app/6752551504?mt=8"
-    /// 版本检测
-    static let appStoreVersionURL = "https://itunes.apple.com/cn/lookup?id=6752551504"
-    
-    /// 服务器地址
-    //static let baseURL = "http://118.145.178.188:32000"
-    static let baseURL = "https://app-api.deepchords.com"
-    //海外版
-    //    static let baseURL = "https://app-api.deepchords-ai.com"
-    
-    /// 用户隐私协议地址
-    static let yonghuBaseURL = "https://pub-tos.deepchords.com"
-}
-
-
-
 
 //class CCConfig{
 //    static var appLanguage = AppSupportLanguage.english
-//
+//    
 //    static let wxAppID = "wxeb3291e720293abc"
 //    static let wxUniversalLink = "https://www.playboykq.com/app/"
 //    static let appStoreLink = "https://itunes.apple.com/cn/app/6757697090?mt=8"
 //    /// 版本检测
 //    static let appStoreVersionURL = "https://itunes.apple.com/cn/lookup?id=6757697090"
-//
+//    
 //    /// 服务器地址
-//    static let baseURL = "https://app-api.playboykq.com"
-//
+//    static let baseURL = "https://app-api.deepchords.com"
+//    
 //    /// 用户隐私协议地址
 //    static let yonghuBaseURL = "https://pub-cdn.playboykq.com"
-//
+//    
 //}
+
+class CCConfig{
+    static var appLanguage = AppSupportLanguage.english
+
+    static let wxAppID = "wxeb3291e720293abc"
+    static let wxUniversalLink = "https://www.playboykq.com/app/"
+    static let appStoreLink = "https://itunes.apple.com/cn/app/6757697090?mt=8"
+    /// 版本检测
+    static let appStoreVersionURL = "https://itunes.apple.com/cn/lookup?id=6757697090"
+
+    /// 服务器地址
+    static let baseURL = "https://app-api.playboykq.com"
+
+    /// 用户隐私协议地址
+    static let yonghuBaseURL = "https://pub-cdn.playboykq.com"
+
+}
index 2364006..03dc84d 100644 (file)
@@ -103,7 +103,7 @@ class HomeDeviceVC:BaseVC{
                 self?.startConectBle(model)
             }
         }
-        CacheManager.shared.user.tokenIsValid(){[weak self] sucess in
+        CacheManager.shared.user.getUserInfo(){[weak self] sucess in
             self?.collectionView.reloadData()
         }
     }
index f61e054..8735333 100644 (file)
@@ -9,7 +9,7 @@ import Foundation
 
 /// 日记管理
 class Logger {
-    static var isDebug: Bool = false
+    static var isDebug: Bool = true
     
     fileprivate static let shared = Logger()
     private var fileHandle:FileHandle?
index f2105fd..c2d9684 100644 (file)
@@ -21,6 +21,8 @@ class BaseTC:UITabBarController{
     func setupUI(){
         if CCDevice.isJoy{
             let homeVC = HomeDeviceVC()
+//            let homeVC = SportHomeVC()
+
             let modeVC = ModeVC()
             let sleepVC = SleepVC()
             let mineVC = MineVC()
index 8116b4b..907fdaf 100644 (file)
@@ -39,7 +39,7 @@ class AccountSetVC: BaseVC{
     }
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
-        CacheManager.shared.user.tokenIsValid(){[weak self] sucess in
+        CacheManager.shared.user.getUserInfo{[weak self] sucess in
             self?.header.updateUI()
         }
     }
index b0a1e88..6763925 100644 (file)
@@ -95,7 +95,7 @@ class MineUserInfoView: BaseView {
         }
     }
     func updateUI(){
-        CacheManager.shared.user.tokenIsValid(){[weak self] sucess in
+        CacheManager.shared.user.getUserInfo{[weak self] sucess in
             guard let self = self else {return}
             titleLabel.text = CacheManager.shared.user.info.userName
             icon.kf.setImage(with:CacheManager.shared.user.info.avatar.yc.asUrl )
index 4f5b527..a50cd1d 100644 (file)
@@ -50,11 +50,11 @@ class UserInfoCell: BaseTableViewCell {
             titleLabel.text = type.title
             valueIcon.isHidden = type != .avatar
             
-            if type == .nickName || type == .gender || type == .area {
-                valueLabel.isHidden = false
+            if type == .avatar  {
+                valueLabel.isHidden = true
             }
             else{
-                valueLabel.isHidden = true
+                valueLabel.isHidden = false
             }
             let info = CacheManager.shared.user.info
             if type == .nickName {
@@ -68,6 +68,18 @@ class UserInfoCell: BaseTableViewCell {
                 //                valueLabel.text = info.countryName
                 valueLabel.text = info.cacheCountryName
             }
+            else if type == .birthday {
+                valueLabel.text = info.birthday
+            }
+            else if type == .height {
+                valueLabel.text = info.tall + "cm"
+            }
+            else if type == .weight {
+                valueLabel.text = info.weight + "kg"
+            }
+            else if type == .hobbies {
+                valueLabel.text = info.preference
+            }
             else if type == .avatar{
                 valueIcon.kf.setImage(with:CacheManager.shared.user.info.avatar.yc.asUrl )
             }
index 45e7ad0..4c05333 100644 (file)
@@ -103,9 +103,14 @@ extension UserInfoVC{
         let v = CustomPicker3(title: "日期".l10n)
 //        v.selectedIndex = 50
         v.show()
-        v.didSelected = {[weak self] (date) in
+        v.didSelected = {[weak self] (value) in
             guard let self = self else { return  }
-            
+            CacheManager.shared.user.info.birthday = value.format(.short)
+//            CacheManager.shared.user.info.birthday = "\(Int(value.timeIntervalSince1970))"
+
+            var params:[String:Any] = [:]
+            params["birthday"] = CacheManager.shared.user.info.birthday
+            uploadUserData(params)
         }
     }
     func heightAction(){
@@ -115,7 +120,10 @@ extension UserInfoVC{
         v.show()
         v.didSelected = {[weak self] (index,value) in
             guard let self = self else { return  }
-
+            CacheManager.shared.user.info.tall = String(value.prefix(value.count - 2))
+            var params:[String:Any] = [:]
+            params["tall"] = CacheManager.shared.user.info.tall
+            uploadUserData(params)
         }
     }
     func weightAction(){
@@ -125,7 +133,10 @@ extension UserInfoVC{
         v.show()
         v.didSelected = {[weak self] (index,value) in
             guard let self = self else { return  }
-            
+            CacheManager.shared.user.info.weight = String(value.prefix(value.count - 2))
+            var params:[String:Any] = [:]
+            params["weight"] = CacheManager.shared.user.info.weight
+            uploadUserData(params)
         }
     }
     func hobiesAction(){
@@ -135,7 +146,10 @@ extension UserInfoVC{
         v.show()
         v.didSelected = {[weak self] (index,value) in
             guard let self = self else { return  }
-            
+            CacheManager.shared.user.info.preference = value
+            var params:[String:Any] = [:]
+            params["preference"] = CacheManager.shared.user.info.preference
+            uploadUserData(params)
         }
     }
     func genderAction(){
@@ -217,7 +231,7 @@ extension UserInfoVC{
         }
     }
     func refreshUI(){
-        CacheManager.shared.user.tokenIsValid(){ [weak self] success in
+        CacheManager.shared.user.getUserInfo{ [weak self] success in
             self?.tableView.reloadData()
         }
         LoginVM.fetchCountryList {[weak self] result in
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/AddGroupHeader.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/AddGroupHeader.swift
new file mode 100644 (file)
index 0000000..f9912ab
--- /dev/null
@@ -0,0 +1,40 @@
+//
+//  AddGroupHeader.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+class AddGroupHeader: BaseView {
+    let icon = UIImageView()
+    let titleLabel = UILabel()
+    
+    override func setupViews() {
+        addSubviews([icon,titleLabel])
+        
+        titleLabel.do { v in
+            v.textColor = .color(.secondary)
+            v.font = .regular(10)
+            v.text = "设置团队头像".l10n
+        }
+
+        icon.do { v in
+            v.image = UIImage(named: "group_avatar")
+            yc.setCornerRadius(12)
+
+        }
+    }
+    
+    override func setupLayout() {
+        icon.snp.makeConstraints { make in
+            make.size.equalTo(90)
+            make.centerX.equalToSuperview()
+            make.top.equalToSuperview()
+        }
+        titleLabel.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.top.equalTo(icon.snp.bottom).offset(6)
+        }
+
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/CreateGroupVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/CreateGroupVC.swift
new file mode 100644 (file)
index 0000000..d381349
--- /dev/null
@@ -0,0 +1,134 @@
+//
+//  CreateGroupVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/5.
+//
+
+import UIKit
+
+class CreateGroupVC: BaseVC{
+    let headerView = AddGroupHeader()
+    let nameView = SportInputItem()
+    let typeView = SportSelectItem()
+    let desView = SportInputItem()
+    let lightView = SportSelectItem()
+    let verifyView = SportSwitchItem()
+    let okBtn = CustomButton()
+    var sportType:SportType = .walk
+    
+    override func setupViews() {
+        navBar.do { v in
+            v.title = "创建团队".l10n
+        }
+        view.addSubviews([headerView,nameView,typeView,desView,lightView,verifyView,okBtn])
+        nameView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "团队名称".l10n
+            v.textField.text = "111"
+            v.textField.attributedPlaceholder = NSAttributedString(string: "给团队起个名字".l10n, attributes: [NSAttributedString.Key.foregroundColor: UIColor.color(.placeholder)])
+
+        }
+        typeView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "团队类型".l10n
+            v.detailLabel.text = sportType.name
+            v.yc.addTap(target: self, action: #selector(typeAction))
+        }
+        desView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "简介".l10n
+            v.textField.attributedPlaceholder = NSAttributedString(string: "描述一下您的团".l10n, attributes: [NSAttributedString.Key.foregroundColor: UIColor.color(.placeholder)])
+        }
+        lightView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "灯带设置".l10n
+            v.yc.addTap(target: self, action: #selector(lightAction))
+
+        }
+        verifyView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "加入验证".l10n
+            v.detailLabel.text = "开启后,成员需要申请才能加入".l10n
+        }
+        okBtn.set(title: "完成创建".l10n,style: .theme1, target: self, action: #selector(okAction))
+    }
+    override func setupLayout() {
+        headerView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.top.equalToSuperview().inset(kNavBtm + 20)
+            make.height.equalTo(120)
+        }
+        nameView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(headerView.snp.bottom).offset(10)
+            make.height.equalTo(51)
+        }
+        typeView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(nameView.snp.bottom).offset(10)
+            make.height.equalTo(51)
+        }
+        desView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(typeView.snp.bottom).offset(10)
+            make.height.equalTo(65)
+        }
+        lightView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(desView.snp.bottom).offset(10)
+            make.height.equalTo(51)
+        }
+        verifyView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(lightView.snp.bottom).offset(10)
+            make.height.equalTo(65)
+        }
+        okBtn.snp.makeConstraints { make in
+            make.bottom.equalToSuperview().inset(80)
+            make.left.right.equalToSuperview().inset(51)
+            make.height.equalTo(46)
+        }
+    }
+    @objc func typeAction(){
+        let vc = GroupTypeVC()
+        vc.didSelected = {[weak self] value in
+            self?.sportType = value
+            self?.typeView.detailLabel.text = value.name
+        }
+        App.shared.goToPage(vc)
+    }
+    @objc func lightAction(){
+        App.shared.goToPage(LightSetVC())
+    }
+    @objc func okAction(){
+        if nameView.isEmpty  {
+            YLprogressHUD.showAutoHiden("团队名称不能为空".l10n)
+            return
+        }
+        
+        YLprogressHUD.showLoading()
+        var params:[String:Any] = [:]
+        // 团队名称,必须
+        params["name"] = nameView.value
+        // 头像
+//        params["icon"] = ""
+        // 运动类型:running | cycling | walking,必须
+        params["type"] = sportType.rawValue
+        // 团队简介,非必须
+//        params["introduction"] = ""
+        // 1加入审核,0不需要审核,非必须,默认0
+        params["joinReview"] = verifyView.iSwitch.isOn ? "1":"0"
+        let api =  CommomApi.createSportGroup(param: params)
+        HttpClient.request(api){ (model:ResponseBaseModel, res) in
+            
+            if model.isSuccess{
+                YLprogressHUD.hidden()
+            }
+            else{
+                YLprogressHUD.showAutoHiden("请求失败".l10n)
+            }
+        }
+    }
+}
+
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportInputItem.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportInputItem.swift
new file mode 100644 (file)
index 0000000..4c10566
--- /dev/null
@@ -0,0 +1,136 @@
+//
+//  SportInputItem.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+class SportInputItem: BaseView,UITextFieldDelegate {
+    let valueLabel = UILabel()
+    let textField = UITextField()
+    let titleLabel = UILabel()
+    var maxLength = 10
+    
+    var isEmpty:Bool{
+        if let text = textField.text,text.isNotEmpty {
+            return false
+        }
+        return true
+    }
+    var value:String{
+        return textField.text ?? ""
+    }
+    
+    override func setupViews() {
+        yc.setCornerRadius(12)
+        addSubviews([valueLabel,titleLabel,textField])
+        
+        titleLabel.do { v in
+            v.textColor = .color(.first)
+            v.font = .medium(14)
+        }
+        textField.do { v in
+            v.textColor = .color(.first)
+            v.keyboardType = .default
+            v.returnKeyType = .done
+            v.textAlignment = .left
+            v.addTarget(self, action: #selector(textFieldValueChange), for: .valueChanged)
+//            v.backgroundColor = .red
+            v.delegate = self
+        }
+        valueLabel.do { v in
+            v.textColor = .color(.placeholder)
+            v.font = .regular(10)
+            v.textAlignment = .right
+            v.text = "0/\(maxLength)"
+        }
+        backgroundColor = .white
+    }
+    
+    override func setupLayout() {
+        
+        titleLabel.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.left.equalToSuperview().inset(14)
+        }
+        textField.snp.makeConstraints { make in
+            make.left.equalTo(titleLabel.snp.right).offset(10).priority(.high)
+            make.centerY.height.equalToSuperview()
+            make.right.equalToSuperview().inset(50).priority(.low)
+        }
+        valueLabel.snp.makeConstraints { make in
+            make.width.equalTo(38)
+            make.height.equalToSuperview()
+            make.centerY.equalToSuperview()
+            make.right.equalToSuperview().inset(12)
+        }
+    }
+    @objc func textFieldValueChange(){
+        valueLabel.text = "\(textField.text?.count ?? 0)/\(maxLength)"
+    }
+    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+        textField.resignFirstResponder()
+        return false
+    }
+}
+
+class SportTextViewItem: BaseView,UITextViewDelegate {
+    let valueLabel = UILabel()
+    let textView = UITextView()
+    let titleLabel = UILabel()
+    var maxLength = 10
+    
+    override func setupViews() {
+        yc.setCornerRadius(12)
+        addSubviews([valueLabel,titleLabel,textView])
+        
+        titleLabel.do { v in
+            v.textColor = .color(.first)
+            v.font = .medium(14)
+            v.text = "简介".l10n
+        }
+        textView.do { v in
+            v.textColor = .color(.first)
+            v.keyboardType = .default
+            v.returnKeyType = .done
+            v.textAlignment = .left
+            v.delegate = self
+        }
+        valueLabel.do { v in
+            v.textColor = .color(.placeholder)
+            v.font = .regular(10)
+            v.textAlignment = .right
+            v.text = "0/\(maxLength)"
+        }
+        backgroundColor = .white
+    }
+    
+    override func setupLayout() {
+        
+        titleLabel.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.left.equalToSuperview().inset(14)
+        }
+        textView.snp.makeConstraints { make in
+            make.left.equalTo(titleLabel.snp.right).offset(10).priority(.high)
+            make.centerY.height.equalToSuperview()
+            make.right.equalToSuperview().inset(50).priority(.low)
+        }
+        valueLabel.snp.makeConstraints { make in
+            make.width.equalTo(38)
+            make.height.equalToSuperview()
+            make.centerY.equalToSuperview()
+            make.right.equalToSuperview().inset(12)
+        }
+    }
+    
+    func textViewDidChange(_ textView: UITextView) {
+        valueLabel.text = "\(textView.text?.count ?? 0)/\(maxLength)"
+    }
+
+    func textView(_ textView: UITextView, shouldChangeTextInRanges ranges: [NSValue], replacementText text: String) -> Bool {
+        textView.resignFirstResponder()
+        
+        return false
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSelectItem.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSelectItem.swift
new file mode 100644 (file)
index 0000000..51d8041
--- /dev/null
@@ -0,0 +1,48 @@
+//
+//  SportItem.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+class SportSelectItem: BaseView {
+    let icon = UIImageView()
+    let detailLabel = UILabel()
+    let titleLabel = UILabel()
+    
+    override func setupViews() {
+        yc.setCornerRadius(12)
+        addSubviews([icon,titleLabel,detailLabel])
+        
+        titleLabel.do { v in
+            v.textColor = .color(.first)
+            v.font = .medium(14)
+        }
+        detailLabel.do { v in
+            v.textColor = .color(.secondary)
+            v.font = .regular(12)
+        }
+        icon.do { v in
+            v.image = UIImage(named: "arrow_2")
+        }
+        backgroundColor = .white
+    }
+    
+    override func setupLayout() {
+        
+        titleLabel.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.left.equalToSuperview().inset(14)
+        }
+        detailLabel.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.right.equalToSuperview().inset(27)
+        }
+        icon.snp.makeConstraints { make in
+            make.width.equalTo(7)
+            make.height.equalTo(13)
+            make.centerY.equalToSuperview()
+            make.right.equalToSuperview().inset(12)
+        }
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSwitchItem.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Create/SportSwitchItem.swift
new file mode 100644 (file)
index 0000000..4f5423a
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  SportSwitchItem.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+class SportSwitchItem: BaseTableViewCell {
+    let titleLabel = UILabel()
+    let detailLabel = UILabel()
+    let iSwitch = UISwitch()
+  
+
+    override func setupViews() {
+        addSubviews([titleLabel,detailLabel,iSwitch])
+        
+        backgroundColor = .color(.cellBg)
+        titleLabel.do { (v) in
+            v.textColor = .color(.first)
+            v.font = .bold(14)
+            v.textAlignment = .left
+        }
+        detailLabel.do { (v) in
+            v.textColor = .color(.secondary)
+            v.font = .regular(10)
+            v.textAlignment = .left
+        }
+        iSwitch.do { v in
+            v.addTarget(self, action: #selector(swicthAction), for: .valueChanged)
+        }
+    }
+    
+    override func setupLayout() {
+        titleLabel.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(16)
+            m.left.equalToSuperview().offset(16)
+        }
+        detailLabel.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(16)
+            m.left.equalToSuperview().offset(16)
+        }
+        iSwitch.snp.makeConstraints { (m) in
+            m.right.equalToSuperview().inset(15)
+            m.centerY.equalToSuperview()
+        }
+    }
+
+  
+    @objc func swicthAction(){
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupCell.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupCell.swift
new file mode 100644 (file)
index 0000000..3174168
--- /dev/null
@@ -0,0 +1,90 @@
+//
+//  MyGroupCell.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+ class MyGroupCell: BaseTableViewCell {
+    let bgView = UIView()
+    let icon = UIImageView()
+    let nameLabel = UILabel()
+    let contentLabel = UILabel()
+    
+    var model:MyGroupModel!{
+        didSet{
+            if model.icon.isEmpty{
+                icon.image = UIImage(named: "group_avatar")
+            }
+            else{
+                icon.kf.setImage(with: model.icon.yc.asUrl)
+            }
+            nameLabel.text =  model.name
+            contentLabel.text = model.type.name + ".\(model.userCount)" + "人已加入".l10n
+        }
+    }
+    
+    
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    override func setupViews() {
+        contentView.addSubview(bgView)
+        bgView.addSubviews([icon,nameLabel,contentLabel])
+        
+        backgroundColor = .color(.bgColor)
+        contentView.backgroundColor = .clear
+        selectionStyle = .none
+        bgView.do { v in
+            v.backgroundColor = .color(.cellBg)
+            v.yc.setCornerRadius(8)
+        }
+        nameLabel.do { (v) in
+            v.textColor = .color(.first)
+            v.font = .medium(14)
+            v.textAlignment = .left
+            v.lineBreakMode = .byTruncatingTail
+        }
+        contentLabel.do { v in
+            v.textColor = .color(.secondary)
+            v.font = .regular(11)
+            v.textAlignment = .left
+            v.lineBreakMode = .byTruncatingTail
+        }
+
+        icon.do { v in
+            v.yc.setCornerRadius(8)
+        }
+    }
+    
+    override func setupLayout() {
+        bgView.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview().inset(18)
+            m.top.equalToSuperview().inset(6)
+            m.bottom.equalToSuperview()
+        }
+        
+        icon.snp.makeConstraints { (m) in
+            m.size.equalTo(36)
+            m.left.equalToSuperview().inset(15)
+            m.top.equalToSuperview().inset(15)
+        }
+        nameLabel.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(16)
+            m.left.equalToSuperview().offset(60)
+            m.right.lessThanOrEqualToSuperview().inset(16)
+        }
+        contentLabel.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(16)
+            m.left.equalToSuperview().offset(60)
+            m.right.lessThanOrEqualToSuperview().inset(16)
+        }
+
+    }
+    
+    
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupModel.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupModel.swift
new file mode 100644 (file)
index 0000000..703df34
--- /dev/null
@@ -0,0 +1,31 @@
+//
+//  Untitled.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+import HandyJSON
+
+class MyGroupModelRoot:ResponseBaseModel {
+    var data = [MyGroupModel]()
+}
+
+class MyGroupModel:HandyJSON {
+    var id = "" // 团队ID
+    var userId = ""// 用户ID,创建者的ID
+    var creatorNickname = "" // 创建者昵称
+    var creatorAvatar = "" // https://example.com/avatar.jpg", // 创建者头像
+    var icon = "" // https://example.com/icon.jpg", // 图标
+    var state = "" // 状态:1正常,0解散
+    var name = "" // 团队名称
+    var type:SportType = SportType.walk // 运动类型:running | cycling | walking
+    var introduction = "" // 团队简介
+    var joinReview = ""// 1加入审核,0不需要审核
+    var userCount = 0 //加入人数
+    var totalDistance = "" // 总距离,单位米
+    var totalTime = "" // 总运动时长,单位秒
+    var createTime = "" // 创建时间
+    var updateTime = ""// 更新时间
+    required public init() { }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupVC.swift
new file mode 100644 (file)
index 0000000..7b3f120
--- /dev/null
@@ -0,0 +1,115 @@
+//
+//  MyGroupVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+import JXSegmentedView
+
+
+enum MyGroupType{
+    case create
+    case add
+    
+    var name:String{
+        switch self {
+        case .create:
+            return "我管理的"
+        case .add:
+            return "我加入的"
+        }
+    }
+    var value:String{
+        switch self {
+        case .create:
+            return "1"
+        case .add:
+            return "0"
+        }
+    }
+    static var all:[MyGroupType] = [.create,.add]
+}
+
+class MyGroupVC: BaseVC {
+    private let segmentedDataSource = JXSegmentedTitleDataSource()
+    private let segmentedView = JXSegmentedView()
+    private lazy var listContainerView: JXSegmentedListContainerView! = {
+        let view = JXSegmentedListContainerView(dataSource: self, type: .scrollView)
+        return view
+    }()
+    
+    var list:[MyGroupType] = MyGroupType.all
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+        //        AudioPlayView.shared.show()
+        self.view.addSubview(AudioPlayView.shared)
+        MapManager.shared.setupSdk()
+    }
+    
+    override func setupLayout(){
+        
+        segmentedView.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview()
+            m.height.equalTo(44.fitR)
+            m.top.equalToSuperview().inset(kNavBtm)
+        }
+        listContainerView.snp.makeConstraints { (m) in
+            m.width.left.equalToSuperview()
+            m.top.equalTo(segmentedView.snp.bottom)
+            m.bottom.equalToSuperview()
+        }
+    }
+    override func setupViews(){
+        view.addSubview(segmentedView)
+        view.addSubview(listContainerView)
+        
+        view.backgroundColor = .color(.bgColor)
+        segmentedView.do { (v) in
+            segmentedDataSource.titleNormalColor = .color(.secondary)
+            segmentedDataSource.titleSelectedColor = .color(.first)
+            segmentedDataSource.titleNormalFont = .regular(14)
+            segmentedDataSource.titleSelectedFont = .bold(16)
+            segmentedDataSource.isTitleZoomEnabled = true
+            // segmentedDataSource.titleSelectedZoomScale = 1
+            segmentedDataSource.isTitleStrokeWidthEnabled = true
+            segmentedDataSource.isItemSpacingAverageEnabled = true
+            segmentedDataSource.isTitleColorGradientEnabled = true
+            segmentedDataSource.titles = list.map{"\($0.name)"}
+            segmentedView.backgroundColor = .clear
+            
+            //配置指示器
+            let indicator = JXSegmentedIndicatorLineView()
+            indicator.indicatorWidth = 20
+            indicator.indicatorHeight = 4
+            indicator.verticalOffset = 6
+            indicator.indicatorColor = .color(.theme)
+            segmentedView.indicators = [indicator]
+            
+            v.dataSource = segmentedDataSource
+            v.listContainer = listContainerView
+        }
+    }
+}
+
+extension MyGroupVC: JXSegmentedListContainerViewListDelegate {
+    func listView() -> UIView {
+        return view
+    }
+}
+
+extension MyGroupVC: JXSegmentedListContainerViewDataSource {
+    func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int {
+        if let titleDataSource = segmentedView.dataSource as? JXSegmentedBaseDataSource {
+            return titleDataSource.dataSource.count
+        }
+        return 0
+    }
+    
+    func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate {
+        let type = list[index]
+        return MyGroupView(selectType: type)
+        
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupView.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/MyGroup/MyGroupView.swift
new file mode 100644 (file)
index 0000000..9cbc484
--- /dev/null
@@ -0,0 +1,82 @@
+//
+//  GroupListView.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+import UIKit
+import JXSegmentedView
+import MJRefresh
+
+
+class MyGroupView: BaseView,UITableViewDelegate,UITableViewDataSource {
+    let tableView = UITableView(frame: .zero, style: .plain)
+    var list = [MyGroupModel]()
+    var type = MyGroupType.add
+    
+    init(selectType type:MyGroupType){
+        super.init(frame: .zero)
+        self.type = type
+        tableView.mj_header?.beginRefreshing()
+    }
+    
+    override func setupViews() {
+        addSubview(tableView)
+        tableView.do { v in
+            v.backgroundColor = .color(.bgColor)
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 74
+            v.separatorStyle = .none
+            v.register(MyGroupCell.self, forCellReuseIdentifier: MyGroupCell.reuseID)
+            v.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(refreshAction))
+        }
+    }
+    
+    override func setupLayout() {
+        tableView.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(10)
+            m.left.right.bottom.equalToSuperview()
+        }
+    }
+    
+    @objc func refreshAction(){
+        var params:[String:Any] = [:]
+        params["type"] = type.value
+        
+        let api = CommomApi.getSportGroupList(param: params)
+        HttpClient.request(api) {[weak self] (model:MyGroupModelRoot,res) in
+            guard let self = self else {return}
+            if model.isSuccess{
+                list = model.data
+            }
+            tableView.reloadData()
+            tableView.mj_header?.endRefreshing()
+        }
+
+    }
+
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+            return list.count
+        }
+        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+            let cell = MyGroupCell.cell(withTableView: tableView, indexPath: indexPath)
+            cell.model = list[indexPath.row]
+            return cell
+        }
+        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        }
+
+}
+
+extension MyGroupView: JXSegmentedListContainerViewListDelegate {
+    func listView() -> UIView {
+        return self
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupRoleVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupRoleVC.swift
new file mode 100644 (file)
index 0000000..d3b91e0
--- /dev/null
@@ -0,0 +1,144 @@
+import UIKit
+import HandyJSON
+
+enum GroupRoleType:String,HandyJSONEnum{
+    case none = "none"
+    case pfs = "pfs"
+    case lpz = "lpz"
+    case gpz = "gpz"
+    case ccs = "ccs"
+    case psy = "psy"
+    case bjy = "bjy"
+    case qns = "qns"
+    case lqz = "lqz"
+    case gqz = "gqz"
+    case pps = "pps"
+    
+    
+    var name:String{
+        switch self {
+        case .none:
+            return "无"
+        case .pfs:
+            return "破风手"
+        case .lpz:
+            return "领跑者"
+        case .gpz:
+            return "跟跑者"
+        case .ccs:
+            return "冲刺手"
+        case .psy:
+            return "配速员"
+        case .bjy:
+            return "补给员"
+        case .qns:
+            return "全能手"
+        case .lqz:
+            return "领骑者"
+        case .gqz:
+            return "跟骑者"
+        case .pps:
+            return "爬坡手"
+        }
+    }
+    var color:UIColor{
+        switch self {
+        case .none:
+            return .red
+        case .pfs:
+            return .red
+        case .lpz:
+            return .red
+        case .gpz:
+            return .red
+        case .ccs:
+            return .red
+        case .psy:
+            return .red
+        case .bjy:
+            return .red
+        case .qns:
+            return .red
+        case .lqz:
+            return .red
+        case .gqz:
+            return .red
+        case .pps:
+            return .red
+        }
+    }
+    
+    static var all:[GroupRoleType] = [.none,.pfs,.lpz,.gpz,.ccs,.psy,.bjy,.qns]
+}
+
+class GroupRoleVC: BaseVC{
+    let tableView = UITableView(frame: .zero, style: .plain)
+    var list:[GroupRoleType] = GroupRoleType.all
+    var currentType = GroupRoleType.none
+    let btn = CustomButton()
+    var didSelected:((GroupRoleType)->Void)?
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+    override func setupViews() {
+        self.navBar.title = "团队类型".l10n
+        tableView.do { v in
+            v.backgroundColor = .color(.bgColor)
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 52
+            v.separatorStyle = .none
+            v.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)
+            v.register(SelectCell.self, forCellReuseIdentifier: SelectCell.reuseID)
+        }
+        view.addSubviews([tableView,btn])
+        
+        btn.set(title: "确定".l10n, target: self, action: #selector(btnAction))
+    }
+    override func setupLayout() {
+        tableView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.top.equalTo(kNavBtm)
+        }
+        btn.snp.makeConstraints { make in
+            make.width.equalTo(272)
+            make.height.equalTo(46)
+            make.centerX.equalToSuperview()
+            make.bottom.equalToSuperview().inset(82)
+        }
+    }
+    @objc func btnAction(){
+        didSelected?(currentType)
+        self.navigationController?.popViewController(animated: true)
+    }
+}
+
+extension GroupRoleVC:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = SelectCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.titleLabel.text = list[indexPath.row].name
+        let rect = CGRect(x: 0, y: 0, width: kScreenWid - 36, height: 52)
+        if indexPath.row == 0 {
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 8, height: 8))
+        }
+        else if indexPath.row == list.count - 1{
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: 8, height: 8))
+        }
+        else{
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.allCorners], cornerRadii: CGSize(width: 0, height: 0))
+        }
+        cell.selectedIcon.isHidden =  list[indexPath.row] != currentType
+        return cell
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let data = list[indexPath.row]
+        currentType = data
+        tableView.reloadData()
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupTypeVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/Other/GroupTypeVC.swift
new file mode 100644 (file)
index 0000000..bb7a0e6
--- /dev/null
@@ -0,0 +1,80 @@
+//
+//  GroupTypeVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+import UIKit
+
+class GroupTypeVC: BaseVC{
+    let tableView = UITableView(frame: .zero, style: .plain)
+    var list:[SportType] = SportType.all
+    var currentType = SportType.walk
+    let btn = CustomButton()
+    var didSelected:((SportType)->Void)?
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+    override func setupViews() {
+        self.navBar.title = "团队类型".l10n
+        tableView.do { v in
+            v.backgroundColor = .color(.bgColor)
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 52
+            v.separatorStyle = .none
+            v.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)
+            v.register(SelectCell.self, forCellReuseIdentifier: SelectCell.reuseID)
+        }
+        view.addSubviews([tableView,btn])
+        
+        btn.set(title: "确定".l10n, target: self, action: #selector(btnAction))
+    }
+    override func setupLayout() {
+        tableView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.top.equalTo(kNavBtm)
+        }
+        btn.snp.makeConstraints { make in
+            make.width.equalTo(272)
+            make.height.equalTo(46)
+            make.centerX.equalToSuperview()
+            make.bottom.equalToSuperview().inset(82)
+        }
+    }
+    @objc func btnAction(){
+        didSelected?(currentType)
+        self.navigationController?.popViewController(animated: true)
+    }
+}
+
+extension GroupTypeVC:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = SelectCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.titleLabel.text = list[indexPath.row].name
+        let rect = CGRect(x: 0, y: 0, width: kScreenWid - 36, height: 52)
+        if indexPath.row == 0 {
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 8, height: 8))
+        }
+        else if indexPath.row == list.count - 1{
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: 8, height: 8))
+        }
+        else{
+            cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.allCorners], cornerRadii: CGSize(width: 0, height: 0))
+        }
+        cell.selectedIcon.isHidden =  list[indexPath.row] != currentType
+        return cell
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let data = list[indexPath.row]
+        currentType = data
+        tableView.reloadData()
+    }
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/Group/add/AddGroupVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/Group/add/AddGroupVC.swift
new file mode 100644 (file)
index 0000000..89046c7
--- /dev/null
@@ -0,0 +1,98 @@
+//
+//  AddGrpupVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/6.
+//
+
+import UIKit
+
+class AddGroupVC: BaseVC{
+    let nameView = SportInputItem()
+    let typeView = SportSelectItem()
+    let desView = SportInputItem()
+    let okBtn = CustomButton()
+    var sportType:GroupRoleType = .none
+    
+    override func setupViews() {
+        navBar.do { v in
+            v.title = "加入团队".l10n
+        }
+        view.addSubviews([nameView,typeView,desView,okBtn])
+        nameView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "团队号".l10n
+            v.textField.text = "2019706199229804545"
+            v.textField.attributedPlaceholder = NSAttributedString(string: "请输入团队号".l10n, attributes: [NSAttributedString.Key.foregroundColor: UIColor.color(.placeholder)])
+            
+        }
+        typeView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "团队角色".l10n
+            v.detailLabel.text = sportType.name
+            v.yc.addTap(target: self, action: #selector(typeAction))
+        }
+        desView.do { v in
+            v.yc.setCornerRadius(12)
+            v.titleLabel.text = "打招呼内容".l10n
+            v.textField.attributedPlaceholder = NSAttributedString(string: "描述一下您的团".l10n, attributes: [NSAttributedString.Key.foregroundColor: UIColor.color(.placeholder)])
+        }
+        okBtn.set(title: "加入".l10n,style: .theme1, target: self, action: #selector(okAction))
+    }
+    override func setupLayout() {
+        nameView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalToSuperview().inset(kNavBtm + 20)
+            make.height.equalTo(51)
+        }
+        typeView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(nameView.snp.bottom).offset(10)
+            make.height.equalTo(51)
+        }
+        desView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(18)
+            make.top.equalTo(typeView.snp.bottom).offset(10)
+            make.height.equalTo(65)
+        }
+        okBtn.snp.makeConstraints { make in
+            make.bottom.equalToSuperview().inset(80)
+            make.left.right.equalToSuperview().inset(51)
+            make.height.equalTo(46)
+        }
+    }
+    @objc func typeAction(){
+        let vc = GroupRoleVC()
+        vc.didSelected = {[weak self] value in
+            self?.sportType = value
+            self?.typeView.detailLabel.text = value.name
+        }
+        App.shared.goToPage(vc)
+    }
+    @objc func lightAction(){
+        App.shared.goToPage(LightSetVC())
+    }
+    @objc func okAction(){
+        if nameView.isEmpty  {
+            YLprogressHUD.showAutoHiden("团队名称不能为空".l10n)
+            return
+        }
+        
+        YLprogressHUD.showLoading()
+        var params:[String:Any] = [:]
+        params["id"] = nameView.value
+        params["requestText"] = desView.value
+
+        let api =  CommomApi.applyJoinGroup(param: params)
+        HttpClient.request(api){ (model:ResponseBaseModel, res) in
+            
+            if model.isSuccess{
+                YLprogressHUD.hidden()
+            }
+            else{
+                YLprogressHUD.showAutoHiden("请求失败".l10n)
+            }
+        }
+    }
+}
+
index 655cd2f..5afe77e 100644 (file)
@@ -68,7 +68,7 @@ extension ReadyVC{
         }
         @objc func skipAction(){
             timer.invalidate()
-            App.shared.goToPage(BaseVC())
+            App.shared.goToPage(SportingVC())
             removeFromSuperview()
         }
     }
index 31318c4..78b2034 100644 (file)
@@ -57,7 +57,7 @@ extension ReadyVC{
             App.shared.goToPage(SportTargetVC())
         }
         @objc func goAction(){
-            if true {
+            if false {
                 CustomAlert.showWith(title: "完善数据".l10n, messgage: "完善你的身体档案,让运动数据更准确。".l10n,ok: "前往".l10n) {
                     
                 } okCallback: {
index d09ceef..3c32ad5 100644 (file)
 
 extension SportRootView{
     class DataView: BaseView {
-        
+        let header = headItem()
+        let line = UIView()
+        let lastView = ItemView()
         
         override func setupViews() {
             backgroundColor = .color(.cellBg)
+            addSubviews([header,lastView,line])
+            line.backgroundColor = .color(.separateLine)
         }
         
         override func setupLayout() {
+            header.snp.makeConstraints { make in
+                make.left.right.top.equalToSuperview()
+                make.height.equalTo(51)
+            }
+            lastView.snp.makeConstraints { make in
+                make.left.right.bottom.equalToSuperview()
+                make.height.equalTo(72)
+            }
+            line.snp.makeConstraints { make in
+                make.left.right.equalToSuperview().inset(14)
+                make.height.equalTo(1)
+                make.bottom.equalTo(header)
+            }
+        }
+        class headItem: BaseView {
+            let icon = UIImageView()
+            let detailLabel = UILabel()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                yc.setCornerRadius(12)
+                addSubviews([icon,titleLabel,detailLabel])
+                
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .medium(14)
+                    v.text = "运动数据".l10n
+                }
+                detailLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(12)
+                    v.text = "全部".l10n
+                }
+                icon.do { v in
+                    v.image = UIImage(named: "arrow_2")
+                }
+                backgroundColor = .white
+            }
+            
+            override func setupLayout() {
+                
+                titleLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview()
+                    make.left.equalToSuperview().inset(14)
+                }
+                detailLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview()
+                    make.right.equalToSuperview().inset(27)
+                }
+                icon.snp.makeConstraints { make in
+                    make.width.equalTo(7)
+                    make.height.equalTo(13)
+                    make.centerY.equalToSuperview()
+                    make.right.equalToSuperview().inset(12)
+                }
+            }
+        }
+        
+        class ItemView: BaseView {
+            let icon = UIImageView()
+            let detailLabel = UILabel()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                yc.setCornerRadius(12)
+                addSubviews([icon,titleLabel,detailLabel])
+                
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .medium(14)
+                    v.text = "户外跑步 6.21公里"
+                }
+                detailLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(10)
+                    v.text = "30分26秒"
+                }
+                icon.do { v in
+                    v.image = UIImage(named: "add_2")
+                }
+                backgroundColor = .white
+            }
             
+            override func setupLayout() {
+                
+                titleLabel.snp.makeConstraints { make in
+                    make.top.equalToSuperview().inset(16)
+                    make.left.equalToSuperview().inset(64)
+                }
+                detailLabel.snp.makeConstraints { make in
+                    make.bottom.equalToSuperview().inset(16)
+                    make.left.equalTo(titleLabel)
+                }
+                icon.snp.makeConstraints { make in
+                    make.size.equalTo(40)
+                    make.centerY.equalToSuperview()
+                    make.left.equalToSuperview().inset(14)
+                }
+            }
         }
     }
 }
index 575d9b7..620dc8a 100644 (file)
@@ -7,14 +7,96 @@
 
 extension SportRootView{
     class GroupView: BaseView {
+        let creatGroup = ItemView()
+        let addGroup = ItemView()
+        let myGroup = ItemView()
         
+        override func setupViews() {
+            addSubviews([creatGroup,addGroup,myGroup])
+            creatGroup.do { v in
+                v.titleLabel.text = "创建团队".l10n
+                v.detailLabel.text = "创建我的团队".l10n
+                v.yc.addTap(target: self, action: #selector(creatAction))
+            }
+            addGroup.do { v in
+                v.titleLabel.text = "加入团队".l10n
+                v.detailLabel.text = "加入已创建的团队".l10n
+                v.yc.addTap(target: self, action: #selector(joinAction))
+
+            }
+            myGroup.do { v in
+                v.titleLabel.text = "我的团队".l10n
+                v.detailLabel.text = "我创建和已加入的团队".l10n
+                v.icon.isHidden = true
+                v.yc.addTap(target: self, action: #selector(myAction))
+            }
+        }
+        
+        override func setupLayout() {
+            creatGroup.snp.makeConstraints { make in
+                make.left.top.right.equalToSuperview()
+                make.height.equalTo(65)
+            }
+            addGroup.snp.makeConstraints { make in
+                make.left.bottom.equalToSuperview()
+                make.height.equalTo(65)
+                make.width.equalTo((kScreenWid - 36 - 10)/2)
+            }
+            myGroup.snp.makeConstraints { make in
+                make.right.bottom.equalToSuperview()
+                make.height.equalTo(addGroup)
+                make.left.equalTo(addGroup.snp.right).offset(10)
+            }
+        }
+        @objc func creatAction(){
+            App.shared.goToPage(CreateGroupVC())
+        }
+        @objc func joinAction(){
+            App.shared.goToPage(AddGroupVC())
+        }
+        @objc func myAction(){
+            App.shared.goToPage(MyGroupVC())
+        }
+    }
+    class ItemView: BaseView {
+        let icon = UIImageView()
+        let detailLabel = UILabel()
+        let titleLabel = UILabel()
         
         override func setupViews() {
-            backgroundColor = .color(.cellBg)
+            backgroundColor =  .color(.cellBg)
+            yc.setCornerRadius(12)
+            addSubviews([icon,titleLabel,detailLabel])
+            
+            titleLabel.do { v in
+                v.textColor = .color(.first)
+                v.font = .medium(14)
+            }
+            detailLabel.do { v in
+                v.textColor = .color(.secondary)
+                v.font = .regular(10)
+            }
+            icon.do { v in
+                v.image = UIImage(named: "add_2")
+            }
+            backgroundColor = .white
         }
         
         override func setupLayout() {
             
+            titleLabel.snp.makeConstraints { make in
+                make.top.equalToSuperview().inset(16)
+                make.left.equalToSuperview().inset(14)
+            }
+            detailLabel.snp.makeConstraints { make in
+                make.bottom.equalToSuperview().inset(16)
+                make.left.equalTo(titleLabel)
+            }
+            icon.snp.makeConstraints { make in
+                make.size.equalTo(36)
+                make.centerY.equalToSuperview()
+                make.right.equalToSuperview().inset(12)
+            }
         }
     }
 }
index 05c6339..d29ffed 100644 (file)
@@ -7,14 +7,20 @@
 
 extension SportRootView{
     class PlanView: BaseView {
-        
+        let icon = ItemView()
         
         override func setupViews() {
-            backgroundColor = .color(.cellBg)
+            addSubviews([icon])
+            icon.do { v in
+                v.titleLabel.text = "智能运动计划建议".l10n
+                v.detailLabel.text = "AI规划个人定制运动计划".l10n
+            }
         }
         
         override func setupLayout() {
-            
+            icon.snp.makeConstraints { make in
+                make.edges.equalToSuperview()
+            }
         }
     }
 }
index 245babb..dadc7a4 100644 (file)
@@ -7,14 +7,92 @@
 
 extension SportRootView{
     class RouteView: BaseView {
-        
+        let header = headItem()
+        let line = UIView()
+        let routeView1 = UIView()
+        let routeView2 = UIView()
+
         
         override func setupViews() {
             backgroundColor = .color(.cellBg)
+            addSubviews([header,routeView1,routeView2,line])
+            line.backgroundColor = .color(.separateLine)
+            
+            routeView1.do { v in
+                v.backgroundColor = .lightGray
+                v.yc.setCornerRadius(12)
+            }
+            routeView2.do { v in
+                v.backgroundColor = .lightGray
+                v.yc.setCornerRadius(12)
+            }
         }
         
         override func setupLayout() {
+            header.snp.makeConstraints { make in
+                make.left.right.top.equalToSuperview()
+                make.height.equalTo(51)
+            }
+            routeView1.snp.makeConstraints { make in
+                make.left.bottom.equalToSuperview().inset(14)
+                make.height.equalTo(96)
+                make.width.equalTo(((kScreenWid - 64 - 10)/2))
+            }
+            routeView2.snp.makeConstraints { make in
+                make.right.bottom.equalToSuperview().inset(14)
+                make.height.equalTo(96)
+                make.width.equalTo(((kScreenWid - 64 - 10)/2))
+            }
+            line.snp.makeConstraints { make in
+                make.left.right.equalToSuperview().inset(14)
+                make.height.equalTo(1)
+                make.bottom.equalTo(header)
+            }
+        }
+        class headItem: BaseView {
+            let icon = UIImageView()
+            let detailLabel = UILabel()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                yc.setCornerRadius(12)
+                addSubviews([icon,titleLabel,detailLabel])
+                
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .medium(14)
+                    v.text = "路线探索".l10n
+                }
+                detailLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(12)
+                    v.text = "全部".l10n
+                }
+                icon.do { v in
+                    v.image = UIImage(named: "arrow_2")
+                }
+                backgroundColor = .white
+            }
             
+            override func setupLayout() {
+                
+                titleLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview()
+                    make.left.equalToSuperview().inset(14)
+                }
+                detailLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview()
+                    make.right.equalToSuperview().inset(27)
+                }
+                icon.snp.makeConstraints { make in
+                    make.width.equalTo(7)
+                    make.height.equalTo(13)
+                    make.centerY.equalToSuperview()
+                    make.right.equalToSuperview().inset(12)
+                }
+            }
         }
+        
+       
     }
 }
index a6c0a71..67a3834 100644 (file)
@@ -4,12 +4,12 @@
 //
 //  Created by liangshi on 2026/1/20.
 //
+import HandyJSON
 
-
-enum SportType{
-    case run
-    case ride
-    case walk
+enum SportType:String,HandyJSONEnum{
+    case run = "running"
+    case ride = "cycling"
+    case walk = "walking"
     
     var name:String{
         switch self {
@@ -31,6 +31,7 @@ enum SportType{
             return "sport_walk"
         }
     }
+    
     static var all:[SportType] = [.run,.ride,.walk]
 }
 
@@ -92,12 +93,13 @@ class SportTypeItem: BaseView {
     var type:SportType = .run{
         didSet{
             titleLabel.text = type.name
+            icon.image = UIImage(named: type.icon)
         }
     }
     override func setupViews() {
         addSubviews([titleLabel,icon])
         icon.do { v in
-            v.image = UIImage(named: type.icon)
+            
         }
         titleLabel.do { v in
             v.textColor = .color(.first)
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailBoard.swift b/ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailBoard.swift
new file mode 100644 (file)
index 0000000..31f67d9
--- /dev/null
@@ -0,0 +1,181 @@
+////
+////  Untitled.swift
+////  ShenYin
+////
+////  Created by liangshi on 2026/2/5.
+////
+//
+import UIKit
+
+extension SportDetailVC{
+    class SportDetailBoard: BaseView {
+        let topIcon = UIImageView()
+        let header = headerItem()
+        let distanceItem = LabelItem()
+        let durationItem = LabelItem()
+        let speedItem = LabelItem()
+        let calorieItem = LabelItem()
+        let stepItem = LabelItem()
+        let okBtn = UIButton(type: .custom)
+        
+        override func setupViews() {
+            backgroundColor = .white
+            addSubviews([topIcon,header,distanceItem,durationItem,speedItem,calorieItem,stepItem,okBtn])
+            topIcon.do { v in
+                v.backgroundColor = .color(.secondary)
+                v.yc.setCornerRadius(2)
+            }
+            distanceItem.do { v in
+                v.titleLabel.text = "0"
+                v.detailLabel.text = "总距离".l10n
+            }
+            durationItem.do { v in
+                v.titleLabel.text = "00:00:00"
+                v.detailLabel.text = "总时长".l10n
+            }
+            speedItem.do { v in
+                v.titleLabel.text = "8'26\""
+                v.detailLabel.text = "配速".l10n
+            }
+            calorieItem.do { v in
+                v.titleLabel.text = "300"
+                v.detailLabel.text = "卡路里".l10n
+            }
+            stepItem.do { v in
+                v.titleLabel.text = "1200"
+                v.detailLabel.text = "步数".l10n
+            }
+            okBtn.do { v in
+                v.setImage(UIImage(named: "btn_pause"), for: .normal)
+                v.addTarget(self, action: #selector(okAction), for: .touchUpInside)
+            }
+        }
+        
+        override func setupLayout() {
+            topIcon.snp.makeConstraints { make in
+                make.width.equalTo(50)
+                make.height.equalTo(4)
+                make.top.equalToSuperview().inset(6)
+                make.centerX.equalToSuperview()
+            }
+            header.snp.makeConstraints { make in
+                make.top.equalToSuperview().inset(28)
+                make.left.right.equalToSuperview()
+                make.height.equalTo(25)
+            }
+            distanceItem.snp.makeConstraints { make in
+                make.left.equalToSuperview().inset(18)
+                make.top.equalToSuperview().inset(100)
+                make.height.equalTo(50)
+            }
+            durationItem.snp.makeConstraints { make in
+                make.left.equalToSuperview().inset(18)
+                make.top.equalToSuperview().inset(180)
+                make.height.equalTo(50)
+            }
+            speedItem.snp.makeConstraints { make in
+                make.left.equalToSuperview().inset(kScreenWid/2 + 18)
+                make.top.equalTo(durationItem.snp.top)
+                make.height.equalTo(50)
+            }
+            calorieItem.snp.makeConstraints { make in
+                make.left.equalToSuperview().inset(18)
+                make.top.equalToSuperview().inset(250)
+                make.height.equalTo(50)
+            }
+            stepItem.snp.makeConstraints { make in
+                make.left.equalToSuperview().inset(kScreenWid/2 + 18)
+                make.top.equalTo(calorieItem.snp.top)
+                make.height.equalTo(50)
+            }
+            okBtn.snp.makeConstraints { make in
+                make.centerX.equalToSuperview()
+                make.bottom.equalToSuperview().inset(50)
+                make.size.equalTo(90)
+            }
+        }
+        
+        @objc func okAction(){
+            App.shared.goToPage(SportDetailVC())
+        }
+        
+        
+        class headerItem: BaseView {
+            let deviceLabel = UILabel()
+            let deviceView = UIView()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                addSubviews([titleLabel,deviceView])
+                deviceView.addSubviews([deviceLabel])
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .bold(16)
+                    v.textAlignment = .left
+                    v.text = "户外跑步"
+                }
+                deviceView.do { v in
+                    v.backgroundColor = .rgb(0xF7F7F7 )
+                    v.yc.setCornerRadius(13)
+                }
+                deviceLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(10)
+                    v.textAlignment = .center
+                    v.text = "Deep Lite2 Ultra"
+                }
+            }
+            
+            override func setupLayout() {
+                titleLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview().inset(0)
+                    make.left.equalToSuperview().inset(18)
+                }
+                deviceView.snp.makeConstraints { make in
+                    make.width.equalTo(120)
+                    make.height.equalTo(26)
+                    make.left.equalToSuperview().inset(94)
+                    make.centerY.equalToSuperview()
+                }
+                deviceLabel.snp.makeConstraints { make in
+                    make.centerY.right.equalToSuperview()
+                    make.left.equalToSuperview().inset(18)
+                }
+            }
+        }
+        
+        
+        class LabelItem: BaseView {
+            let detailLabel = UILabel()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                addSubviews([titleLabel,detailLabel])
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .bold(24)
+                    v.textAlignment = .left
+                }
+                detailLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(12)
+                    v.textAlignment = .left
+                }
+            }
+            
+            override func setupLayout() {
+                titleLabel.snp.makeConstraints { make in
+                    make.top.equalToSuperview().inset(0)
+                    make.left.right.equalToSuperview()
+                }
+                detailLabel.snp.makeConstraints { make in
+                    make.bottom.equalToSuperview().inset(0)
+                    make.left.right.equalToSuperview()
+                }
+            }
+        }
+    }
+    
+    
+    
+}
diff --git a/ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailVC.swift b/ShenYin/ShenYin/UI/Sport/Sport/SportDetail/SportDetailVC.swift
new file mode 100644 (file)
index 0000000..22a0030
--- /dev/null
@@ -0,0 +1,87 @@
+//
+//  SportDetailVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2026/2/5.
+//
+
+import MAMapKit
+
+class SportDetailVC: BaseVC {
+    var mapView:MAMapView!
+    let simpleView = UIView()
+    let detailView = SportDetailBoard()
+    
+    override func setupViews() {
+        
+        
+        
+        mapView = MAMapView(frame: .zero)
+        mapView.delegate = self
+        mapView.showsUserLocation = true
+        mapView.zoomLevel = 16
+        mapView.userTrackingMode = .followWithHeading
+        
+        view.addSubviews([mapView,simpleView,detailView])
+        mapView.do { v in
+            
+        }
+        simpleView.do { v in
+            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: 100), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 20, height: 20))
+            v.yc.addTap(target: self, action: #selector(simpleTapAction))
+        }
+        detailView.do { v in
+            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: 460), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 20, height: 20))
+            v.isHidden = true
+            v.yc.addTap(target: self, action: #selector(detailTapAction))
+        }
+    }
+    override func setupLayout() {
+        simpleView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.bottom.equalToSuperview()
+            make.height.equalTo(100)
+        }
+        detailView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.bottom.equalToSuperview()
+            make.height.equalTo(460)
+        }
+        mapView.snp.makeConstraints { make in
+            make.left.right.top.equalToSuperview()
+            make.bottom.equalTo(simpleView.snp.top).offset(20)
+        }
+    }
+    override func setupData() {
+        
+    }
+    
+    @objc func simpleTapAction(){
+        simpleView.isHidden = true
+        detailView.isHidden = false
+        showDetail()
+    }
+    @objc func detailTapAction(){
+        simpleView.isHidden = false
+        detailView.isHidden = true
+        showSimple()
+    }
+    func showSimple(){
+        mapView.snp.remakeConstraints { make in
+            make.left.right.top.equalToSuperview()
+            make.bottom.equalTo(simpleView.snp.top).offset(20)
+        }
+    }
+    func showDetail(){
+        mapView.snp.remakeConstraints { make in
+            make.left.right.top.equalToSuperview()
+            make.bottom.equalTo(detailView.snp.top).offset(20)
+        }
+    }
+}
+
+extension SportDetailVC:MAMapViewDelegate{
+    func mapViewRequireLocationAuth(_ locationManager: CLLocationManager!) {
+        //        locationManager.requestAlwaysAuthorization()
+    }
+}
index 87ce152..f14c052 100644 (file)
@@ -10,15 +10,17 @@ import UIKit
 extension SportingVC{
     class DetailBoard: BaseView {
         let topIcon = UIImageView()
+        let header = headerItem()
         let distanceItem = LabelItem()
         let durationItem = LabelItem()
         let speedItem = LabelItem()
         let calorieItem = LabelItem()
         let stepItem = LabelItem()
+        let okBtn = UIButton(type: .custom)
         
         override func setupViews() {
             backgroundColor = .white
-            addSubviews([topIcon,distanceItem,durationItem,speedItem,calorieItem,stepItem])
+            addSubviews([topIcon,header,distanceItem,durationItem,speedItem,calorieItem,stepItem,okBtn])
             topIcon.do { v in
                 v.backgroundColor = .color(.secondary)
                 v.yc.setCornerRadius(2)
@@ -32,16 +34,20 @@ extension SportingVC{
                 v.detailLabel.text = "总时长".l10n
             }
             speedItem.do { v in
-                v.titleLabel.text = "00:00:00"
-                v.detailLabel.text = "总时长".l10n
+                v.titleLabel.text = "8'26\""
+                v.detailLabel.text = "配速".l10n
             }
             calorieItem.do { v in
-                v.titleLabel.text = "00:00:00"
-                v.detailLabel.text = "总时长".l10n
+                v.titleLabel.text = "300"
+                v.detailLabel.text = "卡路里".l10n
             }
             stepItem.do { v in
-                v.titleLabel.text = "00:00:00"
-                v.detailLabel.text = "总时长".l10n
+                v.titleLabel.text = "1200"
+                v.detailLabel.text = "步数".l10n
+            }
+            okBtn.do { v in
+                v.setImage(UIImage(named: "btn_pause"), for: .normal)
+                v.addTarget(self, action: #selector(okAction), for: .touchUpInside)
             }
         }
         
@@ -52,9 +58,14 @@ extension SportingVC{
                 make.top.equalToSuperview().inset(6)
                 make.centerX.equalToSuperview()
             }
+            header.snp.makeConstraints { make in
+                make.top.equalToSuperview().inset(28)
+                make.left.right.equalToSuperview()
+                make.height.equalTo(25)
+            }
             distanceItem.snp.makeConstraints { make in
                 make.left.equalToSuperview().inset(18)
-                make.top.equalToSuperview().inset(27)
+                make.top.equalToSuperview().inset(100)
                 make.height.equalTo(50)
             }
             durationItem.snp.makeConstraints { make in
@@ -67,52 +78,104 @@ extension SportingVC{
                 make.top.equalTo(durationItem.snp.top)
                 make.height.equalTo(50)
             }
-            distanceItem.snp.makeConstraints { make in
+            calorieItem.snp.makeConstraints { make in
                 make.left.equalToSuperview().inset(18)
                 make.top.equalToSuperview().inset(250)
                 make.height.equalTo(50)
             }
             stepItem.snp.makeConstraints { make in
                 make.left.equalToSuperview().inset(kScreenWid/2 + 18)
-                make.top.equalTo(distanceItem.snp.top)
+                make.top.equalTo(calorieItem.snp.top)
                 make.height.equalTo(50)
             }
+            okBtn.snp.makeConstraints { make in
+                make.centerX.equalToSuperview()
+                make.bottom.equalToSuperview().inset(50)
+                make.size.equalTo(90)
+            }
         }
         
-        @objc func groupAction(){
-            App.shared.goToPage(SportSetVC())
+        @objc func okAction(){
+            App.shared.goToPage(SportDetailVC())
         }
 
-    }
-    
-    class LabelItem: BaseView {
-        let detailLabel = UILabel()
-        let titleLabel = UILabel()
         
-        override func setupViews() {
-            addSubviews([titleLabel,detailLabel])
-            titleLabel.do { v in
-                v.textColor = .color(.first)
-                v.font = .bold(24)
-                v.textAlignment = .left
-            }
-            detailLabel.do { v in
-                v.textColor = .color(.secondary)
-                v.font = .regular(12)
-                v.textAlignment = .left
+        class headerItem: BaseView {
+            let deviceLabel = UILabel()
+            let deviceView = UIView()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                addSubviews([titleLabel,deviceView])
+                deviceView.addSubviews([deviceLabel])
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .bold(16)
+                    v.textAlignment = .left
+                    v.text = "户外跑步"
+                }
+                deviceView.do { v in
+                    v.backgroundColor = .rgb(0xF7F7F7 )
+                    v.yc.setCornerRadius(13)
+                }
+                deviceLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(10)
+                    v.textAlignment = .center
+                    v.text = "Deep Lite2 Ultra"
+                }
+            }
+            
+            override func setupLayout() {
+                titleLabel.snp.makeConstraints { make in
+                    make.centerY.equalToSuperview().inset(0)
+                    make.left.equalToSuperview().inset(18)
+                }
+                deviceView.snp.makeConstraints { make in
+                    make.width.equalTo(120)
+                    make.height.equalTo(26)
+                    make.left.equalToSuperview().inset(94)
+                    make.centerY.equalToSuperview()
+                }
+                deviceLabel.snp.makeConstraints { make in
+                    make.centerY.right.equalToSuperview()
+                    make.left.equalToSuperview().inset(18)
+                }
             }
         }
         
-        override func setupLayout() {
-            titleLabel.snp.makeConstraints { make in
-                make.top.equalToSuperview().inset(0)
-                make.left.right.equalToSuperview()
-            }
-            detailLabel.snp.makeConstraints { make in
-                make.bottom.equalToSuperview().inset(0)
-                make.left.right.equalToSuperview()
+        
+        class LabelItem: BaseView {
+            let detailLabel = UILabel()
+            let titleLabel = UILabel()
+            
+            override func setupViews() {
+                addSubviews([titleLabel,detailLabel])
+                titleLabel.do { v in
+                    v.textColor = .color(.first)
+                    v.font = .bold(24)
+                    v.textAlignment = .left
+                }
+                detailLabel.do { v in
+                    v.textColor = .color(.secondary)
+                    v.font = .regular(12)
+                    v.textAlignment = .left
+                }
+            }
+            
+            override func setupLayout() {
+                titleLabel.snp.makeConstraints { make in
+                    make.top.equalToSuperview().inset(0)
+                    make.left.right.equalToSuperview()
+                }
+                detailLabel.snp.makeConstraints { make in
+                    make.bottom.equalToSuperview().inset(0)
+                    make.left.right.equalToSuperview()
+                }
             }
         }
     }
-
+    
+    
+  
 }
index ed528b3..fe9a9f6 100644 (file)
@@ -27,10 +27,11 @@ class SportingVC: BaseVC {
             
         }
         simpleView.do { v in
-            //            v.backgroundColor = .blue
+            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: 100), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 20, height: 20))
             v.yc.addTap(target: self, action: #selector(simpleTapAction))
         }
         detailView.do { v in
+            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: 460), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 20, height: 20))
             v.isHidden = true
             v.yc.addTap(target: self, action: #selector(detailTapAction))
         }
@@ -48,7 +49,7 @@ class SportingVC: BaseVC {
         }
         mapView.snp.makeConstraints { make in
             make.left.right.top.equalToSuperview()
-            make.bottom.equalTo(simpleView.snp.top)
+            make.bottom.equalTo(simpleView.snp.top).offset(20)
         }
     }
     override func setupData() {
@@ -68,13 +69,13 @@ class SportingVC: BaseVC {
     func showSimple(){
         mapView.snp.remakeConstraints { make in
             make.left.right.top.equalToSuperview()
-            make.bottom.equalTo(simpleView.snp.top)
+            make.bottom.equalTo(simpleView.snp.top).offset(20)
         }
     }
     func showDetail(){
         mapView.snp.remakeConstraints { make in
             make.left.right.top.equalToSuperview()
-            make.bottom.equalTo(detailView.snp.top)
+            make.bottom.equalTo(detailView.snp.top).offset(20)
         }
     }
 }
index 76af958..7344928 100644 (file)
@@ -11,6 +11,7 @@ class MapManager {
     static let shared = MapManager()
     
     func setupSdk(){
+        MAMapView.updatePrivacyAgree(AMapPrivacyAgreeStatus.didAgree)
         AMapServices.shared().apiKey = "57aebc5a63fa3ccb8cb81ae0cab649d1"
         //判断是否是首次启动
         if !UserDefaults.standard.bool(forKey: "agreeStatus") {