diff --git a/lib/data/models/appconfig.dart b/lib/data/models/appconfig.dart index 1d1b844ab..fa5cb0922 100644 --- a/lib/data/models/appconfig.dart +++ b/lib/data/models/appconfig.dart @@ -47,6 +47,7 @@ class AppConfig { return uuids; } +//根据产品名称获取产品配置 static DBProduct? getproduct(String name) { final foundProduct = config.products.firstWhere((product) => product.devicename == name); diff --git a/lib/data/models/appconfig_model.dart b/lib/data/models/appconfig_model.dart index b4b6a4f90..945103b42 100644 --- a/lib/data/models/appconfig_model.dart +++ b/lib/data/models/appconfig_model.dart @@ -75,6 +75,7 @@ class DBProduct { final int factoryid; final int devicetype; final String devicename; + final String? productimage; final String scanuuid; final String? version; final String? updatedescription; @@ -85,6 +86,7 @@ class DBProduct { required this.factoryid, required this.devicetype, required this.devicename, + required this.productimage, required this.scanuuid, required this.version, required this.updatedescription, diff --git a/lib/data/models/appconfig_model.g.dart b/lib/data/models/appconfig_model.g.dart index b8e08075e..e75d17437 100644 --- a/lib/data/models/appconfig_model.g.dart +++ b/lib/data/models/appconfig_model.g.dart @@ -76,6 +76,7 @@ DBProduct _$DBProductFromJson(Map json) => DBProduct( factoryid: (json['factoryid'] as num).toInt(), devicename: json['devicename'] as String, devicetype: json['devicetype'] as int, + productimage: json['productimage'] as String?, scanuuid: json['scanuuid'] as String, version: json['version'] as String?, updatedescription: json['updatedescription'] as String?, diff --git a/lib/modules/home/controllers/home_controller.dart b/lib/modules/home/controllers/home_controller.dart index 8b47ae480..c5cb174cb 100644 --- a/lib/modules/home/controllers/home_controller.dart +++ b/lib/modules/home/controllers/home_controller.dart @@ -22,8 +22,12 @@ enum ConnectionStatus { /// 主页控制器,管理设备连接状态和信息展示 class HomeController extends GetxController { static const String _tag = 'HomeCtrl'; + static const String _lastDeviceNameKey = 'last_connected_device_name'; // 存储键 + static const String _lastDeviceImageKey = + 'last_connected_device_image'; // 存储上一次设备图片的键 static HomeController get to => Get.find(); final GetStorage _storage = GetStorage(); + String? _lastConnectedDeviceImage; // 新增:存储上一次连接设备的图片链接 final _isFullyConnected = false.obs; String? _lastConnectedDeviceName; @@ -98,6 +102,7 @@ class HomeController extends GetxController { void onInit() { super.onInit(); _otaCheckService = Get.find(); + _loadLastConnectedDeviceName(); // 加载持久化的设备名称 _initWithCachedInfo(); // 移除了电池信息定时刷新的启动 } @@ -132,7 +137,7 @@ class HomeController extends GetxController { _classicBluetoothWorker = ever(_bluetoothManager.currentDeviceRx, (BluetoothDevice? device) { if (device != null) { - _lastConnectedDeviceName = device.name; + _saveLastConnectedDeviceName(device.name); // 使用新的保存方法 } _checkConnectionStatus(); }); @@ -142,6 +147,28 @@ class HomeController extends GetxController { }); } + /// 从本地存储加载最后连接的设备名称 + void _loadLastConnectedDeviceName() { + _lastConnectedDeviceName = _storage.read(_lastDeviceNameKey); + Logger.d(_tag, '加载最后连接的设备名称: $_lastConnectedDeviceName'); + } + + /// 保存最后连接的设备名称到本地存储 + void _saveLastConnectedDeviceName(String deviceName) { + _lastConnectedDeviceName = deviceName; + _storage.write(_lastDeviceNameKey, deviceName); + Logger.d(_tag, '保存最后连接的设备名称: $deviceName'); + } + + /// 保存上一次连接设备的图片链接到本地存储 + void _saveLastConnectedDeviceImage(String? imageUrl) { + if (imageUrl != null && imageUrl.isNotEmpty) { + _lastConnectedDeviceImage = imageUrl; + _storage.write(_lastDeviceImageKey, imageUrl); + Logger.d(_tag, '保存上一次连接设备的图片: $imageUrl'); + } + } + Future refreshDeviceConnection() async { await _checkConnectionStatus(); @@ -235,6 +262,7 @@ class HomeController extends GetxController { } final deviceName = currentDevice?.name; + //final deviceName = '102'; if (deviceName != null && deviceName.isNotEmpty) { return deviceName; } @@ -404,4 +432,69 @@ class HomeController extends GetxController { Map getOtaCheckStatus() { return _otaCheckService.getCheckStatus(); } + + /// 获取当前设备的产品图片路径 + /// 如果没有配置产品图片或获取失败,返回null使用默认图片 + String? getCurrentDeviceImage() { + try { + final deviceName = getDeviceName(); + if (deviceName == 'unknownEquipment'.tr) { + Logger.d(_tag, '设备未知,使用默认图片'); + return null; + } + + // 通过AppConfig获取产品信息 + if (!AppConfig.isInitialized()) { + Logger.w(_tag, 'AppConfig未初始化,使用默认图片'); + return null; + } + + final product = AppConfig.getproduct(deviceName); + if (product != null && + product.productimage != null && + product.productimage!.isNotEmpty) { + Logger.d(_tag, '获取到设备产品图片: ${product.productimage}'); + _saveLastConnectedDeviceImage(product.productimage); + return product.productimage; + } else { + Logger.d(_tag, '设备 "$deviceName" 未配置产品图片,使用默认图片'); + return null; + } + } catch (e) { + Logger.e(_tag, '获取设备产品图片失败: $e'); + return null; + } + } + + /// 获取设备图片的完整资源路径 + /// 处理网络图片URL和本地资源路径 + String getDeviceImagePath(bool isDarkMode) { + final productImage = getCurrentDeviceImage(); + + if (productImage != null) { + // 如果是网络图片URL + if (productImage.startsWith('http://') || + productImage.startsWith('https://')) { + return productImage; + } + // 如果是本地资源路径,确保以assets/开头 + else if (productImage.startsWith('assets/')) { + return productImage; + } + // 如果只是文件名,添加assets/images/前缀 + else { + return 'assets/images/$productImage'; + } + } + + // 使用默认耳机图片 + return isDarkMode + ? 'assets/images/headphone_new3.png' + : 'assets/images/headphone_new4.png'; + } + + /// 判断是否为网络图片 + bool isNetworkImage(String imagePath) { + return imagePath.startsWith('http://') || imagePath.startsWith('https://'); + } } diff --git a/lib/modules/home/views/home_view.dart b/lib/modules/home/views/home_view.dart index 4541a14d3..51cdbb387 100644 --- a/lib/modules/home/views/home_view.dart +++ b/lib/modules/home/views/home_view.dart @@ -220,12 +220,58 @@ class HomeView extends GetView { child: ClipRRect( // 添加 ClipRRect borderRadius: BorderRadius.circular(16.r), - child: Image.asset( - isDarkMode - ? 'assets/images/headphone_new3.png' - : 'assets/images/headphone_new4.png', - height: 220.h, - fit: BoxFit.contain, + child: GetBuilder( + builder: (controller) { + final imagePath = controller.getDeviceImagePath(isDarkMode); + final isNetwork = controller.isNetworkImage(imagePath); + + return isNetwork + ? Image.network( + imagePath, + height: 220.h, + fit: BoxFit.contain, + errorBuilder: (context, error, stackTrace) { + // 网络图片加载失败时使用默认图片 + return Image.asset( + isDarkMode + ? 'assets/images/headphone_new3.png' + : 'assets/images/headphone_new4.png', + height: 220.h, + fit: BoxFit.contain, + ); + }, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return SizedBox( + height: 220.h, + child: Center( + child: CircularProgressIndicator( + value: loadingProgress.expectedTotalBytes != + null + ? loadingProgress.cumulativeBytesLoaded / + loadingProgress.expectedTotalBytes! + : null, + ), + ), + ); + }, + ) + : Image.asset( + imagePath, + height: 220.h, + fit: BoxFit.contain, + errorBuilder: (context, error, stackTrace) { + // 本地图片加载失败时使用默认图片 + return Image.asset( + isDarkMode + ? 'assets/images/headphone_new3.png' + : 'assets/images/headphone_new4.png', + height: 220.h, + fit: BoxFit.contain, + ); + }, + ); + }, ), ), ), diff --git a/lib/modules/login/controllers/login_controller.dart b/lib/modules/login/controllers/login_controller.dart index 6462b66f1..a159b0269 100644 --- a/lib/modules/login/controllers/login_controller.dart +++ b/lib/modules/login/controllers/login_controller.dart @@ -932,7 +932,59 @@ class LoginController extends GetxController { Logger().d('getAppConfig:进来了'); // 根据API设计调整 final resp = UserGetAppConfigResp.fromJson(response); + + // 详细记录解析后的配置信息 + Logger().d('getAppConfig: 配置解析成功'); + Logger().d('getAppConfig: 环境变量数量 = ${resp.env.length}'); + Logger().d('getAppConfig: 智能体数量 = ${resp.agents.length}'); + Logger().d('getAppConfig: MCP服务器数量 = ${resp.mcps.length}'); + Logger().d('getAppConfig: 产品设备数量 = ${resp.products.length}'); + + // 详细记录产品设备信息 + if (resp.products.isNotEmpty) { + Logger().d('getAppConfig: ========== 产品设备详细信息 =========='); + for (int i = 0; i < resp.products.length; i++) { + final product = resp.products[i]; + Logger().d( + 'getAppConfig: 产品[$i] ID=${product.id}, 设备名称="${product.devicename}"'); + Logger().d( + 'getAppConfig: 产品[$i] 厂商ID=${product.factoryid}, 设备类型=${product.devicetype}'); + Logger().d('getAppConfig: 产品[$i] 扫描UUID="${product.scanuuid}"'); + Logger().d( + 'getAppConfig: 产品[$i] 产品图片="${product.productimage ?? "未设置"}"'); + Logger().d('getAppConfig: 产品[$i] 版本="${product.version ?? "未设置"}"'); + Logger().d( + 'getAppConfig: 产品[$i] 更新描述="${product.updatedescription ?? "未设置"}"'); + Logger().d( + 'getAppConfig: 产品[$i] 更新包地址="${product.updatepackageaddress ?? "未设置"}"'); + Logger().d('getAppConfig: ----------------------------------------'); + } + Logger().d('getAppConfig: ========== 产品设备信息结束 =========='); + } else { + Logger().w('getAppConfig: 警告 - 未获取到任何产品设备信息'); + } + + // 记录环境变量信息 + if (resp.env.isNotEmpty) { + Logger().d('getAppConfig: ========== 环境变量信息 =========='); + resp.env.forEach((key, value) { + Logger().d('getAppConfig: 环境变量 $key = "$value"'); + }); + Logger().d('getAppConfig: ========== 环境变量信息结束 =========='); + } + AppConfig.initialize(resp); + Logger().d( + 'getAppConfig: AppConfig初始化完成,产品数量验证 = ${AppConfig.config.products.length}'); + + // 验证AppConfig中的产品数据 + final productNames = AppConfig.allproductNames(); + final productUuids = AppConfig.allproductUuids(); + Logger().d('getAppConfig: 可用产品名称列表 = $productNames'); + Logger().d('getAppConfig: 可用产品UUID列表 = $productUuids'); + + Logger().d('getAppConfig: 应用配置获取和初始化成功完成'); + return true; } catch (e) { Logger().d('getAppConfig 取失败: $e'); diff --git a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart index f306bde15..4a4e9e896 100644 --- a/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart +++ b/lib/modules/ota_upgrade/controllers/ota_upgrade_controller.dart @@ -1,12 +1,14 @@ import 'package:classic_bluetooth/classic_bluetooth.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; -import 'package:logger/web.dart'; +// import 'package:logger/web.dart'; +import 'package:get_storage/get_storage.dart'; import 'package:ota/ota.dart'; import '../../../data/services/ble_manager.dart'; import 'ota_core_contropller.dart'; import 'ota_download_contropller.dart'; import '../views/ota_upgrade_popup_view.dart'; +import '../../../core/utils/logger.dart'; /// OTA升级主控制器 - 重构后的简化版本 /// 负责协调各个服务,管理升级流程的整体状态 @@ -33,13 +35,18 @@ class OtaUpgradeController extends GetxController { final RxBool isFetchingDeviceInfo = false.obs; final RxBool showDetailedStatus = false.obs; final RxBool isBleConnected = true.obs; + final GetStorage _storage = GetStorage(); String _address = ''; String _updatePackageAddress = ''; + String? _lastConnectedDeviceImage; // 新增:存储上一次连接设备的图片链接 + + get lastConnectedDeviceImage => _lastConnectedDeviceImage; @override void onInit() { super.onInit(); + _loadLastConnectedDeviceImage(); // 加载持久化的设备图片 _initializeController(); } @@ -51,6 +58,13 @@ class OtaUpgradeController extends GetxController { super.onClose(); } + /// 从本地存储加载上一次连接设备的图片链接 + void _loadLastConnectedDeviceImage() { + _lastConnectedDeviceImage = _storage.read('last_connected_device_name'); + Logger.d( + 'OtaUpgradeController', '加载上一次连接设备的图片: $_lastConnectedDeviceImage'); + } + /// 初始化控制器 /// 设置事件监听并加载版本信息 Future _initializeController() async { @@ -169,7 +183,7 @@ class OtaUpgradeController extends GetxController { detailedStatus.value = '下载失败,请检查网络连接'; showDetailedStatus.value = false; _handleError('下载失败', e.toString()); - Logger().d('下载失败: $e'); + Logger.d('OtaUpgradeController', '下载失败: $e'); } } diff --git a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart index e9011531a..10f7180b8 100644 --- a/lib/modules/ota_upgrade/views/ota_upgrade_view.dart +++ b/lib/modules/ota_upgrade/views/ota_upgrade_view.dart @@ -185,12 +185,43 @@ class OtaUpgradeView extends GetView { width: 1, ), ), - child: Image.asset( - isDarkMode - ? 'assets/images/headphone_new3.png' - : 'assets/images/headphone_new4.png', - height: 100.h, - fit: BoxFit.contain, + child: GetBuilder( + builder: (controller) { + final imagePath = controller.lastConnectedDeviceImage; + + // 网络图片 + return Image.network( + imagePath, + height: 100.h, + fit: BoxFit.contain, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return SizedBox( + height: 100.h, + child: Center( + child: CircularProgressIndicator( + value: loadingProgress.expectedTotalBytes != null + ? loadingProgress.cumulativeBytesLoaded / + loadingProgress.expectedTotalBytes! + : null, + strokeWidth: 2, + color: isDarkMode ? Colors.white : Colors.blue, + ), + ), + ); + }, + errorBuilder: (context, error, stackTrace) { + // 网络图片加载失败时使用默认图片 + return Image.asset( + isDarkMode + ? 'assets/images/headphone_new3.png' + : 'assets/images/headphone_new4.png', + height: 100.h, + fit: BoxFit.contain, + ); + }, + ); + }, ), ); }