From 80eca1553ab286394990435bcd933a9ea95e7c6d Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Fri, 25 Jul 2025 22:00:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(OTA=E5=8D=87=E7=BA=A7):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=A7=E5=93=81=E9=85=8D=E7=BD=AE=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在AppConfig中添加getproduct方法用于本地查询产品配置 - 修改OTA升级控制器使用本地配置替代API请求 - 在设置控制器中添加状态锁防止重复检查更新 --- lib/data/models/appconfig.dart | 6 ++++ .../controllers/ota_upgrade_controller.dart | 32 +++++++++++-------- .../controllers/settings_controller.dart | 14 ++++---- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/lib/data/models/appconfig.dart b/lib/data/models/appconfig.dart index a2086b527..19dcf0565 100644 --- a/lib/data/models/appconfig.dart +++ b/lib/data/models/appconfig.dart @@ -30,4 +30,10 @@ class AppConfig { config.products.map((user) => user.devicename).toList(); return names; } + + static DBProduct? getproduct(String name) { + final foundProduct = + config.products.firstWhere((product) => product.devicename == name); + return foundProduct; + } } diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 907dd85f8..6d1162846 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -1,4 +1,5 @@ import 'package:classic_bluetooth/classic_bluetooth.dart'; +import 'package:voitrans/data/models/appconfig_model.dart'; import '/routes/app_routes.dart'; import 'package:logger/web.dart'; import 'package:flutter/material.dart'; @@ -12,6 +13,7 @@ import 'package:dio/dio.dart'; import 'package:path_provider/path_provider.dart'; import 'package:ota/ota.dart'; import '../../../data/services/ble_manager.dart'; +import '../../../data/models/appconfig.dart'; class OtaUpgradeController extends GetxController { static const int NOT_STARTED = -1; // 未开始 @@ -193,24 +195,26 @@ class OtaUpgradeController extends GetxController { _address = connectedDevices.first.address; } - // API请求 - final response = await Api.getproduct({ - "id": deviceInfo.firmwareProductId, - }); + DBProduct? product = AppConfig.getproduct("DeapSound"); - // 处理API响应 - if (response['product'] == null) { - throw const FormatException('API 响应格式错误'); - } + // // API请求 + // final response = await Api.getproduct({ + // "id": deviceInfo.firmwareProductId, + // }); + + // // 处理API响应 + // if (response['product'] == null) { + // throw const FormatException('API 响应格式错误'); + // } - final resp = OtaConfigResp.fromJson(response); - Logger().d('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); - latestVersion.value = resp.systemversion!; - updatedescription.value = resp.updatedescription!; - updatepackageaddress = resp.updatepackageaddress!; + // final resp = OtaConfigResp.fromJson(response); + // Logger().d('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); + // latestVersion.value = resp.systemversion!; + // updatedescription.value = resp.updatedescription!; + updatepackageaddress = product!.updatepackageaddress!; // 版本检查 - bool isUpdate = _isNewVersionAvailable(resp.systemversion!); + bool isUpdate = _isNewVersionAvailable(product!.version!); if (isUpdate) { await _bleManager.setEnterOta(true); diff --git a/lib/modules/settings/controllers/settings_controller.dart b/lib/modules/settings/controllers/settings_controller.dart index 5b92b5474..7c3bf6a8c 100644 --- a/lib/modules/settings/controllers/settings_controller.dart +++ b/lib/modules/settings/controllers/settings_controller.dart @@ -1,4 +1,3 @@ -import 'package:firebase_auth/firebase_auth.dart' as firebase; import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; @@ -7,15 +6,11 @@ import '../../../core/themes/theme_service.dart'; import '../../../data/services/speech_factory.dart'; import '../models/language_model.dart'; import 'package:logger/logger.dart'; -import '../../../data/models/user_Info.dart'; import '../../../data/services/ble_manager.dart'; -import 'package:path_provider/path_provider.dart'; -import 'dart:io'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'dart:async'; -import 'package:app_settings/app_settings.dart'; import '../../../data/services/version_update_service.dart'; import '../../common/widgets/version_update_dialog.dart'; @@ -128,6 +123,8 @@ class SettingsController extends GetxController { final appVersion = ''.obs; final buildNumber = ''.obs; + bool isCheckingUpdate = false; //状态锁,防止重复检查 + // 权限相关 // 权限组,用于在UI中显示 final List> permissionGroups = [ @@ -482,6 +479,9 @@ class SettingsController extends GetxController { /// 手动检查版本更新 Future checkForUpdate() async { + if (isCheckingUpdate) return; + isCheckingUpdate = true; + try { // 显示加载提示 Get.dialog( @@ -515,7 +515,7 @@ class SettingsController extends GetxController { } catch (e) { // 关闭加载提示 if (Get.isDialogOpen == true) { - Get.back(); + Get.back(closeOverlays: true); } Get.snackbar( @@ -525,6 +525,8 @@ class SettingsController extends GetxController { backgroundColor: Colors.red.withOpacity(0.8), colorText: Colors.white, ); + } finally { + isCheckingUpdate = false; } } } From f7a734e7a79eb814b6ca005d22d6a13cf062d718 Mon Sep 17 00:00:00 2001 From: liwei1dao Date: Sat, 26 Jul 2025 11:14:30 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/devices_controller.dart | 43 ++++++++-- .../chat_api/SystemFunctionHandler.swift | 79 +++++++++++++++++++ 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/lib/modules/devices/controllers/devices_controller.dart b/lib/modules/devices/controllers/devices_controller.dart index ba32f0c98..8dd28c7a8 100644 --- a/lib/modules/devices/controllers/devices_controller.dart +++ b/lib/modules/devices/controllers/devices_controller.dart @@ -14,31 +14,48 @@ import 'package:get/get_state_manager/src/simple/get_controllers.dart'; */ class DevicesController extends GetxController { late final BleManager _bleManager; - late final Map> devices; + + // 修改为响应式变量 + final RxMap> devices = >{}.obs; + + // 或者使用这种方式 + // final Rx>> devices = Rx>>({}); @override void onInit() { super.onInit(); _bleManager = Get.find(); + + // 在初始化时加载设备数据 + _loadDevices(); } - @override - void onClose() { - super.onClose(); + // 加载设备数据 + void _loadDevices() { + devices.clear(); for (var device in User.instance.devices) { - if (!devices.containsKey(device.id)) { + if (!devices.containsKey(device.devicetype)) { devices[device.devicetype] = []; } devices[device.devicetype]!.add(device); } } + @override + void onClose() { + super.onClose(); + // onClose 中不应该修改数据,这里应该是清理资源 + } + void unbindearphone(UserDevice device) async { final response = await Api.unbinddevice({ "id": device.id, }); if (response != null) { - devices[device.devicetype]!.remove(device); + // 响应式更新 + devices[device.devicetype]?.remove(device); + devices.refresh(); // 触发UI更新 + User.instance.removeUserDevice(device.id); _bleManager.clearPairedDevices(); _bleManager.disconnect(); @@ -48,4 +65,18 @@ class DevicesController extends GetxController { return; } } + + // 添加设备 + void addDevice(UserDevice device) { + if (!devices.containsKey(device.devicetype)) { + devices[device.devicetype] = []; + } + devices[device.devicetype]!.add(device); + devices.refresh(); // 触发UI更新 + } + + // 获取指定类型的设备列表 + List getDevicesByType(int deviceType) { + return devices[deviceType] ?? []; + } } diff --git a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift index 6a553d692..a2dc14ec2 100644 --- a/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift +++ b/local_plugins/chat_api/ios/chat_api/Sources/chat_api/SystemFunctionHandler.swift @@ -4,6 +4,7 @@ import EventKit import CoreLocation import MessageUI import location_service +import user_portrait // 添加这行 /// 结果结构体 public struct Result { @@ -65,6 +66,9 @@ public class SystemFunctionHandler: NSObject { // 注册打开录音机功能 registerOpenRecorderFunction(client: client) + // 注册用户画像更新功能 + registerSetUserProfileFieldFunction(client: client) + } catch { // 静默处理错误 } @@ -720,3 +724,78 @@ private class OpenRecorderHandler: FunctionHandler { // private enum LocationError: Error { // ... // } + + /// 注册设置用户画像字段函数 + private func registerSetUserProfileFieldFunction(client: MCPClient) { + let parameters: [String: Any] = [ + "type": "object", + "properties": [ + "key": [ + "type": "string", + "description": "画像字段名,例如:age、tone、工作经历、device_preference" + ], + "value": [ + "type": "string", + "description": "字段对应的值" + ] + ], + "required": ["key", "value"] + ] + + let handler = SetUserProfileFieldHandler() + _ = client.registerLocalFunction( + name: "set_user_profile_field", + description: "设置或更新用户画像中的某一个字段", + parameters: parameters, + handler: handler + ) + } +/// 设置用户画像字段处理器 +private class SetUserProfileFieldHandler: FunctionHandler { + func handle(arguments: [String: Any]) async throws -> String { + guard let key = arguments["key"] as? String, + let value = arguments["value"] as? String else { + throw ChatApiException("缺少必要参数:key 和 value") + } + + // 验证参数 + if key.isEmpty { + throw ChatApiException("画像字段名不能为空") + } + + if value.isEmpty { + throw ChatApiException("字段值不能为空") + } + + let result = await setUserProfileField(key: key, value: value) + return "{\"result\": \"\(result.message)\", \"key\": \"\(key)\", \"value\": \"\(value)\"}\"}" + } + + private func setUserProfileField(key: String, value: String) async -> Result { + return await withCheckedContinuation { continuation in + DispatchQueue.main.async { + do { + // 使用 UserPortrait 单例设置画像字段 + UserPortrait.shared.set(key: key, value: value) + + // 发送通知给其他模块 + UserPortrait.shared.sendUpdateNotification(key: key, value: value) + + print("[SetUserProfileFieldHandler] 成功设置用户画像字段: \(key) = \(value)") + + continuation.resume(returning: Result( + success: true, + message: "成功设置用户画像字段 \(key) 为 \(value)" + )) + } catch { + print("[SetUserProfileFieldHandler] 设置用户画像字段失败: \(error.localizedDescription)") + + continuation.resume(returning: Result( + success: false, + message: "设置用户画像字段失败:\(error.localizedDescription)" + )) + } + } + } + } +} From eaee575fe736b9d05797b87454f3950c1a91413b Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Sat, 26 Jul 2025 11:16:07 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(ota=5Fupgrade):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E8=80=B3=E6=9C=BA=E5=9B=BE=E7=89=87=E8=B5=84=E6=BA=90=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=89=88=E6=9C=AC=E6=A3=80=E6=9F=A5=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新暗黑模式和明亮模式下的耳机图片资源 修复版本检查逻辑,使用产品版本作为最新版本 --- .../ota_upgrade/controllers/ota_upgrade_controller.dart | 4 ++-- lib/modules/ota_upgrade/views/ota_upgrade_view.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index 6d1162846..3fe3f689c 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -209,12 +209,12 @@ class OtaUpgradeController extends GetxController { // final resp = OtaConfigResp.fromJson(response); // Logger().d('getequipmentinfo,resp.systemversion: ${resp.systemversion}'); - // latestVersion.value = resp.systemversion!; + latestVersion.value = product?.version ?? ""; // updatedescription.value = resp.updatedescription!; updatepackageaddress = product!.updatepackageaddress!; // 版本检查 - bool isUpdate = _isNewVersionAvailable(product!.version!); + bool isUpdate = _isNewVersionAvailable(product.version!); if (isUpdate) { await _bleManager.setEnterOta(true); diff --git a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart index c2d8ab091..922964c9d 100644 --- a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart +++ b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart @@ -187,8 +187,8 @@ class OtaUpgradeView extends GetView { ), child: Image.asset( isDarkMode - ? 'assets/images/headphone_dark.png' - : 'assets/images/headphone_light.png', + ? 'assets/images/headphone_new3.png' + : 'assets/images/headphone_new4.png', height: 100.h, fit: BoxFit.contain, ), From 46e8409750cc633a4b8b4b826fe57acfdddad6e9 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Sat, 26 Jul 2025 12:52:15 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(settings):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A3=80=E6=9F=A5=E5=AF=B9=E8=AF=9D=E6=A1=86?= =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=9A=84=E5=8F=AF=E9=9D=A0=E6=80=A7=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改进对话框关闭逻辑,使用显式状态跟踪和多种关闭方式确保对话框能正确关闭。同时优化颜色透明度设置方式。 --- .../controllers/settings_controller.dart | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/modules/settings/controllers/settings_controller.dart b/lib/modules/settings/controllers/settings_controller.dart index 7c3bf6a8c..92829c798 100644 --- a/lib/modules/settings/controllers/settings_controller.dart +++ b/lib/modules/settings/controllers/settings_controller.dart @@ -482,8 +482,12 @@ class SettingsController extends GetxController { if (isCheckingUpdate) return; isCheckingUpdate = true; + // 用于跟踪我们的对话框 + bool dialogShown = false; + try { // 显示加载提示 + dialogShown = true; Get.dialog( const Center( child: CircularProgressIndicator(), @@ -494,8 +498,12 @@ class SettingsController extends GetxController { final versionService = VersionUpdateService.to; final updateInfo = await versionService.checkForUpdate(); - // 关闭加载提示 - Get.back(); + // 关闭加载提示 - 使用精确的关闭方式 + if (dialogShown) { + dialogShown = false; + // 直接关闭最顶层的对话框,不依赖状态判断 + Navigator.of(Get.overlayContext!).pop(); + } if (updateInfo.hasUpdate) { // 显示更新对话框 @@ -508,21 +516,30 @@ class SettingsController extends GetxController { .tr //当前已是最新版本 .replaceAll('{version}', updateInfo.currentVersion), snackPosition: SnackPosition.TOP, - backgroundColor: Colors.green.withOpacity(0.8), + backgroundColor: Colors.green.withValues(alpha: 0.8), colorText: Colors.white, ); } } catch (e) { - // 关闭加载提示 - if (Get.isDialogOpen == true) { - Get.back(closeOverlays: true); + // 关闭加载提示 - 异常情况下的可靠关闭 + if (dialogShown) { + dialogShown = false; + try { + // 尝试直接关闭 + Navigator.of(Get.overlayContext!).pop(); + } catch (popError) { + // 如果直接关闭失败,使用备用方案 + if (Get.isDialogOpen == true) { + Get.back(); + } + } } Get.snackbar( 'error'.tr, 'networkErrorRetry'.tr, // 网络错误,请稍后重试 snackPosition: SnackPosition.TOP, - backgroundColor: Colors.red.withOpacity(0.8), + backgroundColor: Colors.red.withValues(alpha: 0.8), colorText: Colors.white, ); } finally {