ble连接优化
authorliangzhenying <867174124@qq.com>
Mon, 10 Nov 2025 03:14:15 +0000 (11:14 +0800)
committerliangzhenying <867174124@qq.com>
Mon, 10 Nov 2025 03:14:15 +0000 (11:14 +0800)
73 files changed:
ShenYin/Podfile.lock
ShenYin/PrivacyInfo.xcprivacy [new file with mode: 0644]
ShenYin/ShenYin.xcodeproj/project.pbxproj
ShenYin/ShenYin/Api/Config.swift
ShenYin/ShenYin/Api/HttpClient2.swift
ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/Contents.json [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/server_qr.png [new file with mode: 0644]
ShenYin/ShenYin/Assets.xcassets/home/chat/role_linjianvhai.imageset/Contents.json [moved from ShenYin/ShenYin/Assets.xcassets/home/chat/role_ linjianvhai.imageset/Contents.json with 100% similarity]
ShenYin/ShenYin/Assets.xcassets/home/chat/role_linjianvhai.imageset/Group_2377.png [moved from ShenYin/ShenYin/Assets.xcassets/home/chat/role_ linjianvhai.imageset/Group_2377.png with 100% similarity]
ShenYin/ShenYin/Assets.xcassets/home/chat/role_linjianvhai.imageset/Group_2377@2x.png [moved from ShenYin/ShenYin/Assets.xcassets/home/chat/role_ linjianvhai.imageset/Group_2377@2x.png with 100% similarity]
ShenYin/ShenYin/Assets.xcassets/home/chat/role_linjianvhai.imageset/Group_2377@3x.png [moved from ShenYin/ShenYin/Assets.xcassets/home/chat/role_ linjianvhai.imageset/Group_2377@3x.png with 100% similarity]
ShenYin/ShenYin/Cache/DCFolder.swift
ShenYin/ShenYin/Cache/DeviceCache.swift [new file with mode: 0644]
ShenYin/ShenYin/Cache/FontCache.swift [deleted file]
ShenYin/ShenYin/Cache/TipsCache.swift
ShenYin/ShenYin/Cache/UserInfo.swift
ShenYin/ShenYin/Cache/UserModel.swift
ShenYin/ShenYin/Info.plist
ShenYin/ShenYin/Tools/Category/Open+map.swift
ShenYin/ShenYin/Tools/YLTools.swift
ShenYin/ShenYin/UI/Base/BasePresentView.swift
ShenYin/ShenYin/UI/Base/BaseTC.swift
ShenYin/ShenYin/UI/Customer/CustomerHeaderView.swift
ShenYin/ShenYin/UI/Customer/CustomerVC.swift
ShenYin/ShenYin/UI/Home/CallingRecordVC.swift
ShenYin/ShenYin/UI/Home/Chat/ChatHeaderView.swift
ShenYin/ShenYin/UI/Home/Chat/ChatVC.swift
ShenYin/ShenYin/UI/Home/Chat/NavigationBarItem.swift
ShenYin/ShenYin/UI/Home/Chat/RoleListVC.swift
ShenYin/ShenYin/UI/Home/Chinese2English/Chinese2EnglishVC.swift
ShenYin/ShenYin/UI/Home/Device/HomeDeviceVC.swift
ShenYin/ShenYin/UI/Home/Dialog/DialogTranlateVC.swift
ShenYin/ShenYin/UI/Home/FieldRecording/FieldRecordingVC.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/FileSaver.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/HistoryRecordCell.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/RecordHistoryModel.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/VC/CloudRecordVC.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/VC/HistoryRecordVC.swift
ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedCell.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedVC.swift [new file with mode: 0644]
ShenYin/ShenYin/UI/Home/HistoryRecord/search/HistorySelectedVC.swift
ShenYin/ShenYin/UI/Home/RecordDetail/RecordDetailVC.swift
ShenYin/ShenYin/UI/Home/RecordTranslateVC.swift
ShenYin/ShenYin/UI/Home/Root/HomeBottomView.swift
ShenYin/ShenYin/UI/Home/Scan/BleScanVC.swift
ShenYin/ShenYin/UI/Launch/AppLaunch.swift
ShenYin/ShenYin/UI/Launch/BleManager.swift
ShenYin/ShenYin/UI/Launch/LanConfig.swift
ShenYin/ShenYin/UI/Mine/Feedback/FeedbackContentView.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/ContryListVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/ForgetVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/LoginVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/RegisterVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/SmsLoginVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/VerifyCodeVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/VerifyEmailVC.swift
ShenYin/ShenYin/UI/Mine/Login/Controller/VerifyPhoneVC.swift
ShenYin/ShenYin/UI/Mine/Login/View/AgreeView.swift
ShenYin/ShenYin/UI/Mine/Login/View/OthersLoginView.swift
ShenYin/ShenYin/UI/Mine/Login/ViewModel/LoginVM.swift
ShenYin/ShenYin/UI/Mine/RevokeVC.swift
ShenYin/ShenYin/UI/Mine/Root/MineHeaderView.swift
ShenYin/ShenYin/UI/Mine/Root/MineVC.swift
ShenYin/ShenYin/UI/Mine/Update/AppUpdateVM.swift
ShenYin/ShenYin/UI/Mine/Update/UpdateVC.swift
ShenYin/ShenYin/UI/Mine/UserInfo/CustomCell1.swift
ShenYin/ShenYin/UI/Mine/UserInfo/UserInfoVC.swift
ShenYin/ShenYin/UI/Mode/ModeListView.swift [deleted file]
ShenYin/ShenYin/UI/Mode/ModeVC.swift
ShenYin/ShenYin/UI/common/LogVC.swift
ShenYin/ShenYin/UI/common/YLprogressHUD.swift
ShenYin/ShenYin/UI/common/pop/PopTextField.swift
ShenYin/podfile

index 10bc72b..fa1c8e9 100644 (file)
@@ -49,12 +49,6 @@ PODS:
   - JXSegmentedView (1.4.1)
   - Kingfisher (6.3.1)
   - MJRefresh (3.7.9)
-  - netfox (1.21.0)
-  - Realm (20.0.3):
-    - Realm/Headers (= 20.0.3)
-  - Realm/Headers (20.0.3)
-  - RealmSwift (20.0.3):
-    - Realm (= 20.0.3)
   - SnapKit (5.7.1)
   - SocketRocket (0.7.1)
   - SVProgressHUD (2.3.1):
@@ -86,8 +80,6 @@ DEPENDENCIES:
   - JXSegmentedView
   - Kingfisher (~> 6.0)
   - MJRefresh
-  - netfox
-  - RealmSwift
   - SnapKit
   - SocketRocket
   - SVProgressHUD
@@ -121,9 +113,6 @@ SPEC REPOS:
     - JXSegmentedView
     - Kingfisher
     - MJRefresh
-    - netfox
-    - Realm
-    - RealmSwift
     - SnapKit
     - SocketRocket
     - SVProgressHUD
@@ -156,9 +145,6 @@ SPEC CHECKSUMS:
   JXSegmentedView: cd73555ce2134d1656db2cb383ba9c2f36fb5078
   Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74
   MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
-  netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7
-  Realm: 853e5089d6042dff807bda000277eadfe2da93d2
-  RealmSwift: f33c19577cefcbf681345d721fcbc7b42be4c949
   SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
   SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
   SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22
@@ -172,6 +158,6 @@ SPEC CHECKSUMS:
   YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
   ZipArchive: e25a4373192673e3229ac8d6e9f64a3e5713c966
 
-PODFILE CHECKSUM: 06f9ef8c019046f938158cfb86472b866db8d248
+PODFILE CHECKSUM: 3a7a732ff076ffc1ffadc01ed95542ab50a068f8
 
 COCOAPODS: 1.16.2
diff --git a/ShenYin/PrivacyInfo.xcprivacy b/ShenYin/PrivacyInfo.xcprivacy
new file mode 100644 (file)
index 0000000..148b97e
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>NSPrivacyTracking</key>
+       <false/>
+       <key>NSPrivacyTrackingDomains</key>
+       <array/>
+       <key>NSPrivacyAccessedAPITypes</key>
+       <array>
+               <dict>
+                       <key>NSPrivacyAccessedAPIType</key>
+                       <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
+                       <key>NSPrivacyAccessedAPITypeReasons</key>
+                       <array>
+                               <string>E174.1</string>
+                       </array>
+               </dict>
+       </array>
+       <key>NSPrivacyCollectedDataTypes</key>
+       <array/>
+</dict>
+</plist>
index 749bf6b..361a9b9 100644 (file)
@@ -9,6 +9,7 @@
 /* Begin PBXBuildFile section */
                3F79C6142E6055E500EC38B9 /* JoyGemAI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; };
                3F79C6152E6055E500EC38B9 /* JoyGemAI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+               3F8F58292EBCA2B800FFC00B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */; };
                F2E449CAD5874BE652A69B50 /* Pods_ShenYin.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3862D5561144E20721225B96 /* Pods_ShenYin.framework */; };
 /* End PBXBuildFile section */
 
