diff --git a/lib/common/utils/app/app_setting_tool.dart b/lib/common/utils/app/app_setting_tool.dart index 872bdb6..307b08c 100644 --- a/lib/common/utils/app/app_setting_tool.dart +++ b/lib/common/utils/app/app_setting_tool.dart @@ -768,8 +768,9 @@ abstract class AppSettingTool { } } - // 根据后台返回的数据更新到缓存 - static Future updateSysInfoByService(ServiceHardware data) async { + // 根据后台返回的数据更新到缓存;返回排除 syncTime 后业务字段是否有变化, + // 供定时任务决定是否广播配置刷新,避免无变化时反复弹"配置修改中"遮罩。 + static Future updateSysInfoByService(ServiceHardware data) async { if (ObjectUtil.isEmpty(data)) { final setting = SysSetting( sysType: SysType.CANTEEN, @@ -777,9 +778,13 @@ abstract class AppSettingTool { sqlAddress: await AppFileTool.getDatabaseBackupPath(), ); await _setSetting(sysJson: setting); - return; + return true; } final sysSetting = await AppSettingTool.getSysSetting(); + // syncTime 每次同步都会刷新,判定业务变化前先排除该键。 + final beforeJson = json.encode( + sysSetting.toJson()..remove('syncTime'), + ); final id = data.id; if (ObjectUtil.isNotEmpty(id)) { sysSetting.serviceId = id; @@ -849,6 +854,10 @@ abstract class AppSettingTool { } sysSetting.syncTime = DateTime.now(); await _setSetting(sysJson: sysSetting); + final afterJson = json.encode( + sysSetting.toJson()..remove('syncTime'), + ); + return beforeJson != afterJson; } /// 将当前业务终端的打印机绑定和打印参数持久化到本机;空响应表示尚未绑定。 diff --git a/lib/common/utils/sync/sync_check_tool.dart b/lib/common/utils/sync/sync_check_tool.dart index d087e78..ec34db6 100644 --- a/lib/common/utils/sync/sync_check_tool.dart +++ b/lib/common/utils/sync/sync_check_tool.dart @@ -817,7 +817,14 @@ class SyncCheckTool { ? _ScheduledTaskActionResult.skipped(update.message) : _ScheduledTaskActionResult.success(update.message); case ScheduledTaskType.configSync: - await SyncConfigTool.autoSyncSysInfo(); + final result = await SyncConfigTool.autoSyncSysInfo(); + // 配置变化才广播刷新:面板页收到 CONFIG 会弹"配置修改中"遮罩, + // 无条件广播会让收银页随定时周期反复被遮罩打断。 + if (result != null && + result.changed && + Get.isRegistered()) { + Get.find().mqUpdateEventBus.fire(MqtActionEnum.CONFIG); + } return const _ScheduledTaskActionResult.success('设备配置同步完成'); case ScheduledTaskType.departmentFaceSync: final mode = request.debugAllFaces diff --git a/lib/common/utils/sync/sync_config_tool.dart b/lib/common/utils/sync/sync_config_tool.dart index 0c5e32f..6b299c1 100644 --- a/lib/common/utils/sync/sync_config_tool.dart +++ b/lib/common/utils/sync/sync_config_tool.dart @@ -4,11 +4,16 @@ import 'package:common_utils/common_utils.dart'; import 'package:pj_supermarket_cloud/common/index.dart'; +/// 设备配置同步结果:setting 为已落库的最新快照,changed 表示业务字段是否有变化。 +typedef SysConfigSyncResult = ({SysSetting setting, bool changed}); + abstract class SyncConfigTool { static const _tag = "sync配置工具"; - // 自动同步设备信息导本地缓存 - static Future autoSyncSysInfo() async { + /// 自动同步设备信息到本地缓存;未登录、未绑定或接口失败返回 null。 + /// 返回的必须是同步后的最新快照:调用方会直接用它刷新界面(如基本信息页), + /// 返回同步前的旧实例会让页面继续显示旧端口等配置。 + static Future autoSyncSysInfo() async { final login = await AppUserTool.isLogin(); if (!login) return null; final sysSetting = await AppSettingTool.getSysSetting(); @@ -23,37 +28,32 @@ abstract class SyncConfigTool { return null; } // 基本信息 - await AppSettingTool.updateSysInfoByService(data); + final changed = await AppSettingTool.updateSysInfoByService(data); // 人脸sdk - await autoSyncFaceSdk(detail: data, sysInfo: sysSetting); - logger.i("|$_tag|结束同步设备信息 sysInfo:|${json.encode(sysSetting)}|"); - return sysSetting; + final latest = await AppSettingTool.getSysSetting(); + await autoSyncFaceSdk( + detail: data, + before: sysSetting, + latest: latest, + ); + logger.i("|$_tag|结束同步设备信息 sysInfo:|${json.encode(latest)}|"); + return (setting: latest, changed: changed); } - // 自动同步设备信息导本地缓存-同步人脸sdk + /// 同步后检查人脸 SDK 参数并记录激活状态;回写必须用最新快照 latest。 + /// before 仅用于判定服务端是否变更了人脸参数;若用同步前的旧实例整体回写, + /// 会把 updateSysInfoByService 刚写入的新 MQTT 配置回滚成旧值。 static Future autoSyncFaceSdk({ required ServiceHardware detail, - required SysSetting sysInfo, + required SysSetting before, + required SysSetting latest, }) async { - final appId = detail.faceAppId; - final sdkKey = detail.faceSdkKey; - final activeKey = detail.faceActiveKey; - bool isUpdate = false; - if (appId != sysInfo.faceAppId) { - sysInfo.faceAppId = appId; - isUpdate = true; - } - if (sdkKey != sysInfo.faceSdkKey) { - sysInfo.faceSdkKey = sdkKey; - isUpdate = true; - } - if (activeKey != sysInfo.faceActiveKey) { - sysInfo.faceActiveKey = activeKey; - isUpdate = true; - } - if (!isUpdate) return; + final changed = detail.faceAppId != before.faceAppId || + detail.faceSdkKey != before.faceSdkKey || + detail.faceActiveKey != before.faceActiveKey; + if (!changed) return; final activeSdk = await AppFaceTool.isActiveSdk(); - await AppSettingTool.setSysSetting(sysInfo); + await AppSettingTool.setSysSetting(latest); logger.i("|$_tag||同步人脸sdk参数自动激活${activeSdk ? '成功' : '失败'}"); } } diff --git a/lib/pages/setting/controller.dart b/lib/pages/setting/controller.dart index 6806597..37211a2 100644 --- a/lib/pages/setting/controller.dart +++ b/lib/pages/setting/controller.dart @@ -312,8 +312,11 @@ class SettingController extends GetxController { maskType: EasyLoadingMaskType.black, ); try { - final setting = await SyncConfigTool.autoSyncSysInfo(); - if (setting != null) sysSetting.value = setting; + final result = await SyncConfigTool.autoSyncSysInfo(); + // result.setting 是同步后最新快照,直接刷新 Rx 才能让基本信息页显示新配置。 + if (result != null) { + sysSetting.value = _orderedSysSetting(result.setting); + } Toast.success(msg: "同步设备信息成功"); EasyLoading.dismiss(); } catch (e, stack) { diff --git a/lib/pages/setting/face_setting_controller.dart b/lib/pages/setting/face_setting_controller.dart index 24a19ad..9ee6d82 100644 --- a/lib/pages/setting/face_setting_controller.dart +++ b/lib/pages/setting/face_setting_controller.dart @@ -162,8 +162,8 @@ class FaceSettingController extends GetxController { isSyncingConfig.value = true; errorMessage.value = ''; try { - final setting = await SyncConfigTool.autoSyncSysInfo(); - if (setting == null) { + final result = await SyncConfigTool.autoSyncSysInfo(); + if (result == null) { throw Exception('设备配置同步无返回'); } await Get.find().getSetting();