@@ -30,6 +31,7 @@
                3862D5561144E20721225B96 /* Pods_ShenYin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ShenYin.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                3F79C4902E603B4700EC38B9 /* JoyGemAI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JoyGemAI.framework; sourceTree = "<group>"; };
                3F887B9C2E38D8DC00C98658 /* ShenYin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShenYin.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
                5F5DE5910965D53C2B3405B0 /* Pods-ShenYin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShenYin.debug.xcconfig"; path = "Target Support Files/Pods-ShenYin/Pods-ShenYin.debug.xcconfig"; sourceTree = "<group>"; };
                CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.debug.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.debug.xcconfig"; sourceTree = "<group>"; };
                CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.release.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.release.xcconfig"; sourceTree = "<group>"; };
@@ -84,6 +86,7 @@
                3F887B932E38D8DC00C98658 = {
                        isa = PBXGroup;
                        children = (
+                               3F8F58282EBCA2B800FFC00B /* PrivacyInfo.xcprivacy */,
                                3F887B9E2E38D8DC00C98658 /* ShenYin */,
                                3F887B9D2E38D8DC00C98658 /* Products */,
                                34A14A83ECF09370871C891F /* Pods */,
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               3F8F58292EBCA2B800FFC00B /* PrivacyInfo.xcprivacy in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 79d53b1..aebce50 100644 (file)
@@ -5,14 +5,11 @@
 //  Created by liangshi on 2025/10/15.
 //
 
-class Config{
-
-    
-    static var appLanguage = AppSupportLanguage.chinse
+class DCConfig{
+    static var appLanguage = AppSupportLanguage.china
 }
-class DCGlobal {
 
-    
+class DCGlobal {    
     /// 微信开发平台 App ID
     static let wxAppID = "wxf19317f23b00d8ab"
     static let wxUniversalLink = "https://www.thisiot.com/flychat"
index 35d1757..ff2820b 100644 (file)
@@ -106,8 +106,12 @@ enum CommomApi
     case uploadVoiceFile(param:[String:Any])
     /// 创建录音记录
     case voiceRecord(param:[String:Any])
+    /// 录音文本记录上报
+    case voiceRecordText(param:[String:Any])
     /// 获取录音记录
     case getVoiceRecord(recordId:String)
+    /// 获取录音文本记录上报
+    case getVoiceRecordText(param:[String:Any])
     /// 更新录音
     case updateVoiceRecord(param:[String:Any])
     /// 删除录音
@@ -183,9 +187,9 @@ extension CommomApi{
         case .storageSize:
             return "/res/voice-file/storage-size"
         case .musicCategory:
-            return "/res/music-category/list"
+            return "/res/music-category/list?languageCode=\(DCConfig.appLanguage.lanCode)"
         case .musicCategoryList(let categoryId,let page):
-            return "/res/sleep-music/list/\(page)?categoryId=\(categoryId)"
+            return "/res/sleep-music/list/\(page)?categoryId=\(categoryId)&languageCode=\(DCConfig.appLanguage.lanCode)"
         case .musicUrl( let id):
             return "/res/music-file/path/\(id)"
         case .recordUrl( let id):
@@ -209,7 +213,7 @@ extension CommomApi{
         case .feedbackHistory:
             return "/uc/feedback"
         
-        case .productInfo(let name):
+        case .productInfo(_):
             return "/dev/product-info/by-name"
         case .deviceList:
             return "/dev/device/list"
@@ -238,8 +242,12 @@ extension CommomApi{
             
         case .voiceRecord(_):
             return "/res/voice-record"
+        case .voiceRecordText(_):
+            return "/res/voice-record-txt"
         case .getVoiceRecord(let recordId):
             return "/res/voice-record/\(recordId)"
+        case .getVoiceRecordText(_):
+            return "/res/voice-record-txt/list"
         case .updateVoiceRecord(let param):
             return "/res/voice-record/\(param["id"]!)"
         case .deleteVoiceRecord(let recordId):
@@ -255,7 +263,7 @@ extension CommomApi{
     
     var method:RequestMethod{
         switch self {
-        case .register(_),.phoneCodeLogin(_),.emailCodeLogin(_),.appleLogin(_),.login(_),.commitFeedback(_),.voiceRecord(_):
+        case .register(_),.phoneCodeLogin(_),.emailCodeLogin(_),.appleLogin(_),.login(_),.commitFeedback(_),.voiceRecord(_),.voiceRecordText(_):
             return .post
         case .updatePwd(_),.updateUserInfo(_),.updatePhone(_),.updateEmail(_),.bindDevice(_),.otaUpdateVersion(_),.voiceRecordCollection(_),.updateVoiceRecord(_):
             return .put
@@ -326,6 +334,10 @@ extension CommomApi{
             break
         case let .voiceRecord(para):
             params += para
+        case let .voiceRecordText(para):
+            params += para
+        case let .getVoiceRecordText(para):
+            params += para
         case let .voiceRecordList(para):
             params += para
         case let .updateVoiceRecord(para):
@@ -352,7 +364,7 @@ class HttpClient{
         let url = target.url
         let params = target.param
         Logger.debug("request => ",url)
-        Logger.debug(params)
+        Logger.debug(YLToos.jsonToString(params))
         
         if target.method == .get {
             HTTP.GET(url,parameters: params,requestSerializer: JSONParameterSerializer()){ response in
@@ -563,11 +575,11 @@ extension HttpClient{
                 return
             }
             let responseStr = response.data.string ?? ""
-            if let code = dict["code"] as? Int,code == 50000{
-                YLprogressHUD.showAutoHiden(text: "当前账号已经退出登录"){
-                    CacheManager.shared.user.logout()
-                }
-            }
+//            if let code = dict["code"] as? Int,code == 50000{
+//                YLprogressHUD.showAutoHiden(text: "当前账号已经退出登录"){
+//                    CacheManager.shared.user.logout()
+//                }
+//            }
             if let res = T.deserialize(from: dict){
                 completionHandler(res,responseStr)
                 return
@@ -642,15 +654,4 @@ extension HttpClient{
     }
 }
 
-extension Data {
-    var string: String? { String(data: self, encoding: .utf8) }
-    func jsonObject(options: JSONSerialization.ReadingOptions = [.mutableContainers]) -> Any? {
-        do { return try JSONSerialization.jsonObject(with: self, options: options) }
-        catch { Logger.debug(error) }
-        return nil
-    }
-}
 
-extension String {
-    var data: Data? { self.data(using: .utf8) }
-}
diff --git a/ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/Contents.json b/ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3cbe57f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "server_qr.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/server_qr.png b/ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/server_qr.png
new file mode 100644 (file)
index 0000000..a06461f
Binary files /dev/null and b/ShenYin/ShenYin/Assets.xcassets/customer/server_qr.imageset/server_qr.png differ
index fda2224..be2be8c 100644 (file)
@@ -19,7 +19,6 @@ class DCFolder {
     }
     
     static func createFolder(_ foldPath:String){
-        Logger.debug("路径 " ,foldPath)
         let fileManager = FileManager.default
         if !fileManager.fileExists(atPath: foldPath) {
             do {
diff --git a/ShenYin/ShenYin/Cache/DeviceCache.swift b/ShenYin/ShenYin/Cache/DeviceCache.swift
new file mode 100644 (file)
index 0000000..453db22
--- /dev/null
@@ -0,0 +1,44 @@
+//
+//  DeviceCache.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/11/8.
+//
+
+class DeviceCache {
+    static let shared = DeviceCache()
+    private let userDefaults = UserDefaults.standard
+    private let deviceListKey = "DeviceCache"
+    
+    func add(_ uuid: String,mac:String) {
+        var deviceList = getList()
+        deviceList[uuid] = mac
+        userDefaults.set(deviceList, forKey: deviceListKey)
+        userDefaults.synchronize()
+    }
+    func getMac(_ uuid:String)->String?{
+        let deviceList = getList()
+        Logger.debug(deviceList)
+        return deviceList[uuid]
+    }
+    func getList() -> [String:String] {
+        if let data = userDefaults.value(forKey: deviceListKey) as? [String:String]{
+           return data
+        }
+        return [:]
+    }
+}
+
+
+extension DeviceCache{
+    static func saveLastConnected(mac:String){
+        UserDefaults.standard.set(mac, forKey: "LastConnect")
+        UserDefaults.standard.synchronize()
+    }
+    static func getLastConnected()->String?{
+        if let value = UserDefaults.standard.value(forKey: "LastConnect"),let obj = value as? String {
+            return obj
+        }
+        return nil
+    }
+}
diff --git a/ShenYin/ShenYin/Cache/FontCache.swift b/ShenYin/ShenYin/Cache/FontCache.swift
deleted file mode 100644 (file)
index 36f1c61..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-//  FontCache.swift
-//  ShenYin
-//
-//  Created by liangshi on 2025/10/24.
-//
-
-class FontCache{
-    static func saveFont(type:FontType){
-        UserDefaults.standard.set(type.rawValue, forKey: "FontCache")
-        UserDefaults.standard.synchronize()
-    }
-    static func getFont()->FontType{
-        if let value = UserDefaults.standard.value(forKey: "FontCache"),let font = value as? Int {
-            return FontType(rawValue: font) ?? .stand
-        }
-        return FontType.stand
-    }
-}
index d2f1b3a..e41de2e 100644 (file)
@@ -17,3 +17,30 @@ class TipsCache{
         return true
     }
 }
+
+class FontCache{
+    static func saveFont(type:FontType){
+        UserDefaults.standard.set(type.rawValue, forKey: "FontCache")
+        UserDefaults.standard.synchronize()
+    }
+    static func getFont()->FontType{
+        if let value = UserDefaults.standard.value(forKey: "FontCache"),let font = value as? Int {
+            return FontType(rawValue: font) ?? .stand
+        }
+        return FontType.stand
+    }
+}
+
+class RoleCache{
+    static let key = "RoleCache"
+    static func save(type:String){
+        UserDefaults.standard.set(type, forKey: key)
+        UserDefaults.standard.synchronize()
+    }
+    static func get()->String?{
+        if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
+            return text
+        }
+        return nil
+    }
+}
index bd069f8..4514eea 100644 (file)
@@ -37,6 +37,15 @@ class UserInfo:ResponseBaseModel {
     var gender = GenderType.unnkown
     var countryName = ""
     var countryId = ""
+    
+    var cacheCountryName:String{
+        for item in LoginVM.shared.countryList {
+            if item.id == self.countryId{
+                return item.name
+            }
+        }
+        return ""
+    }
 }
 
 
index c764725..426510c 100644 (file)
@@ -49,9 +49,11 @@ extension UserModel{
                 self.info = model.data
                 UserCache.shared.save(self.info)
             }
-//            else{
-//                logout()
-//            }
+            else{
+                if let dict = YLToos.stringToJson(res),let code = dict["code"] as? Int,code == 50000{
+                    logout()
+                }
+            }
             finished?()
         }
     }
index 82a0f3a..b0ef8fa 100644 (file)
@@ -51,5 +51,7 @@
                <string>bluetooth-central</string>
                <string>audio</string>
        </array>
+       <key>NSLocationWhenInUseUsageDescription</key>
+       <string>允许APP使用定位方便查找耳机</string>
 </dict>
 </plist>
index 6f785d4..0fcb153 100644 (file)
@@ -5,98 +5,98 @@
 //  Created by apple on 2020/12/16.
 //
 
-import Foundation
-import MapKit
-
-struct MapTool {
-    /// Info plist
-    /// LSApplicationQueriesSchemes 需要添加 iosamap
-    private static let aMapScheme = "iosamap://"
-    private static let aMapSchemeUrl = URL(string: aMapScheme)
-    private static var canOpenAmap: Bool {
-        if let url = aMapSchemeUrl {
-            return UIApplication.shared.canOpenURL(url)
-        } else {
-            return false
-        }
-    }
-    
-    private static let mapsScheme = "http://maps.apple.com/"
-    private static let mapsSchemeUrl = URL(string: mapsScheme)
-    private static var canOpenMaps: Bool {
-        if let url = mapsSchemeUrl {
-            return UIApplication.shared.canOpenURL(url)
-        } else {
-            return false
-        }
-    }
-    
-    /// Info plist
-    /// LSApplicationQueriesSchemes 需要添加 baidumap
-    private static let bMapScheme = "baidumap://"
-    private static let bMapSchemeUrl = URL(string: bMapScheme)
-    private static var canOpenbMap: Bool {
-        if let url = bMapSchemeUrl {
-            return UIApplication.shared.canOpenURL(url)
-        } else {
-            return false
-        }
-    }
-    
-    /// 导航功能方法封装
-    /// @param lat 纬度
-    /// @param lng 经度
-    /// @param address 地图显示目的地
-    /// @param currentController 在哪个VC弹出
-//    static func mapNavigation(lat: Double, lng: Double, address: String, currentVC: UIViewController) {
-//        let urlScheme = ""
-//        let appName = ""
-//        var address = address
-//        let coordiante = CLLocationCoordinate2DMake(lat, lng)
-//        if address.isEmpty {
-//            address = "目的地"
-//        }
-//        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
-//        if canOpenMaps {
-//            let action = UIAlertAction(title: "苹果地图", style: .default) { (action) in
-//                let currentLocation = MKMapItem.forCurrentLocation()
-//                let toLocation = MKMapItem(placemark: MKPlacemark(coordinate: coordiante))
-//                toLocation.name = address
-//                MKMapItem.openMaps(with: [currentLocation, toLocation],
-//                                   launchOptions: [
-//                                    MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
-//                                    MKLaunchOptionsShowsTrafficKey:true]
-//                )
-//            }
-//            alert.addAction(action)
+//import Foundation
+//import MapKit
+//
+//struct MapTool {
+//    /// Info plist
+//    /// LSApplicationQueriesSchemes 需要添加 iosamap
+//    private static let aMapScheme = "iosamap://"
+//    private static let aMapSchemeUrl = URL(string: aMapScheme)
+//    private static var canOpenAmap: Bool {
+//        if let url = aMapSchemeUrl {
+//            return UIApplication.shared.canOpenURL(url)
+//        } else {
+//            return false
 //        }
-//        if canOpenbMap {
-//            let action = UIAlertAction(title: "百度地图", style: .default) { (action) in
-//                let bstr = "baidumap://map/direction?origin={{我的位置}}&destination=name:\(address)|latlng:\(coordiante.latitude),\(coordiante.longitude)&mode=driving&coord_type=gcj02"
-//                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
-//                guard let urlStr2 = urlStr else { return }
-//                guard let url = urlStr2.url else { return }
-//                UIApplication.shared.open(url, options: [:]) { (success) in
-//                    SNLog("scheme try end")
-//                }
-//            }
-//            alert.addAction(action)
+//    }
+//    
+//    private static let mapsScheme = "http://maps.apple.com/"
+//    private static let mapsSchemeUrl = URL(string: mapsScheme)
+//    private static var canOpenMaps: Bool {
+//        if let url = mapsSchemeUrl {
+//            return UIApplication.shared.canOpenURL(url)
+//        } else {
+//            return false
 //        }
-//        if canOpenAmap {
-//            let action = UIAlertAction(title: "高德地图", style: .default) { (action) in
-//                let bstr = "iosamap://path?sourceApplication=\(appName)&backScheme=\(urlScheme)&dlat=\(coordiante.latitude)&dlon=\(coordiante.longitude)&dname=\(address)&dev=0&t=0"
-//                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
-//                guard let urlStr2 = urlStr else { return }
-//                guard let url = urlStr2.url else { return }
-//                UIApplication.shared.open(url, options: [:]) { (success) in
-//                    SNLog("scheme try end")
-//                }
-//            }
-//            alert.addAction(action)
+//    }
+//    
+//    /// Info plist
+//    /// LSApplicationQueriesSchemes 需要添加 baidumap
+//    private static let bMapScheme = "baidumap://"
+//    private static let bMapSchemeUrl = URL(string: bMapScheme)
+//    private static var canOpenbMap: Bool {
+//        if let url = bMapSchemeUrl {
+//            return UIApplication.shared.canOpenURL(url)
+//        } else {
+//            return false
 //        }
-//        let action = UIAlertAction(title: "取消", style: .cancel, handler: nil)
-//        alert.addAction(action)
-//        
-//        currentVC.present(alert, animated: true, completion: nil)
 //    }
-}
+//    
+//    /// 导航功能方法封装
+//    /// @param lat 纬度
+//    /// @param lng 经度
+//    /// @param address 地图显示目的地
+//    /// @param currentController 在哪个VC弹出
+////    static func mapNavigation(lat: Double, lng: Double, address: String, currentVC: UIViewController) {
+////        let urlScheme = ""
+////        let appName = ""
+////        var address = address
+////        let coordiante = CLLocationCoordinate2DMake(lat, lng)
+////        if address.isEmpty {
+////            address = "目的地"
+////        }
+////        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+////        if canOpenMaps {
+////            let action = UIAlertAction(title: "苹果地图", style: .default) { (action) in
+////                let currentLocation = MKMapItem.forCurrentLocation()
+////                let toLocation = MKMapItem(placemark: MKPlacemark(coordinate: coordiante))
+////                toLocation.name = address
+////                MKMapItem.openMaps(with: [currentLocation, toLocation],
+////                                   launchOptions: [
+////                                    MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
+////                                    MKLaunchOptionsShowsTrafficKey:true]
+////                )
+////            }
+////            alert.addAction(action)
+////        }
+////        if canOpenbMap {
+////            let action = UIAlertAction(title: "百度地图", style: .default) { (action) in
+////                let bstr = "baidumap://map/direction?origin={{我的位置}}&destination=name:\(address)|latlng:\(coordiante.latitude),\(coordiante.longitude)&mode=driving&coord_type=gcj02"
+////                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
+////                guard let urlStr2 = urlStr else { return }
+////                guard let url = urlStr2.url else { return }
+////                UIApplication.shared.open(url, options: [:]) { (success) in
+////                    SNLog("scheme try end")
+////                }
+////            }
+////            alert.addAction(action)
+////        }
+////        if canOpenAmap {
+////            let action = UIAlertAction(title: "高德地图", style: .default) { (action) in
+////                let bstr = "iosamap://path?sourceApplication=\(appName)&backScheme=\(urlScheme)&dlat=\(coordiante.latitude)&dlon=\(coordiante.longitude)&dname=\(address)&dev=0&t=0"
+////                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
+////                guard let urlStr2 = urlStr else { return }
+////                guard let url = urlStr2.url else { return }
+////                UIApplication.shared.open(url, options: [:]) { (success) in
+////                    SNLog("scheme try end")
+////                }
+////            }
+////            alert.addAction(action)
+////        }
+////        let action = UIAlertAction(title: "取消", style: .cancel, handler: nil)
+////        alert.addAction(action)
+////        
+////        currentVC.present(alert, animated: true, completion: nil)
+////    }
+//}
index 8c0512c..5aa4bb0 100644 (file)
@@ -27,4 +27,94 @@ class YLToos {
         let t =  CMTimeGetSeconds(duration)
         return Int(t)
     }
+    static func stringToJson(_ text:String)->[String:Any]?{
+        guard let data = text.data(using: .utf8) else{
+            return nil
+        }
+        return dataToJson(data)
+    }
+    static func dataToJson(_ data:Data)->[String:Any]?{
+        do {
+            let jsonData = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
+            return jsonData as? [String:Any]
+        } catch {
+            return nil
+        }
+    }
+    static func jsonToString(_ json:[String:Any])->String{
+        if let data = jsonToData(json){
+            return String(data: data, encoding: .utf8) ?? ""
+        }
+        return ""
+    }
+    static func jsonToData(_ json:[String:Any])->Data?{
+        do {
+            let jsonData = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
+            return jsonData
+        } catch {
+            return nil
+        }
+    }
+    
+    static func readFile(from path:String) ->Data?{
+        let fileURL = URL(fileURLWithPath: path)
+        do {
+            let data = try Data(contentsOf:fileURL)
+            return data
+        } catch {
+            return nil
+        }
+    }
+    
+    static func saveToFile(data:Data,path:String)->Bool{
+        let url = URL(fileURLWithPath: path)
+        do {
+            try data.write(to: url, options: .atomic)
+            return true
+        }
+        catch{
+            Logger.debug(error)
+            return false
+        }
+    }
+    
+    static func base64ToImage(_ base64String: String) -> UIImage? {
+        if let data = Data(base64Encoded: base64String),
+           let image = UIImage(data: data) {
+            return image
+        }
+        return nil
+    }
+    
+    static func generateRandomString(length: Int = 16) -> String {
+        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+        var randomString: String = ""
+        for _ in 0..<length {
+            let randomValue = Int.random(in: 0...letters.count - 1)
+            randomString.append(letters[letters.index(letters.startIndex, offsetBy: randomValue)])
+        }
+        return randomString
+    }
+    static func generateRandomString2(length: Int = 16) -> String {
+        let letters = "abcdef0123456789"
+        var randomString: String = ""
+        for _ in 0..<length {
+            let randomValue = Int.random(in: 0...letters.count - 1)
+            randomString.append(letters[letters.index(letters.startIndex, offsetBy: randomValue)])
+        }
+        return randomString
+    }
+}
+
+extension Data {
+    var string: String? { String(data: self, encoding: .utf8) }
+    func jsonObject(options: JSONSerialization.ReadingOptions = [.mutableContainers]) -> Any? {
+        do { return try JSONSerialization.jsonObject(with: self, options: options) }
+        catch { Logger.debug(error) }
+        return nil
+    }
+}
+
+extension String {
+    var data: Data? { self.data(using: .utf8) }
 }
index 6794963..73f94bc 100644 (file)
@@ -110,8 +110,8 @@ class BasePresentView2: UIView {
     }
     func show(animate:Bool = true) -> Void {
         self.layer.opacity = 1
-        App.shared.window?.addSubview(self)
-
+//        App.shared.window?.addSubview(self)
+        App.shared.topVC().view.addSubview(self)
     }
     
     @objc func hide() -> Void {
index 979cc38..2b03d61 100644 (file)
@@ -55,6 +55,6 @@ class BaseTC:UITabBarController{
         self.tabBar.backgroundColor = .white
         view.backgroundColor = .color(.bgColor)
 
-//        self.selectedIndex = 4
+//        self.selectedIndex = 2
     }
 }
index 201cfee..abad918 100644 (file)
@@ -69,15 +69,15 @@ class CustomerHeaderView: BaseView {
             bgView.addSubview(label)
             totalHeight = label.bottom + 12
             
-            if item !== vm.list.last {
-                let line = UIView()
-                line.backgroundColor = .hexString("#F2F2F2")
-                line.height = 1
-                line.width = kScreenWid - 2*70
-                line.left = 10
-                line.top = totalHeight - 6
-                bgView.addSubview(line)
-            }
+//            if item !== vm.list.last {
+//                let line = UIView()
+//                line.backgroundColor = .hexString("#F2F2F2")
+//                line.height = 1
+//                line.width = kScreenWid - 2*70
+//                line.left = 10
+//                line.top = totalHeight - 6
+//                bgView.addSubview(line)
+//            }
             
             label.add(target: self, action: #selector(tapAction(_:)))
         }
index b91e401..2ca35b6 100644 (file)
@@ -11,7 +11,7 @@ class CustomerVC:BaseVC{
     let toolBar = SendToolBar()
     let qaView = CustomerHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 195))
     let tableView = UITableView(frame: CGRectZero, style: .plain)
-    var dataList:[FeedbackContentModel] = []
+    var dataList:[Any] = []
     override func viewDidLoad() {
         super.viewDidLoad()
     }
@@ -31,6 +31,7 @@ class CustomerVC:BaseVC{
             v.separatorStyle = .none
             v.tableHeaderView = qaView
             v.register(FeedbackContentViewCell.self, forCellReuseIdentifier: FeedbackContentViewCell.reuseID)
+            v.register(FeedbackContentImageCell.self, forCellReuseIdentifier: FeedbackContentImageCell.reuseID)
         }
         toolBar.do { v in
             v.textField.text = ""
@@ -99,9 +100,18 @@ extension CustomerVC:UITableViewDelegate,UITableViewDataSource {
     }
     
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell = FeedbackContentViewCell.cell(withTableView: tableView, indexPath: indexPath)
-        cell.data = dataList[indexPath.row]
-        return cell
+        let data = dataList[indexPath.row]
+        if let model = data as? FeedbackContentModel  {
+            let cell = FeedbackContentViewCell.cell(withTableView: tableView, indexPath: indexPath)
+            cell.data = model
+            return cell
+        }
+        else if let model = data as? UIImage{
+            let cell = FeedbackContentImageCell.cell(withTableView: tableView, indexPath: indexPath)
+            cell.imgView.image = model
+            return cell
+        }
+        return UITableViewCell()
     }
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         
@@ -111,7 +121,9 @@ extension CustomerVC:SendToolBarDelegate{
     func sendToolBar(_ toolBar: SendToolBar, _ text: String) {
         toolBar.textField.resignFirstResponder()
         dataList.append(FeedbackContentModel(content: text,isSend: true))
-        dataList.append(FeedbackContentModel(content: "请加企业微信:123456",isSend: false))
+        dataList.append(FeedbackContentModel(content: "请加企业客服微信具体解答您的问题!",isSend: false))
+        dataList.append(UIImage(named: "server_qr")!)
+        
         refreshData()
         toolBar.textField.text = ""
         
index cd4297c..f6e5c66 100644 (file)
@@ -15,7 +15,12 @@ class CallingRecordVC:BaseVC{
     var messageList : [(String,UInt)] = []
     var recordFilePath : String?
 
+    var autoStart = false
     
+    init(autoStart :Bool = false) {
+        self.autoStart = autoStart
+        super.init()
+    }
     override func viewDidLoad() {
         super.viewDidLoad()
     }
@@ -56,6 +61,9 @@ class CallingRecordVC:BaseVC{
     }
     override func setupData() {
         JoyGemCallManager.shared().delegate = self
+        if autoStart{
+            startRecord()
+        }
     }
 
     override func viewDidAppear(_ animated: Bool) {
@@ -97,6 +105,12 @@ class CallingRecordVC:BaseVC{
 //            debugPrint("播放音频时发生错误: \(error.localizedDescription)")
 //        }
     }
+    func startRecord(){
+        toolBar.recordBtnAction()
+    }
+    func stopRecord(){
+        toolBar.recordBtnAction()
+    }
 }
 
 extension CallingRecordVC:FieldRecordBarDelegate{
@@ -121,7 +135,7 @@ extension CallingRecordVC:FieldRecordBarDelegate{
                 let v = PopTextField()
                 v.show()
                 v.cancelTap = {
-                    
+                    App.shared.popPage()
                 }
                 v.okTap = { [weak self]  text in
                     guard let self = self else{return}
index b47b374..6a89517 100644 (file)
@@ -13,7 +13,7 @@ class ChatHeaderView: BaseView {
     
     var role:JoyGemSpeaker!{
         didSet{
-//            titleLabel.text = role.name
+            titleLabel.text = "嗨!我是" + role.name
             icon.image = UIImage(named: "role_" + role.role)
         }
     }
index 2213ff8..e036073 100644 (file)
@@ -66,7 +66,7 @@ class ChatVC:BaseVC{
             make.bottom.equalToSuperview().inset(30)
         }
         tableView.snp.makeConstraints { make in
-            make.top.equalToSuperview().inset(80)
+            make.top.equalToSuperview().inset(kNavBtm)
             make.left.right.equalToSuperview()
             make.bottom.equalTo(toolBar.snp.top)
         }
@@ -129,8 +129,18 @@ class ChatVC:BaseVC{
             guard let self = self,speakers.count > 0 else{return}
             self.roleList = speakers
             self.roleList.insert(xiaoYinRole(), at: 0)
-            self.roleItem.role = roleList.first
-            self.headerView.role = roleList.first
+            
+            var currentRole = roleList.first
+            if let cacheRole = RoleCache.get(){
+                for item in roleList{
+                    if item.role == cacheRole {
+                        currentRole = item
+                        break
+                    }
+                }
+            }            
+            self.roleItem.role = currentRole
+            self.headerView.role = currentRole
             JoyGemChatManager.shared().setSpeaker(self.roleItem.role)
         }
     }
index 1f5b700..374589a 100644 (file)
@@ -22,8 +22,9 @@ class NavigationBarItem: BaseView {
             v.textColor = .rgb(0x121212)
             v.font = .bold(14)
             v.text = "智能体"
-            v.isHidden = true
+            
         }
+        isHidden = true
     }
     
     override func setupLayout() {
index 752faa2..0584d3c 100644 (file)
@@ -74,6 +74,7 @@ extension RoleListVC:UITableViewDelegate,UITableViewDataSource {
     }
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
         let data = list[indexPath.row]
+        RoleCache.save(type: data.role)
         didSelected?(data)
         navigationController?.popViewController(animated: true)
     }
index d7e67c8..29aee02 100644 (file)
@@ -27,6 +27,8 @@ class Chinese2EnglishVC:BaseVC{
         
         toolBar.delegate = self
         toolBar.isChienseEnglish = true
+        toolBar.leftItem.valueLabel.text = "左耳"
+        toolBar.rightItem.valueLabel.text = "右耳"
         
         tableView.backgroundColor = .clear
         tableView.delegate = self
index 585beb2..8a68ff3 100644 (file)
@@ -51,8 +51,12 @@ class HomeDeviceVC:BaseVC{
      func reloadData() {
         DeviceVM.shared.refresh {[weak self] result in
             self?.collectionView.reloadData()
-            if !BleManager.shared.isConnetd,let model = DeviceVM.shared.dataList.first{
-                self?.startConectBle(model)
+            if !BleManager.shared.isConnetd,let lastMac = DeviceCache.getLastConnected(){
+                for item in DeviceVM.shared.dataList {
+                    if item.mac ==  lastMac{
+                        self?.startConectBle(item)
+                    }
+                }
             }
         }
         CacheManager.shared.user.tokenIsValid(){[weak self] in
@@ -122,14 +126,6 @@ extension HomeDeviceVC:UICollectionViewDataSource,UICollectionViewDelegate,UICol
         return cell
     }
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-//        let model = DeviceVM.shared.dataList[indexPath.row]
-//        if BleManager.shared.isConected(mac: model.mac) {
-//            App.shared.goToPage(HomeVC(device: model))
-//            return
-//        }
-//        ConnectPopView.shared.stateDidChange(.connecting)
-//        startConectBle(model,autoJump: true)
-        
         let model = DeviceVM.shared.dataList[indexPath.row]
         if !BleManager.shared.isConected(mac: model.mac) {
             startConectBle(model,autoJump: false)
index dcaf819..57dcd27 100644 (file)
@@ -89,7 +89,7 @@ class DialogTranslateVC:BaseVC{
         }
     }
     override func navRightViewTapped() {
-        let tip = RecordTipsView(type: .tongchuan)
+        let tip = RecordTipsView(type: .dialog)
         tip.show()
     }
     override func viewDidAppear(_ animated: Bool) {
index 09d60b3..5f010a7 100644 (file)
@@ -14,7 +14,12 @@ class FieldRecordingVC:BaseVC{
     let rhythView = RhythView()
     var messageList : [(String,UInt)] = []
     var recordFilePath : String?
+    var autoStart = false
     
+    init(autoStart :Bool = false) {
+        self.autoStart = autoStart
+        super.init()
+    }
 
     override func setupViews() {
         navBar.title = "现场录音"
@@ -30,7 +35,6 @@ class FieldRecordingVC:BaseVC{
             v.contentInset = UIEdgeInsets(top: 0, left: 18, bottom: 0, right: 18)
         }
         view.addSubviews([rhythView,textView,toolBar])
-        
     }
     override func setupLayout() {
         rhythView.snp.makeConstraints { make in
@@ -59,6 +63,9 @@ class FieldRecordingVC:BaseVC{
         } catch {
             Logger.debug(error)
         }
+        if autoStart{
+            startRecord()
+        }
     }
 
     override func viewDidAppear(_ animated: Bool) {
@@ -87,6 +94,12 @@ class FieldRecordingVC:BaseVC{
         textView.scrollRangeToVisible(NSMakeRange(textView.text.count - 1, 1))        
 
     }
+    func startRecord(){
+        toolBar.recordBtnAction()
+    }
+    func stopRecord(){
+        toolBar.recordBtnAction()
+    }
 }
 
 extension FieldRecordingVC:FieldRecordBarDelegate{
@@ -119,7 +132,7 @@ extension FieldRecordingVC:FieldRecordBarDelegate{
                 let v = PopTextField()
                 v.show()
                 v.cancelTap = {
-                    
+                    App.shared.popPage()
                 }
                 v.okTap = { [weak self]  text in
                     guard let self = self else{return}
@@ -172,7 +185,7 @@ extension FieldRecordingVC : JoyGemRecordManagerDelegate {
     
     
     func recordManager(_ manager: JoyGemRecordManager, update mode: JoyGemRecordMode) {
-        Logger.debug("mode: \(mode)")
+        Logger.debug("update mode: \(mode)")
     }
     
     func recordManager(_ manager: JoyGemRecordManager, saveFile path: String) {
@@ -181,11 +194,12 @@ extension FieldRecordingVC : JoyGemRecordManagerDelegate {
     }
     
     func recordManager(_ manager: JoyGemRecordManager, stateChange code: JoyGemStateCode) {
-        Logger.debug("code: \(code)")
+        Logger.debug("stateChange: \(code)")
     }
     
     
     func recordManagerStopped(_ manager: JoyGemRecordManager, reason code: JoyGemRecordStopCode) {
+        Logger.debug("stop reason: \(code)")
         if (code == .actively) {
 //            YLprogressHUD.showAutoHiden("用户主动结束")
 //            toolBar.recordBtn.stopLoading()
@@ -204,7 +218,7 @@ extension FieldRecordingVC : JoyGemRecordManagerDelegate {
     }
     
     func recordManager(_ manager: JoyGemRecordManager, onError code: JoyGemErrorCode) {
-        
+        Logger.debug("onError: \(code)")
     }
 }
 
index a866a7c..25cf978 100644 (file)
@@ -41,6 +41,9 @@ extension FileSaver{
             for fileURL in files {
                 
                 if !zipArchive.addFile(toZip: fileURL, newname: URL(fileURLWithPath: fileURL).lastPathComponent ) {
+                    if !FileManager.default.fileExists(atPath: fileURL){
+                        Logger.debug("文件不存在",fileURL)
+                    }
                     Logger.debug("Failed to add file: \(fileURL)")
                         zipArchive.closeZipFile2()
                         return nil
index 6f4090e..b3052f4 100644 (file)
@@ -31,7 +31,12 @@ class HistoryRecordCell: BaseTableViewCell {
         didSet{
             guard let localModel = localModel else { return  }
             titleLabel.text = localModel.name
-            dateLabel.text = localModel.createTime
+            if localModel.createTime.count > 20{
+                dateLabel.text = String(localModel.createTime.prefix(19))
+            }
+            else{
+                dateLabel.text = localModel.createTime
+            }
             typeLabel.text = localModel.type.title
             durationLabel.text = YLToos.formatSeconds(localModel.duration)
             titleLabel.textColor = localModel.favorite == "0" ? UIColor.hexString("#121212"):.color(.theme)
@@ -85,6 +90,8 @@ class HistoryRecordCell: BaseTableViewCell {
             v.text = "2025-06-02 10:28"
         }
         collectionIcon.do { v in
+//            v.backgroundColor = .red
+            v.contentMode = .center
             v.yc.addTap(target: self, action: #selector(collectionAction))
         }
         playIcon.do { v in
@@ -112,8 +119,8 @@ class HistoryRecordCell: BaseTableViewCell {
             m.right.lessThanOrEqualTo(typeLabel.snp.left).offset(-50)
         }
         collectionIcon.snp.makeConstraints { (m) in
-            m.size.equalTo(16)
-            m.left.equalTo(titleLabel.snp.right).offset(8)
+            m.size.equalTo(32)
+            m.left.equalTo(titleLabel.snp.right)
             m.centerY.equalTo(titleLabel)
         }
         
@@ -133,7 +140,7 @@ class HistoryRecordCell: BaseTableViewCell {
     @objc func collectionAction(){
         if let model = model {
             model.favorite = model.favorite == "0" ? "1":"0"
-            collectionIcon.image = UIImage(named: model.favorite == "0" ? "collection_normal":"collection_selected")
+            self.model = model
             
             var params:[String:Any] = [:]
             params["recordId"] = model.id
@@ -143,8 +150,9 @@ class HistoryRecordCell: BaseTableViewCell {
             }
         }
         else if let localModel = localModel{
+            
             localModel.favorite = localModel.favorite == "0" ? "1":"0"
-            collectionIcon.image = UIImage(named: localModel.favorite == "0" ? "collection_normal":"collection_selected")
+            self.localModel = localModel
             RecordCache.shared.add(localModel)
         }
     }
index a41484e..752e355 100644 (file)
@@ -42,9 +42,51 @@ class RecordHistoryModel:HandyJSON{
     required public init() { }
 }
 
+
+
 class RecordHistorySelectedModel:HandyJSON{
     var isSelcted = false
     var model = RecordDetailModel()
 
     required public init() { }
 }
+
+class CloudSelectedModel:HandyJSON{
+    var isSelcted = false
+    var model = RecordHistoryModel()
+    
+    required public init() { }
+}
+
+
+/// 录音详情
+class CloudRecordDetailRoot:ResponseBaseModel {
+    var data = CloudRecordDetailData()
+}
+class CloudRecordDetailData:HandyJSON {
+    var list = [CloudRecordDetail]()
+    var total = 0
+    var pageSize = 0
+    var currentPage = 0
+    var totalPage = 0
+    var hasNext = false
+    var hasPre = false
+    
+    required public init() { }
+}
+
+class CloudRecordDetail:HandyJSON{
+    var type:RecordType = .present
+    var id = ""
+    var recordId = ""
+    var text = ""
+    var speakerName = ""
+    var translateText = ""
+    var sourceLanguage = ""
+    var targetLanguage = ""
+    var left = false
+    var clientTime = 0
+    var createTime = ""
+    var updateTime = ""
+    required public init() { }
+}
index ebb8676..55b6899 100644 (file)
@@ -11,7 +11,7 @@ import MJRefresh
 class CloudRecordVC: BaseVC{
     let tableView = UITableView(frame: .zero, style: .plain)
     let vm = HistoryRecordVM()
-    var list = [RecordHistoryModel]()
+//    var list = [RecordHistoryModel]()
     
     override func viewDidLoad() {
         super.viewDidLoad()
@@ -24,7 +24,8 @@ class CloudRecordVC: BaseVC{
     override func setupViews() {
         navBar.do { v in
             v.title = "云存储空间"
-            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction)),NavigationRightItem(image: UIImage(named: "search"), target: self,action: #selector(searchAction))]
+//            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction)),NavigationRightItem(image: UIImage(named: "search"), target: self,action: #selector(searchAction))]
+            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction))]
             v.setupRightViews(items)
         }
         
@@ -88,6 +89,81 @@ class CloudRecordVC: BaseVC{
             }
         }
     }
+    func longpressAction(cell:HistoryRecordCell){
+        let window = App.shared.window
+        let rect = cell.superview!.convert(cell.frame, to: window)
+        let top = CGRectGetMaxY(rect)
+        Logger.debug(rect,top)
+        
+        let model = cell.model!
+        
+        let v = RecordPopView()
+        v.contentTop = top
+        v.show()
+        v.hidenCallback = {
+            cell.bgView.backgroundColor = .white
+        }
+        v.shareCallback = {
+            App.shared.goToPage(RecordShareVC(cloudList: [model]))
+        }
+        v.renameCallback = {[weak self] in
+            let v = PopTextField()
+            v.titleLabel.text = "重命名"
+            v.textFiled.text = model.name
+            v.cancelButton.setTitle("取消", for: .normal)
+            v.show()
+            v.cancelTap = {
+                
+            }
+            v.okTap = { [weak self]  text in
+                guard let self = self else{return}
+                model.name = text
+                tableView.reloadData()
+                var params:[String:Any] = [:]
+                params["id"] = model.id
+                params["name"] = model.name
+                let api = CommomApi.updateVoiceRecord(param: params)
+                HttpClient.request(api) {(model:ResponseBaseModel,res) in
+                    
+                }
+            }
+        }
+        v.deleteCallback = {[weak self] in
+            self?.deleteAction(model)
+        }
+        v.selectedCallback = { [weak self] in
+            guard let self = self else{return}
+            let vc = CloudSelectedVC(data: vm.list)
+            vc.deleteCallback = { [weak self] deleteList in
+                guard let self = self else{return}
+                for item in deleteList{
+                    vm.list.removeAll(where: {$0.id == item.id})
+                }
+                tableView.reloadData()
+            }
+            App.shared.goToPage(vc,animated: false)
+        }
+    }
+    func deleteAction(_ model:RecordHistoryModel){
+        CustomAlert.showWith(title: "您要删除这条录音吗?", messgage: "删除后,此记录将无法恢复。", cancelCallback: {}) {[weak self] in
+            guard let self = self else{return}
+            YLprogressHUD.hidden()
+            vm.list.removeAll(where: {$0.id == model.id})
+            tableView.reloadData()
+            HttpClient.request( CommomApi.deleteVoiceRecord(recordId: model.id)) {(result:ResponseBaseModel,res) in
+            }
+        }
+    }
+    func deleteAction(indexPath:IndexPath){
+        CustomAlert.showWith(title: "您要删除这条录音吗?", messgage: "删除后,此记录将无法恢复。", cancelCallback: {}) {[weak self] in
+            guard let self = self else{return}
+            let model = vm.list[indexPath.row]
+            vm.list.removeAll(where: {$0.id == model.id})
+            tableView.deleteRows(at: [indexPath], with:.fade)
+            HttpClient.request(CommomApi.deleteVoiceRecord(recordId: model.id)) {(result:ResponseBaseModel,res) in
+            }
+        }
+    }
 }
 
 extension CloudRecordVC:UITableViewDelegate,UITableViewDataSource {
@@ -98,6 +174,9 @@ extension CloudRecordVC:UITableViewDelegate,UITableViewDataSource {
     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let cell = HistoryRecordCell.cell(withTableView: tableView, indexPath: indexPath)
         cell.model = vm.list[indexPath.row]
+        cell.longPressCallback = {[weak self] cell in
+            self?.longpressAction(cell: cell)
+        }
         return cell
     }
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@@ -128,10 +207,7 @@ extension CloudRecordVC:UITableViewDelegate,UITableViewDataSource {
     // 实现滑动删除功能
     func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
         if editingStyle == .delete {
-            // 从数据源中移除对应数据
-            vm.list.remove(at: indexPath.row)
-            // 从表格中删除对应行
-            tableView.deleteRows(at: [indexPath], with:.fade)
+            deleteAction(indexPath: indexPath)
         }
     }
     
@@ -139,4 +215,7 @@ extension CloudRecordVC:UITableViewDelegate,UITableViewDataSource {
     func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
         return true
     }
+    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
+        return "删除"
+    }
 }
index 2079f98..0799459 100644 (file)
@@ -24,7 +24,8 @@ class HistoryRecordVC: BaseVC{
     override func setupViews() {
         navBar.do { v in
             v.title = "历史记录"
-            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction)),NavigationRightItem(image: UIImage(named: "search"), target: self,action: #selector(searchAction))]
+//            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction)),NavigationRightItem(image: UIImage(named: "search"), target: self,action: #selector(searchAction))]
+            let items = [NavigationRightItem(image: UIImage(named: "filter"),target: self, action: #selector(filterAction))]
             v.setupRightViews(items)
         }
         
@@ -93,6 +94,7 @@ class HistoryRecordVC: BaseVC{
         }
         v.renameCallback = {[weak self] in
             let v = PopTextField()
+            v.titleLabel.text = "重命名"
             v.textFiled.text = model.name
             v.cancelButton.setTitle("取消", for: .normal)
             v.show()
@@ -149,18 +151,22 @@ extension HistoryRecordVC:UITableViewDelegate,UITableViewDataSource {
         let data = list[indexPath.row]
         App.shared.goToPage(RecordDetailVC(record: data,needFrontVC:true))
     }
-    // 实现滑动删除功能
     func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
         if editingStyle == .delete {
-            // 从数据源中移除对应数据
-            list.remove(at: indexPath.row)
-            // 从表格中删除对应行
-            tableView.deleteRows(at: [indexPath], with:.fade)
+            CustomAlert.showWith(title: "您要删除这条录音吗?", messgage: "删除后,此记录将无法恢复。", cancelCallback: {}) {[weak self] in
+                guard let self = self else{return}
+                RecordCache.shared.remove(list[indexPath.row])
+                list.remove(at: indexPath.row)
+                tableView.deleteRows(at: [indexPath], with:.fade)
+            }
+
         }
     }
-    
-    // 允许编辑
     func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
         return true
     }
+    func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
+        return "删除"
+    }
+
 }
diff --git a/ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedCell.swift b/ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedCell.swift
new file mode 100644 (file)
index 0000000..0804a5b
--- /dev/null
@@ -0,0 +1,170 @@
+//
+//  CloudSelectedCell.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/11/7.
+//
+
+class CloudSelectedCell: BaseTableViewCell {
+    let selectedIcon = UIImageView()
+    let bgView = UIView()
+    let playIcon = UIImageView()
+    let titleLabel = UILabel()
+    let collectionIcon = UIImageView()
+    let durationLabel = UILabel()
+    let dateLabel = UILabel()
+    let typeLabel = UILabel()
+    var selectedCallback:((_ cell:CloudSelectedCell)->Void)?
+    
+        var cloudModel:CloudSelectedModel?{
+            didSet{
+                guard let model = cloudModel?.model else { return  }
+                titleLabel.text = model.name
+                dateLabel.text = model.createTime
+                typeLabel.text = model.type.title
+                durationLabel.text = YLToos.formatSeconds(model.duration)
+                titleLabel.textColor = model.favorite == "0" ? UIColor.hexString("#121212"):.color(.theme)
+                collectionIcon.image = UIImage(named: model.favorite == "0" ? "collection_normal":"collection_selected")
+                selectedIcon.image = UIImage(named: cloudModel!.isSelcted ? "btn_selected":"btn_normal")
+            }
+        }
+//    var localModel:RecordHistorySelectedModel?{
+//        didSet{
+//            guard let localModel = localModel else { return  }
+//            titleLabel.text = localModel.model.name
+//            dateLabel.text = localModel.model.createTime
+//            typeLabel.text = localModel.model.type.title
+//            durationLabel.text = YLToos.formatSeconds(localModel.model.duration)
+//            titleLabel.textColor = localModel.model.favorite == "0" ? UIColor.hexString("#121212"):.color(.theme)
+//            collectionIcon.image = UIImage(named: localModel.model.favorite == "0" ? "collection_normal":"collection_selected")
+//            selectedIcon.image = UIImage(named: localModel.isSelcted ? "btn_selected":"btn_normal")
+//        }
+//    }
+    
+    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.addSubviews([selectedIcon,bgView])
+        bgView.addSubviews([playIcon,titleLabel,durationLabel,collectionIcon,typeLabel,dateLabel])
+        
+        backgroundColor = .rgb(0xF7F7F7)
+        contentView.backgroundColor = .clear
+        selectionStyle = .none
+        bgView.do { v in
+            v.backgroundColor = UIColor.white
+            v.layer.cornerRadius = 12
+            v.layer.masksToBounds = true
+        }
+        titleLabel.do { (v) in
+            v.textColor = .rgb(0x121212)
+            v.font = .bold(16)
+            v.textAlignment = .left
+            v.text = "周一会议总结"
+        }
+        durationLabel.do { (v) in
+            v.textColor = .rgb(0x666666)
+            v.font = .regular(12)
+            v.textAlignment = .left
+            v.text = "00:32:27"
+        }
+        typeLabel.do { (v) in
+            v.textColor = .rgb(0x666666)
+            v.font = .regular(12)
+            v.textAlignment = .left
+            v.text = "现场录音"
+        }
+        dateLabel.do { (v) in
+            v.textColor = .rgb(0x666666)
+            v.font = .regular(12)
+            v.textAlignment = .left
+            v.text = "2025-06-02 10:28"
+        }
+        collectionIcon.do { v in
+            v.yc.addTap(target: self, action: #selector(collectionAction))
+        }
+        playIcon.do { v in
+            v.image = UIImage(named: "record_play 2")
+        }
+        selectedIcon.do { v in
+            v.image = UIImage(named: "btn_normal")
+            v.contentMode = .center
+            v.yc.addTap(target: self, action: #selector(selectedAction))
+        }
+    }
+    
+    override func setupLayout() {
+        selectedIcon.snp.makeConstraints { (m) in
+            m.size.equalTo(54)
+            m.left.equalToSuperview().inset(0)
+            m.centerY.equalToSuperview()
+        }
+        bgView.snp.makeConstraints { (m) in
+            m.left.equalToSuperview().inset(54)
+            m.right.equalToSuperview().inset(15)
+            m.top.equalToSuperview().inset(5)
+            m.bottom.equalToSuperview().inset(5)
+            m.height.equalTo(74)
+        }
+        
+        playIcon.snp.makeConstraints { (m) in
+            m.width.size.equalTo(30)
+            m.left.equalToSuperview().inset(14)
+            m.centerY.equalToSuperview()
+        }
+        titleLabel.snp.makeConstraints { (m) in
+            m.top.equalTo(16)
+            m.left.equalTo(playIcon.snp.right).offset(6)
+            m.right.lessThanOrEqualTo(typeLabel.snp.left).offset(-50)
+        }
+        collectionIcon.snp.makeConstraints { (m) in
+            m.size.equalTo(16)
+            m.left.equalTo(titleLabel.snp.right).offset(8)
+            m.centerY.equalTo(titleLabel)
+        }
+        
+        durationLabel.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(16)
+            m.left.equalTo(titleLabel)
+        }
+        typeLabel.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(16)
+            m.right.equalToSuperview().inset(14)
+        }
+        dateLabel.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(16)
+            m.right.equalTo(typeLabel)
+        }
+    }
+    @objc func collectionAction(){
+        //        if let model = model {
+        //            model.favorite = model.favorite == "0" ? "1":"0"
+        //            collectionIcon.image = UIImage(named: model.favorite == "0" ? "collection_normal":"collection_selected")
+        //
+        //            var params:[String:Any] = [:]
+        //            params["recordId"] = model.id
+        //            params["favorite"] = model.favorite
+        //            let api = CommomApi.voiceRecordCollection(param: params)
+        //            HttpClient.request(api) { (model:RecordHistoryModelRoot,res) in
+        //            }
+        //        }
+        //        else
+        //        if let localModel = localModel{
+        //            localModel.model.favorite = localModel.model.favorite == "0" ? "1":"0"
+        //            collectionIcon.image = UIImage(named: localModel.model.favorite == "0" ? "collection_normal":"collection_selected")
+        //            RecordCache.shared.add(localModel.model)
+        //        }
+    }
+    @objc func selectedAction(){
+        if let mode = cloudModel{
+            mode.isSelcted = !mode.isSelcted
+            self.cloudModel = mode
+        }
+        selectedCallback?(self)
+    }
+    
+}
diff --git a/ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedVC.swift b/ShenYin/ShenYin/UI/Home/HistoryRecord/search/CloudSelectedVC.swift
new file mode 100644 (file)
index 0000000..24e0fb5
--- /dev/null
@@ -0,0 +1,201 @@
+//
+//  CloudSelectedVC.swift
+//  ShenYin
+//
+//  Created by liangshi on 2025/11/7.
+//
+
+import UIKit
+class CloudSelectedVC: BaseVC{
+    let tableView = UITableView(frame: .zero, style: .plain)
+    let bottomView = HistorySearchBottomView()
+    var list = [CloudSelectedModel]()
+    var deleteList = [RecordHistoryModel]()
+    var remainDeleteList = [RecordHistoryModel]()
+    var deleteCallback:((_ list:[RecordHistoryModel])->Void)?
+    
+    init(data:[RecordHistoryModel]) {
+        var tempList = [CloudSelectedModel]()
+        for item in data {
+            let model = CloudSelectedModel()
+            model.model = item
+            tempList.append(model)
+        }
+        list = tempList
+        tableView.reloadData()
+        super.init()
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+        tableView.reloadData()
+    }
+    override func setupViews() {
+        navBar.do { v in
+            v.titleLabel.font = .bold(16)
+            v.title = "已选择0项"
+            //            v.leftView.backgroundColor = .red
+            v.leftView.setImage(nil, for: .normal)
+            v.rightView.isHidden = false
+            //            v.rightView.backgroundColor = .red
+            
+            v.leftView.snp.remakeConstraints { (m) in
+                m.leading.equalToSuperview()
+                m.top.equalTo(kNavTop)
+                m.bottom.equalToSuperview()
+                m.width.greaterThanOrEqualTo(58)
+            }
+            v.rightView.snp.remakeConstraints { (m) in
+                m.right.equalToSuperview()
+                m.top.equalTo(kNavTop)
+                m.bottom.equalToSuperview()
+                m.width.greaterThanOrEqualTo(58)
+            }
+            
+            let leftLabel = UILabel()
+            leftLabel.text = "全选"
+            leftLabel.textColor = .hexString("#666666")
+            leftLabel.yc.setBorder(width: 1, color: .hexString("#666666"), radius: 11)
+            leftLabel.font = .regular(12)
+            leftLabel.textAlignment = .center
+            leftLabel.yc.addTap(target: self, action: #selector(allSelctedAction))
+            v.leftView.addSubview(leftLabel)
+            leftLabel.snp.remakeConstraints { (m) in
+                m.leading.equalToSuperview().inset(18)
+                m.height.equalTo(22)
+                m.centerY.equalToSuperview()
+                m.width.greaterThanOrEqualTo(40)
+            }
+            let rightLabel = UILabel()
+            rightLabel.textAlignment = .center
+            rightLabel.text = "完成"
+            rightLabel.textColor = .white
+            rightLabel.backgroundColor = .color(.theme)
+            rightLabel.font = .regular(12)
+            rightLabel.yc.setCornerRadius(11)
+            rightLabel.yc.addTap(target: self, action: #selector(doneAction))
+            
+            v.rightView.addSubview(rightLabel)
+            rightLabel.snp.remakeConstraints { (m) in
+                m.right.equalToSuperview().inset(18)
+                m.height.equalTo(22)
+                m.centerY.equalTo(v.titleLabel)
+                m.width.greaterThanOrEqualTo(40)
+            }
+        }
+        
+        tableView.do { v in
+            v.backgroundColor = .rgb(0xF7F7F7)
+            v.delegate = self
+            v.dataSource = self
+            v.estimatedRowHeight = 84
+            v.separatorStyle = .none
+            //            v.isEditing = true
+            v.register(CloudSelectedCell.self, forCellReuseIdentifier: CloudSelectedCell.reuseID)
+        }
+        bottomView.do { v in
+            v.outItem.yc.addTap(target: self, action: #selector(outputAction))
+            v.deleteItem.yc.addTap(target: self, action: #selector(deleteAction))
+        }
+        view.addSubviews([bottomView,tableView])
+    }
+    override func setupLayout() {
+        bottomView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.height.equalTo(95)
+        }
+        tableView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.top.equalTo(kNavBtm)
+            make.bottom.equalToSuperview().inset(95)
+        }
+    }
+    
+    
+    @objc func allSelctedAction(){
+        for item in list {
+            item.isSelcted = true
+        }
+        tableView.reloadData()
+        selectedAction()
+    }
+    @objc func doneAction(){
+        App.shared.popPage(animated: false)
+    }
+    func selectedAction(){
+        let selectedList = list.filter({$0.isSelcted})
+        navBar.title = "已选择\(selectedList.count)项"
+    }
+    @objc func outputAction(){
+        var tempList = [RecordHistoryModel]()
+        for item in list {
+            if item.isSelcted {
+                tempList.append(item.model)
+            }
+        }
+        App.shared.goToPage(RecordShareVC(cloudList: tempList))
+    }
+    @objc func deleteAction(){
+        var tempList = [RecordHistoryModel]()
+        for item in list {
+            if item.isSelcted {
+                tempList.append(item.model)
+            }
+        }
+        if tempList.count == 0 {
+            return
+        }
+        deleteList = tempList
+        remainDeleteList = tempList
+        CustomAlert.showWith(title: "您要删除这些录音吗?", messgage: "删除后,这些记录将无法恢复。", cancelCallback: {}) {[weak self] in
+            guard let self = self else{return}
+            YLprogressHUD.showLoading()
+            startDelete()
+        }
+    }
+    func startDelete(){
+        if remainDeleteList.count == 0 {
+            for item in deleteList{
+                list.removeAll(where: {$0.model.id == item.id})
+            }
+            deleteCallback?(deleteList)
+            tableView.reloadData()
+            selectedAction()
+            YLprogressHUD.hidden()
+            return
+        }
+        
+        let model = remainDeleteList.last!
+        HttpClient.request( CommomApi.deleteVoiceRecord(recordId: model.id)) {[weak self](result:ResponseBaseModel,res) in
+            guard let self = self else{return}
+            if result.isSuccess{
+                
+            }
+            else{
+                Logger.debug("删除失败",model.id)
+            }
+            remainDeleteList.removeLast()
+            startDelete()
+            
+        }
+    }
+}
+
+extension CloudSelectedVC:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = CloudSelectedCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.cloudModel = list[indexPath.row]
+        cell.selectedCallback = {[weak self] cell in
+            self?.selectedAction()
+        }
+        return cell
+    }
+}
index 9db7143..a564910 100644 (file)
@@ -156,7 +156,6 @@ class HistorySelectedVC: BaseVC{
             RecordCache.shared.remove(list:tempList)
             deleteCallback?(tempList)
             tableView.reloadData()
-            
         }
     }
 }
@@ -174,22 +173,4 @@ extension HistorySelectedVC:UITableViewDelegate,UITableViewDataSource {
         }
         return cell
     }
-//    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-//        let data = list[indexPath.row]
-//
-//    }
-//    // 实现滑动删除功能
-//    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
-//        if editingStyle == .delete {
-//            // 从数据源中移除对应数据
-//            list.remove(at: indexPath.row)
-//            // 从表格中删除对应行
-//            tableView.deleteRows(at: [indexPath], with:.fade)
-//        }
-//    }
-//    
-//    // 允许编辑
-//    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
-//        return true
-//    }
 }
index 837bccb..1099693 100644 (file)
@@ -239,7 +239,6 @@ class RecordDetailVC:BaseVC{
         HttpClient.request(api) {[weak self] (result:RecordHistoryDetailRoot,res) in
             guard let self = self else {return}
             if result.isSuccess{
-                YLprogressHUD.hidden()
                 let model = RecordDetailModel()
                 model.type = result.data.type
                 model.origin = result.data.summary
@@ -248,7 +247,7 @@ class RecordDetailVC:BaseVC{
                 model.name = result.data.name
                 model.createTime = result.data.createTime
                 self.data = model
-                setupViews(data: model)
+                loadDetail(remoteModel: data, localModel: model)
             }
             else{
                 YLprogressHUD.hidden()
@@ -256,6 +255,28 @@ class RecordDetailVC:BaseVC{
             }
         }
     }
+    func loadDetail(remoteModel:RecordHistoryModel,localModel:RecordDetailModel){
+        var params:[String:Any] = [:]
+        params["recordId"] = remoteModel.id
+        params["page"] = 1
+        let api = CommomApi.getVoiceRecordText(param: params)
+        HttpClient.request(api) {[weak self] (result:CloudRecordDetailRoot,res) in
+            guard let self = self else {return}
+            if result.isSuccess,let model = result.data.list.first{
+                YLprogressHUD.hidden()
+              
+                localModel.origin = model.text
+                localModel.translate = model.translateText
+                localModel.from = AiSupportLanguage(rawValue: model.sourceLanguage) ?? .chinse
+                localModel.to = AiSupportLanguage(rawValue: model.targetLanguage) ?? .english
+                setupViews(data: localModel)
+            }
+            else{
+                YLprogressHUD.hidden()
+                setupViews(data: localModel)
+            }
+        }
+    }
 }
 extension RecordDetailVC:RecordDetailTopBarDelegate{
     func recordDetailTopBarSummaryAction(_ bar: RecordDetailTopBar) {
@@ -267,6 +288,9 @@ extension RecordDetailVC:RecordDetailTopBarDelegate{
     
     func recordDetailBarTranstlateAction(_ bar: RecordDetailTopBar) {
         updateLayout()
+        if let data = data,data.translate.isEmpty {
+            translateAction()
+        }
     }
     
     func recordDetailTopBarOgrinAction(_ bar: RecordDetailTopBar) {
@@ -290,6 +314,7 @@ extension RecordDetailVC:RecordDetailBarDelegate{
     
     func recordDetailBarRenameAction(_ bar: RecordDetailBar) {
         let v = PopTextField()
+        v.titleLabel.text = "重命名"
         v.textFiled.text = data?.name ?? ""
         v.cancelButton.setTitle("取消", for: .normal)
         v.show()
@@ -417,12 +442,37 @@ extension RecordDetailVC{
         params["favorite"] = "0"
         params["duration"] = YLToos.getDuration(data!.path)
         params["fileId"] = fileId
-        params["summary"] = data!.origin
-        params["sourceLanguage"] = data!.from.value
-        params["targetLanguage"] = data!.to.value
+        params["summary"] = summaryView.content
+        
+//        Logger.debug(params)
+        HttpClient.request(.voiceRecord(param: params)) {[weak self](model:CommonDataModel,res) in
+            if model.isSuccess{
+//                self?.showUploadSuccess()
+                self?.commitDetail(model.data)
+            }
+            else{
+                YLprogressHUD.showAutoHiden("请求失败")
+            }
+        }
+    }
+    func commitDetail(_ recordId:String){
+        var textList:[String:Any] = [:]
+        textList["text"] = data!.origin
+        textList["translateText"] = data!.translate
+        textList["speakerName"] = CacheManager.shared.user.info.userName
+        textList["sourceLanguage"] = data!.from.value
+        textList["targetLanguage"] = data!.to.value
+        textList["createTime"] = Int(Date().timeIntervalSince1970)
+        textList["left"] = false
+        
+        var params:[String:Any] = [:]
+        params["recordId"] = recordId
+        params["textList"] = [
+            textList
+        ]
         
-        Logger.debug(params)
-        HttpClient.request(.voiceRecord(param: params)) {[weak self](model:AppUpdateModelRoot,res) in
+//        Logger.debug(params)
+        HttpClient.request(.voiceRecordText(param: params)) {[weak self](model:AppUpdateModelRoot,res) in
             if model.isSuccess{
                 self?.showUploadSuccess()
             }
index 1494743..3e71230 100644 (file)
@@ -28,6 +28,7 @@ class RecordTranslateVC:BaseVC{
             v.backgroundColor = .clear
             v.delegate = self
             v.recordBtn.activeView.backgroundColor = .hexString("#F7F7F7")
+            toolBar.rightItem.valueLabel.text = "手机"
         }
         view.backgroundColor = .hexString("#F7F7F7")
         
@@ -142,7 +143,7 @@ extension RecordTranslateVC:RecordBarDelegate{
                 let v = PopTextField()
                 v.show()
                 v.cancelTap = {
-                    
+                    App.shared.popPage()
                 }
                 v.okTap = { [weak self]  text in
                     guard let self = self else{return}
index 30434a7..6c3ba65 100644 (file)
@@ -26,7 +26,7 @@ class HomeBottomView: BaseView {
         titleLabel.do { (v) in
             v.textColor = .rgb(0x313230)
             v.font = .bold(18)
-            v.text = "历史录音"
+            v.text = "历史记录"
         }
         valueLabel.do { (v) in
             v.textColor = .rgb(0x8d8d8d)
index 5c867b3..e7d0b06 100644 (file)
@@ -212,12 +212,14 @@ class BleScanCell: BaseTableViewCell {
     let bgView = UIView()
     let icon = UIImageView()
     let titleLabel = UILabel()
+    let valueLabel = UILabel()
     
     var model:DCPeripheral!{
         didSet{
             titleLabel.text = model.device.name
-            titleLabel.text = titleLabel.text! + "\n" + model.mac
-            titleLabel.adjustsFontSizeToFitWidth = true
+//            titleLabel.text = titleLabel.text!
+            valueLabel.text = model.mac
+//            titleLabel.adjustsFontSizeToFitWidth = true
         }
     }
     
@@ -230,13 +232,13 @@ class BleScanCell: BaseTableViewCell {
     }
     override func setupViews() {
         contentView.addSubview(bgView)
-        bgView.addSubviews([titleLabel,icon])
+        bgView.addSubviews([titleLabel,icon,valueLabel])
         
         backgroundColor = .rgb(0xF7F7F7)
         contentView.backgroundColor = .clear
         selectionStyle = .none
         bgView.do { v in
-//            v.backgroundColor = UIColor.white
+            v.backgroundColor = UIColor.white
             v.layer.cornerRadius = 8
             v.layer.masksToBounds = true
         }
@@ -246,6 +248,12 @@ class BleScanCell: BaseTableViewCell {
             v.textAlignment = .left
             v.numberOfLines = 0
         }
+        valueLabel.do { (v) in
+            v.textColor = .rgb(0x666666)
+            v.font = .regular(13)
+            v.textAlignment = .left
+            v.numberOfLines = 0
+        }
         icon.image = UIImage(named: "scan_device")
     }
     
@@ -263,11 +271,14 @@ class BleScanCell: BaseTableViewCell {
             m.centerY.equalToSuperview()
         }
         titleLabel.snp.makeConstraints { (m) in
-            m.centerY.equalTo(icon)
+            m.top.equalToSuperview().inset(13)
+            m.left.equalTo(icon.snp.right).offset(15)
+            m.right.equalToSuperview().inset(15)
+        }
+        valueLabel.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(13)
             m.left.equalTo(icon.snp.right).offset(15)
             m.right.equalToSuperview().inset(15)
-            m.height.equalToSuperview()
         }
-        
     }
 }
index 10d790d..2bede18 100644 (file)
@@ -7,7 +7,7 @@
 
 import UIKit
 import IQKeyboardManagerSwift
-import netfox
+//import netfox
 class AppLaunch:NSObject{
     @MainActor static func start(){
 //        NFX.sharedInstance().start()
@@ -15,6 +15,9 @@ class AppLaunch:NSObject{
         JoySdkManager.shared.setupSdk()
         setupKeyboard()
         loadCache()
+        LoginVM.fetchCountryList {result in
+
+        }
         
 //        AppUpdateVM.shared.checkedUpdate()
     }
index 2cf9711..4c50b9b 100644 (file)
@@ -45,6 +45,7 @@ class BleManager: NSObject {
 }
 extension BleManager:CBCentralManagerDelegate{
     func centralManagerDidUpdateState(_ central: CBCentralManager) {
+        Logger.debug("蓝牙状态",central.state.rawValue)
         switch central.state {
         case.unknown:
             break
@@ -57,7 +58,8 @@ extension BleManager:CBCentralManagerDelegate{
         case.poweredOff:
             break
         case.poweredOn:
-            startScanDevice()
+//            startScanDevice()
+            checkConnect()
             break
         @unknown default:
             break
@@ -84,6 +86,8 @@ extension BleManager:CBCentralManagerDelegate{
     func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
         stopScanDevice()
         Logger.debug("蓝牙已连接 \(peripheral)")
+        DeviceCache.saveLastConnected(mac: connectPeripheral!.mac)
+        DeviceCache.shared.add(connectPeripheral!.device.identifier.uuidString, mac: connectPeripheral!.mac)
         peripheral.delegate = self
         peripheral.discoverServices([CBUUID(string: kJoyGemAIServiceUUID)]);
         self.isConnetd = true
@@ -175,9 +179,17 @@ extension BleManager{
     
     // MARK: - Public Methods
     func startScanDevice() {
-        centralManager.stopScan()
+//        centralManager.stopScan()
         Logger.debug("扫描中...")
+        Logger.debug("蓝牙状态",centralManager.state.rawValue)
         devices = []
+//        let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)])
+//        Logger.debug("已连接设备",list)
+//        for item in list {
+//            if let mac = DeviceCache.shared.getMac(item.identifier.uuidString){
+//                devices.append(DCPeripheral(device: item,mac: mac))
+//            }
+//        }
         
         centralManager.scanForPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)],options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
         discoverDeviceCallback?(devices)
@@ -243,17 +255,36 @@ extension BleManager : JoyGemAIManagerDelegate {
     }
     
     func joyGemAction(_ action: JoyGemActionMode) {
+        Logger.debug(action)
+        if !CacheManager.shared.user.isLogin{
+            return
+        }
         switch action {
         case .cancel:
             YLprogressHUD.showAutoHiden("请求关闭录音功能/通知关闭了对话")
+            if let topVC = App.shared.topVC(), let vc = topVC as? FieldRecordingVC {
+                vc.stopRecord()
+            }
+            if let topVC = App.shared.topVC(), let vc = topVC as? CallingRecordVC {
+                vc.stopRecord()
+            }
         case .recordLive:
             YLprogressHUD.showAutoHiden("请求开启现场录音")
+            if !App.shared.topVC().isKind(of: FieldRecordingVC.self) {
+                App.shared.goToPage(FieldRecordingVC(autoStart: true))
+            }
         case .recordCall:
             YLprogressHUD.showAutoHiden("请求开启通话录音")
+            if !App.shared.topVC().isKind(of: CallingRecordVC.self) {
+                App.shared.goToPage(CallingRecordVC(autoStart: true))
+            }
         case .si:
             YLprogressHUD.showAutoHiden( "请求开启同传听译")
         case .chat:
             YLprogressHUD.showAutoHiden( "通知开启了AI对话")
+            if !App.shared.topVC().isKind(of: ChatVC.self) {
+                App.shared.goToPage(ChatVC())
+            }
         @unknown default:
             break
         }
@@ -279,6 +310,8 @@ extension BleManager{
             return false
         }
     }
+    
+//    #连接有问题,应当获取设置里面已连接的设备
     func connect(mac:String, finished:@escaping ((Bool) -> Void)){
         BleManager.shared.cancel()
         BleManager.shared.discoverDeviceCallback = { list in
@@ -300,5 +333,21 @@ extension BleManager{
         }
         BleManager.shared.startScanDevice()
     }
-    
+//    func checkConnected(){
+//        if BleManager.shared.isConnetd {
+//            return
+//        }
+//        
+//        let list = centralManager.retrieveConnectedPeripherals(withServices: [CBUUID(string: kJoyGemAIServiceUUID)])
+//        for item in list {
+//            Logger.debug("当前状态",item.name ?? "",item.state)
+//            if let mac = DeviceCache.shared.getMac(item.identifier.uuidString){
+////                devices.append()
+//                BleManager.shared.connectPeripheral(DCPeripheral(device: item,mac: mac))
+//                break
+//            }
+//        }
+//        
+//        
+//    }
 }
index 904b077..05c96cb 100644 (file)
 //
 
 enum AppSupportLanguage{
-    case chinse
-    case english
-    case japanese
-    case korean
-    case french
-    case spanish
-    case portuguese
-    case indonesian
-    case russian
-    case malay
+    case china
+    case usa
+    case japan
+    case korea
+    case taiwan
+    case spani
+    case vietnam
+    case thailand
+    case malaysia
+    case philippines
+    case frence
+    case singapore
+    case indonesia
+    case russia
     
     static var all:[AppSupportLanguage]{
-        return [.chinse,.english,.japanese,.korean,.french,.spanish,.portuguese,.indonesian,.russian,.malay]
+        return [.china,.usa,.japan,.korea,.taiwan,.spani,.vietnam,.thailand,.malaysia,.philippines,.frence,.singapore,.indonesia,.russia]
     }
     var title:String{
         switch self {
-        case .chinse:
+        case .china:
             return "中文"
-        case .english:
-            return "英文"
-        case .japanese:
+        case .usa:
+            return "美国"
+        case .japan:
             return "日文"
-        case .korean:
+        case .korea:
             return "韩文"
-        case .french:
-            return "法语"
-        case .spanish:
-            return "西班牙文"
-        case .portuguese:
-            return "葡萄牙文"
-        case .indonesian:
+        case .taiwan:
+            return "中国台湾"
+        case .spani:
+            return "西班牙"
+        case .vietnam:
+            return "越南"
+        case .thailand:
+            return "泰国"
+        case .malaysia:
+            return "马来西亚"
+        case .philippines:
+            return "菲律宾"
+        case .frence:
+            return "法国"
+        case .singapore:
+            return "新加坡"
+        case .russia:
+            return "俄罗斯"
+        case .indonesia:
             return "印度尼西亚文"
-        case .russian:
-            return "俄文"
-        case .malay:
-            return "马来文"
+        }
+    }
+    var lanCode:String{
+        switch self {
+        case .china:
+            return "zh_CN"
+        case .usa:
+            return "en_US"
+        case .japan:
+            return "ja"
+        case .korea:
+            return "ko"
+        case .taiwan:
+            return "zh-TW"
+        case .spani:
+            return "es"
+        case .vietnam:
+            return "vi"
+        case .thailand:
+            return "th"
+        case .malaysia:
+            return "ms"
+        case .philippines:
+            return "tl"
+        case .frence:
+            return "fr"
+        case .singapore:
+            return "en"
+        case .russia:
+            return "ru"
+        case .indonesia:
+            return "id"
         }
     }
     var map:[String:String]{
         switch self {
-        case .chinse:
+        case .china:
+            return englishMap
+        case .usa:
+            return englishMap
+        case .japan:
+            return englishMap
+        case .korea:
+            return englishMap
+        case .taiwan:
+            return englishMap
+        case .spani:
+            return englishMap
+        case .vietnam:
+            return englishMap
+        case .thailand:
             return englishMap
-        case .english:
+        case .malaysia:
+            return englishMap
+        case .philippines:
+            return englishMap
+        case .frence:
+            return englishMap
+        case .singapore:
+            return englishMap
+        case .russia:
+            return englishMap
+        case .indonesia:
             return englishMap
-        case .japanese:
-            return japaneseMap
-        case .korean:
-            return koreanMap
-        case .french:
-            return frenchMap
-        case .spanish:
-            return spanishMap
-        case .portuguese:
-            return portugueseMap
-        case .indonesian:
-            return indonesianMap
-        case .russian:
-            return russianMap
-        case .malay:
-            return malayMap
         }
     }
 }
@@ -78,42 +130,42 @@ let englishMap:[String:String] = [
     "登录" : "login",
     "注册" : "register",
 ]
-let japaneseMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let koreanMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let frenchMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let spanishMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let portugueseMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let indonesianMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let russianMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
-let malayMap:[String:String] = [
-    "登录" : "login",
-    "注册" : "register",
-]
+//let japaneseMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let koreanMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let frenchMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let spanishMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let portugueseMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let indonesianMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let russianMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
+//let malayMap:[String:String] = [
+//    "登录" : "login",
+//    "注册" : "register",
+//]
 
 extension String{
     var l10n:String{
-        if let value = Config.appLanguage.map[self] {
+        if let value = DCConfig.appLanguage.map[self] {
             return value
         }
         else{
index 75d301a..ab2323a 100644 (file)
@@ -79,7 +79,7 @@ class FeedbackContentViewCell:BaseTableViewCell{
         contentView.backgroundColor = .rgb(0xF6F6F6)
         
         bgView.do { v in
-            v.yc.setCornerRadius(12)
+            v.yc.setCornerRadius(8)
         }
         originalLabel.do { v in
             v.font = .regular(14)
@@ -146,3 +146,49 @@ class FeedbackContentViewCell:BaseTableViewCell{
         }
     }
 }
+class FeedbackContentImageCell:BaseTableViewCell{
+    let bgView = UIView()
+    let imgView = UIImageView()
+    let icon = UIImageView()
+    
+    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.backgroundColor = .rgb(0xF6F6F6)
+        
+        bgView.do { v in
+            v.yc.setCornerRadius(8)
+            v.backgroundColor = .white
+        }
+
+        icon.do { v in
+            v.yc.setCornerRadius(18)
+        }
+//        imgView.do {v  in
+//            v.yc.setCornerRadius(12)
+//        }
+        contentView.addSubviews([bgView,icon])
+        bgView.addSubviews([imgView])
+    }
+    
+    override func setupLayout() {
+        bgView.snp.makeConstraints { make in
+            make.top.equalToSuperview().inset(0)
+            make.bottom.equalToSuperview().inset(10)
+            make.left.right.equalToSuperview().inset(60)
+            make.height.equalTo((kScreenWid-120)*1005/720)
+        }
+        
+        imgView.snp.makeConstraints { make in
+            make.top.bottom.equalToSuperview().inset(5)
+            make.left.right.equalToSuperview().inset(5)
+        }
+    }
+}
index e3cfc89..f04a820 100644 (file)
@@ -60,7 +60,7 @@ extension ContryListVC:UITableViewDelegate,UITableViewDataSource {
         else{
             cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.allCorners], cornerRadii: CGSize(width: 0, height: 0))
         }
-        cell.selectedIcon.isHidden = cell.country.name != currentType.name
+        cell.selectedIcon.isHidden = cell.country.id != currentType.id
         return cell
     }
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
index e226393..d88bfff 100644 (file)
@@ -129,7 +129,7 @@ extension ForgetVC{
                 self?.codeView.codeButton.start()
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(model.msg)
             }
         }
     }
@@ -169,7 +169,7 @@ extension ForgetVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index 74dee85..0caefa9 100644 (file)
@@ -109,6 +109,11 @@ class LoginVC:BaseVC{
 extension LoginVC{
 
     @objc func loginAction(){
+        self.view.endEditing(true)
+        if !agreeView.isAgree {
+            YLprogressHUD.showAutoHiden("请阅读用户协议以及隐私政策并点击同意")
+            return
+        }
         guard let phone = phoneView.textField.value else{
             YLprogressHUD.showAutoHiden("请输入正确的手机号码")
             return
@@ -151,7 +156,7 @@ extension LoginVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index 97ead59..0113088 100644 (file)
@@ -137,11 +137,15 @@ extension RegisterVC{
                 YLprogressHUD.hidden()
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(model.msg)
             }
         }
     }
     @objc func registerAction(){
+        if !agreeView.isAgree {
+            YLprogressHUD.showAutoHiden("请阅读用户协议以及隐私政策并点击同意")
+            return
+        }
         guard let phone = phoneView.textField.value else{
             YLprogressHUD.showAutoHiden("请输入正确的手机号码")
             return
@@ -186,7 +190,7 @@ extension RegisterVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index 0b1a74f..a2852a5 100644 (file)
@@ -140,7 +140,7 @@ extension SmsLoginVC{
                 YLprogressHUD.hidden()
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(model.msg)
             }
         }
     }
@@ -153,6 +153,10 @@ extension SmsLoginVC{
         }
     }
     func phoneLogin(){
+        if !agreeView.isAgree {
+            YLprogressHUD.showAutoHiden("请阅读用户协议以及隐私政策并点击同意")
+            return
+        }
         guard let phone = phoneView.textField.value else{
             YLprogressHUD.showAutoHiden("请输入正确的手机号码")
             return
@@ -176,7 +180,7 @@ extension SmsLoginVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
@@ -205,7 +209,7 @@ extension SmsLoginVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index a96be4b..61fdab7 100644 (file)
@@ -125,7 +125,7 @@ extension VerifyCodeVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
             
         }
index d721e79..ecfa7c2 100644 (file)
@@ -71,7 +71,7 @@ extension VerifyEmailVC{
                 YLprogressHUD.hidden()
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(model.msg)
             }
         }
     }
@@ -93,7 +93,7 @@ extension VerifyEmailVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index 38a7e0f..13a1785 100644 (file)
@@ -71,7 +71,7 @@ extension VerifyPhoneVC{
                 self?.codeView.codeButton.start()
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(model.msg)
             }
         }
     }
@@ -93,7 +93,7 @@ extension VerifyPhoneVC{
                 }
             }
             else{
-                YLprogressHUD.showAutoHiden("请求失败")
+                YLprogressHUD.showAutoHiden(result.msg)
             }
         }
     }
index 703ac59..726ef62 100644 (file)
@@ -12,6 +12,9 @@ class AgreeView: BaseView {
      let agreeValue = UILabel()
     let andlabel = UILabel()
     let useValue = UILabel()
+    var isAgree:Bool{
+        return agreeBtn.isSelected
+    }
     override func setupViews() {
         agreeBtn.do { (v) in
             v.isSelected = true
index 8b0a671..2e73ff7 100644 (file)
@@ -165,6 +165,7 @@ class ThirdLoginView: BaseView {
     }
     @objc func wechatAction(){
         Logger.debug("wechat action")
+        return
         guard IASignWithWeChat.shared.isInstalled else { return  }
 //        guard agreeAgreementBtn.isSelected else { return "请同意《App隐私政策》".asToastShow() }
         
index 9600c70..1e939e5 100644 (file)
@@ -89,4 +89,5 @@ class LoginVM:BaseVM{
             completion(model)
         }
     }
+    
 }
index 1d40f09..4bc55fc 100644 (file)
@@ -26,7 +26,7 @@ class RevokeVC:BaseVC{
             v.font = .regular(14)
             v.textColor = .hexString("#666666")
             v.numberOfLines = 0
-            let text = "请您确保您是有权进行本撤回同意隐私政策操作的相关当事人。撤回同意隐私政策,您将放弃以下资产或者权益:\n\n1.数据清空\n将会停止收集您的个人信息。您使用DeepChords应用过程中产生的数据将被清空;手机中DeepChords应用的缓存数据将被清除。\n\n2.设备解除绑定\nDeepChords账号中,所有设备会与您当前登录的账号解除绑定,并清除设备之前存储在服务器的数据。存储在物理设备中的数据请通过人工本地物理重置来清除。如果您需要重新使用设备,需要您再次进行绑定并且重新授权。\n\n3.其他\n此举还将撤回您对用户协议的同意,并退出DeepChor ds应用。\n\n请您知悉,撤回同意隐私政策不代表撤回同意前的相关行为和责任得到豁免或减轻。若您需要重新在该账号管理设备,需要您重新授权并绑定。请谨慎操作!"
+            let text = "请您确保您是有权进行本撤回同意隐私政策操作的相关当事人。撤回同意隐私政策,您将放弃以下资产或者权益:\n\n1.数据清空\n将会停止收集您的个人信息。您使用DeepChords应用过程中产生的数据将被清空;手机中DeepChords应用的缓存数据将被清除。\n\n2.设备解除绑定\nDeepChords账号中,所有设备会与您当前登录的账号解除绑定,并清除设备之前存储在服务器的数据。存储在物理设备中的数据请通过人工本地物理重置来清除。如果您需要重新使用设备,需要您再次进行绑定并且重新授权。\n\n3.其他\n此举还将撤回您对用户协议的同意,并退出DeepChords应用。\n\n请您知悉,撤回同意隐私政策不代表撤回同意前的相关行为和责任得到豁免或减轻。若您需要重新在该账号管理设备,需要您重新授权并绑定。请谨慎操作!"
             
             let attributedString = NSMutableAttributedString(string: text)
             let paragraphStyle = NSMutableParagraphStyle()
index 74281dd..be69b2d 100644 (file)
@@ -33,7 +33,7 @@ class MineHeaderView: BaseView {
         cloud.snp.makeConstraints { make in
             make.top.equalTo(userInfo.snp.bottom).offset(15)
             make.left.right.equalToSuperview().inset(18)
-            make.height.equalTo(46)
+            make.height.equalTo(56)
         }
         banner.snp.makeConstraints { (m) in
             m.height.equalTo(126)
@@ -173,18 +173,18 @@ class CloudStorageView: BaseView {
             m.centerY.equalToSuperview()
         }
         titleLabel.snp.makeConstraints { (m) in
-            m.top.equalToSuperview().inset(6)
+            m.centerY.equalTo(nameLabel)
             m.left.equalToSuperview().inset(54)
         }
         nameLabel.snp.makeConstraints { (m) in
-            m.centerY.equalTo(titleLabel)
+            m.top.equalToSuperview().inset(10)
             m.right.equalToSuperview().inset(14)
         }
         progressView.snp.makeConstraints { make in
             make.right.equalToSuperview().inset(14)
             make.left.equalToSuperview().inset(54)
             make.height.equalTo(6)
-            make.bottom.equalToSuperview().inset(8)
+            make.bottom.equalToSuperview().inset(12)
         }
 //        PopPlayView().show()
     }
index 00fd206..2da7d41 100644 (file)
@@ -7,8 +7,8 @@
 import UIKit
 class MineVC: BaseVC{
     let tableView = UITableView(frame: .zero, style: .plain)
-    let list:[MineCellType] = [.instructions,.update,.language,.more,.feeback,.about]
-    let headerView =  MineHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 317))
+    let list:[MineCellType] = [.instructions,.update,.more,.feeback,.about]
+    let headerView =  MineHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 327))
     
     override func viewDidLoad() {
         super.viewDidLoad()
index d90cef6..f139dde 100644 (file)
@@ -16,14 +16,19 @@ class AppUpdateVM:BaseVM{
         HttpClient.request(.otaTaskApp(param: params)) {[weak self](model:AppUpdateModelRoot,res) in
             YLprogressHUD.hidden()
             guard let self = self else {return}
-            if model.isSuccess,model.data.targetVersion.uppercased() > model.data.sourceVersion.uppercased(){
-                if model.data.updateType != "0"{
-                    //可选升级
-                    optionUpdate()
+            if model.isSuccess{
+                if model.data.targetVersion.uppercased() > model.data.sourceVersion.uppercased(){
+                    if model.data.updateType != "0"{
+                        //可选升级
+                        optionUpdate()
+                    }
+                    else{
+                        //强制升级
+                        forceUpdate()
+                    }
                 }
                 else{
-                   //强制升级
-                    forceUpdate()
+                    YLprogressHUD.showAutoHiden("已经是最新版本")
                 }
             }
             else{
@@ -40,7 +45,7 @@ class AppUpdateVM:BaseVM{
             }
             UIApplication.shared.open(url)
         }
-
+        
     }
     func forceUpdate(){
         CustomAlert.showWith(title: nil, messgage: "检测到新版本", ok: "前往更新",cancelCallback: nil) {
index dad9f5c..cf18ff4 100644 (file)
@@ -56,7 +56,7 @@ class UpdateVC:BaseVC{
     override func setupData() {
         DeviceVM.getVersion {[weak self] version in
             guard let self = self else{return}
-            let version = version ?? "--"
+            let version = version ?? " --"
             let allText = "当前版本\n" + "V\(version)"
             let attributedString = NSMutableAttributedString(string: allText)
             let paragraphStyle = NSMutableParagraphStyle()
@@ -70,7 +70,7 @@ class UpdateVC:BaseVC{
     }
     @objc func tapAction(){
         if !BleManager.shared.isConnetd{
-//            YLprogressHUD.showAutoHiden("")
+            YLprogressHUD.showAutoHiden("请先连接设备")
             return
         }
         BleUpdateVM.shared.checkedUpdate()
index 3a12ef4..ca26da4 100644 (file)
@@ -105,7 +105,8 @@ class CustomCell1: BaseTableViewCell {
                 valueLabel.text = info.gender.title
             }
             else if type == .area {
-                valueLabel.text = info.countryName
+//                valueLabel.text = info.countryName
+                valueLabel.text = info.cacheCountryName
             }
             else if type == .avatar{
                 valueIcon.kf.setImage(with:CacheManager.shared.user.info.avatar.yc.asUrl )
index f21e3a5..934fcff 100644 (file)
@@ -106,6 +106,8 @@ extension UserInfoVC{
     }
     func areaAction(){
         let vc = ContryListVC()
+        vc.currentType = CountryModel()
+        vc.currentType.id = CacheManager.shared.user.info.countryId
         vc.didSelected = {[weak  self] model in
             guard let self = self else{return}
             CacheManager.shared.user.info.countryName = model.name
@@ -161,7 +163,10 @@ extension UserInfoVC{
         CacheManager.shared.user.tokenIsValid(){[weak self] in
             self?.tableView.reloadData()
         }
-        
+        LoginVM.fetchCountryList {[weak self] result in
+            guard let self = self else{return}
+            self.tableView.reloadData()
+        }
     }
 }
 
diff --git a/ShenYin/ShenYin/UI/Mode/ModeListView.swift b/ShenYin/ShenYin/UI/Mode/ModeListView.swift
deleted file mode 100644 (file)
index 9e68620..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-//  ModeListView.swift
-//  ShenYin
-//
-//  Created by liangshi on 2025/8/12.
-//
-
-class ModeListView: BaseView {
-    let bottonView = UIView()
-    let tipsIcon = UIImageView()
-    let titleLabel = UILabel()
-    let valueLabel = UILabel()
-    
-    override func setupViews() {
-        addSubviews([bottonView])
-        bottonView.addSubviews([titleLabel,valueLabel,tipsIcon])
-        //        backgroundColor = .red
-        bottonView.do { v in
-            v.backgroundColor = .rgb(0xFAFAFA)
-            v.yc.setCornerRadius(30)
-        }
-        tipsIcon.do { v in
-            //            v.backgroundColor = .lightGray
-            v.image = UIImage(named: "home_recordHistory")
-        }
-        titleLabel.do { (v) in
-            v.textColor = .rgb(0x313230)
-            v.font = .bold(18)
-            v.text = "历史录音"
-        }
-        valueLabel.do { (v) in
-            v.textColor = .rgb(0x8d8d8d)
-            v.font = .regular(14)
-            v.text = "随时随地 一键开录"
-        }
-        
-        yc.addTap(target: self, action: #selector(tapAction))
-    }
-    
-    override func setupLayout() {
-        bottonView.snp.makeConstraints { make in
-            make.left.right.equalToSuperview().inset(15)
-            make.top.equalToSuperview()
-            make.bottom.equalToSuperview()
-            make.height.equalTo(116)
-        }
-        titleLabel.snp.makeConstraints { make in
-            make.left.equalToSuperview().inset(15)
-            make.top.equalTo(35)
-        }
-        valueLabel.snp.makeConstraints { make in
-            make.left.equalTo(titleLabel)
-            make.top.equalTo(65)
-        }
-        tipsIcon.snp.makeConstraints { make in
-            make.size.equalTo(50)
-            make.right.equalToSuperview().inset(15)
-            make.centerY.equalToSuperview()
-        }
-    }
-    @objc func tapAction(){
-        App.shared.goToPage(HistoryRecordVC())
-    }
-}
-
index d77f29d..9225023 100644 (file)
@@ -23,7 +23,7 @@ class ModeVC:BaseVC{
     }
     
     override func setupViews() {
-        self.navBar.title = "模式"
+        self.navBar.title = BleManager.shared.connectPeripheral?.device.name ?? ""
         navBar.backgroundColor = .clear
         view.backgroundColor = .color(.bgColor)
         
index d9a921b..65fe7ab 100644 (file)
@@ -46,7 +46,7 @@ class LogVC: BaseVC {
         formatter.dateFormat = "yyyyMMddHHmmss"
         let name = formatter.string(from: Date())
         
-        let filePath = "\(NSHomeDirectory())/Documents/ShenYin_\(name).txt"
+        let filePath = "\(NSHomeDirectory())/Documents/DeepChords_\(name).txt"
         let url = URL(fileURLWithPath: filePath)
         let data = self.textView.text.data(using:.utf8)
         do {
index f64b3fc..79121ae 100644 (file)
@@ -15,7 +15,8 @@ class YLprogressHUD {
         SVProgressHUD.setDefaultStyle(.dark)
         SVProgressHUD.setDefaultMaskType(.clear)
         SVProgressHUD.setContainerView(App.shared.window)
-        SVProgressHUD.show(UIImage(), status: text)
+//        SVProgressHUD.show(UIImage(), status: text)
+        SVProgressHUD.showInfo(withStatus: text)
     }
     
     /// 显示自动消失的 HUD,并在消失后执行回调
index b2beb38..f55a2d4 100644 (file)
@@ -9,7 +9,7 @@ import UIKit
 
 class PopTextField: BasePresentView2 {
     let contentView = UIView()
-    private let titleLabel = UILabel()
+    let titleLabel = UILabel()
     private let textFiledBg = UIView()
     let textFiled = UITextField()
     let cancelButton = CustomButton()
@@ -67,7 +67,7 @@ class PopTextField: BasePresentView2 {
         contentView.snp.makeConstraints { make in
             make.left.right.equalToSuperview().inset(18)
             make.height.equalTo(200)
-            make.center.equalToSuperview()
+            make.centerY.equalToSuperview().offset(-60)
         }
         titleLabel.do { (v) in
             v.textColor = .rgb(0x121212)
@@ -84,10 +84,10 @@ class PopTextField: BasePresentView2 {
             v.placeholder = "请输入录音名字"
             v.font = .bold(16)
             v.textColor = .hexString("#121212")
-            v.becomeFirstResponder()
+//            v.becomeFirstResponder()
         }
         cancelButton.do { (v) in
-            v.setTitle("å\88 é\99¤", for: .normal)
+            v.setTitle("å\8f\96æ¶\88", for: .normal)
             v.titleLabel?.font = .bold(16)
             v.setTitleColor(.hexString("#121212"), for: .normal)
             v.backgroundColor = .hexString("#F7F7F7")
@@ -105,6 +105,7 @@ class PopTextField: BasePresentView2 {
         }
     }
     @objc func okButtonAction(){
+        textFiled.resignFirstResponder()
         guard let text = textFiled.text,text.count > 0 else {
             return
         }
@@ -112,6 +113,7 @@ class PopTextField: BasePresentView2 {
         hide()
     }
     @objc func cancelButtonAction(){
+        textFiled.resignFirstResponder()
         cancelTap?()
         hide()
     }
index 648b0d6..efab40a 100644 (file)
@@ -15,7 +15,7 @@ target 'ShenYin' do
   pod 'MJRefresh'#刷新
   pod 'YYModel'#model解析
   pod 'HandyJSON'#model解析
-  pod 'RealmSwift'#数据库
+#  pod 'RealmSwift'#数据库
   pod 'SwiftDate'#时间转换
   pod 'SVProgressHUD'#蒙版
   pod 'Kingfisher', '~> 6.0'#图片下载K
@@ -28,7 +28,7 @@ target 'ShenYin' do
   pod 'SwiftHTTP'
   pod 'swiftScan'#二维码
   pod 'TZImagePickerController'#图片选择
-  pod 'netfox'#调试
+#  pod 'netfox'#调试
 #  pod 'DoraemonKit'#调试
 
   pod 'SocketRocket'#socket,AI用到