From cc336fd4aff2232f13f603a741f79cb2934935bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9C=E8=99=9E=E6=B8=A0=E6=88=90=E2=80=9D?= <“yuqucheng2006@qq.com”> Date: Mon, 29 Jun 2026 13:12:20 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E9=85=8D=E7=BD=AE=E5=90=8C=E6=AD=A5=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=8F=82=E6=95=B0=E4=BC=A0=E9=80=92?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主要变更: 1. 修复相机背景色为纯黑 2. 调整HTTP请求序列化库为Newtonsoft.Json并添加调试日志 3. 统一设备请求使用ble_mac而非device_sn 4. 重构DeviceConfig实现深拷贝和差异对比,仅同步变更字段 5. 优化指纹数据同步逻辑,新增本地状态更新方法 6. 新增亮度配置同步调用 7. 修复用户列表UI缺少遮罩 --- .../Res/ui/deviceinfopage/设备用户管理.prefab | 45 ++++++++++++++ Assets/Scenes/MainScene.unity | 2 +- Assets/Scripts/Managers/DataBase.cs | 58 ++++++++++++++++++- Assets/Scripts/Managers/DataManager.cs | 49 ++++++++++++---- Assets/Scripts/Network/HttpRequestManager.cs | 4 +- .../UI/Pages/DeviceInfoPage/DeviceInfoPage.cs | 46 +++++++++++++-- .../UI/Pages/DeviceInfoPage/LCDSetting.cs | 2 + .../Scripts/UI/Pages/HomePage/HomePageCtrl.cs | 4 +- .../ScheduleSetting/ScheduleSettingPage.cs | 4 +- 9 files changed, 187 insertions(+), 27 deletions(-) diff --git a/Assets/Res/ui/deviceinfopage/设备用户管理.prefab b/Assets/Res/ui/deviceinfopage/设备用户管理.prefab index 143305a..da35dad 100644 --- a/Assets/Res/ui/deviceinfopage/设备用户管理.prefab +++ b/Assets/Res/ui/deviceinfopage/设备用户管理.prefab @@ -972,6 +972,8 @@ GameObject: - component: {fileID: 6156444094017917638} - component: {fileID: 196291696332333663} - component: {fileID: 6174687206804186718} + - component: {fileID: 6802373552931830562} + - component: {fileID: 7282265199794192874} m_Layer: 5 m_Name: "\u88AB\u5206\u4EAB\u8005\u5217\u8868" m_TagString: Untagged @@ -1037,6 +1039,49 @@ MonoBehaviour: m_OnValueChanged: m_PersistentCalls: m_Calls: [] +--- !u!114 &6802373552931830562 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7074308004564379890} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!114 &7282265199794192874 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7074308004564379890} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 --- !u!1 &7279844199628844094 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scenes/MainScene.unity b/Assets/Scenes/MainScene.unity index 4609ca9..4d8f94b 100644 --- a/Assets/Scenes/MainScene.unity +++ b/Assets/Scenes/MainScene.unity @@ -855,7 +855,7 @@ Camera: m_Enabled: 1 serializedVersion: 2 m_ClearFlags: 2 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0} m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 diff --git a/Assets/Scripts/Managers/DataBase.cs b/Assets/Scripts/Managers/DataBase.cs index 27c40d9..9af9211 100644 --- a/Assets/Scripts/Managers/DataBase.cs +++ b/Assets/Scripts/Managers/DataBase.cs @@ -571,11 +571,65 @@ namespace Kill.Managers } /// - /// 将枚举值转换为服务器配置字符串(小写) + /// 将枚举值转换为服务器配置字符串(大写) /// public static string ToServerString(T enumValue) where T : struct { - return enumValue.ToString().ToLower(); + return enumValue.ToString().ToUpper(); + } + + /// + /// 深拷贝当前配置 + /// + public DeviceConfig Clone() + { + var clone = new DeviceConfig(); + var fields = typeof(DeviceConfig).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + foreach (var field in fields) + { + var value = field.GetValue(this); + if (value != null) + { + // 值类型和字符串直接赋值即可 + field.SetValue(clone, value); + } + } + return clone; + } + + /// + /// 获取与原始配置相比发生变化的字段(包含 device_sn) + /// + /// 原始配置 + /// 变化字段字典,key 为字段名,value 为当前值;若无变化返回空字典 + public Dictionary GetChangedFields(DeviceConfig original) + { + var changed = new Dictionary(); + if (original == null) + { + // 没有原始配置时,认为所有非空字段都发生变化 + var allFields = typeof(DeviceConfig).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + foreach (var field in allFields) + { + var value = field.GetValue(this); + if (value != null) + changed[field.Name] = value; + } + return changed; + } + + var fields = typeof(DeviceConfig).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + foreach (var field in fields) + { + var currentValue = field.GetValue(this); + var originalValue = field.GetValue(original); + + if (!Equals(currentValue, originalValue)) + { + changed[field.Name] = currentValue; + } + } + return changed; } } diff --git a/Assets/Scripts/Managers/DataManager.cs b/Assets/Scripts/Managers/DataManager.cs index c7a29c9..4aa1a35 100644 --- a/Assets/Scripts/Managers/DataManager.cs +++ b/Assets/Scripts/Managers/DataManager.cs @@ -98,6 +98,8 @@ namespace Kill.Managers } } public DeviceConfig deviceConfig; + // 从服务器获取的原始配置快照,用于比对变化字段 + private DeviceConfig _originalDeviceConfig; #region 设备配置 /// @@ -115,7 +117,9 @@ namespace Kill.Managers onSuccess: (data) => { result = data.data; - deviceConfig=result; + deviceConfig = result; + // 保存原始快照,用于后续差异对比 + _originalDeviceConfig = result?.Clone(); }, onError: (code, msg) => { @@ -125,16 +129,31 @@ namespace Kill.Managers } /// - /// 修改设备配置(空值字段不会被修改) + /// 修改设备配置(只提交与原始配置相比发生变化的字段) /// - public async Task UpdateDeviceConfig(string deviceSn, DeviceConfig config) + /// 设备 MAC/序列号 + /// 当前设备配置 + /// 原始配置快照,传 null 时会提交所有非空字段 + public async Task UpdateDeviceConfig(string deviceSn, DeviceConfig config, DeviceConfig original = null) { + if (config == null) + { + Debug.LogError("[DataManager] UpdateDeviceConfig: config 为 null"); + return false; + } + config.device_sn = deviceSn; + var changedFields = config.GetChangedFields(original); + // device_sn 必须始终携带 + changedFields["device_sn"] = deviceSn; - // 构建JSON,跳过null值字段 - string json = BuildDeviceConfigJson(config); + if (changedFields.Count == 0) + { + Debug.Log("[DataManager] UpdateDeviceConfig: 没有字段变化,跳过同步"); + return true; + } - var response = await NetworkCtrl.Instance.Post("/api/v1/device/config", json); + var response = await NetworkCtrl.Instance.Put("/api/v1/device/config", changedFields); bool success = false; ResponseCodeHandler.HandleResponse(response, @@ -231,11 +250,17 @@ namespace Kill.Managers /// /// 同步设备配置到服务器(WiFi在线时调用,由各设置页面Sync方法调用) + /// 只提交与原始配置相比发生变化的字段 /// public async void SyncDeviceConfigToServer() { if (!hasWifi) return; - await UpdateDeviceConfig(selectedDevice.ble_mac, deviceConfig); + bool success = await UpdateDeviceConfig(selectedDevice.ble_mac, deviceConfig, _originalDeviceConfig); + if (success) + { + // 同步成功后刷新原始快照 + _originalDeviceConfig = deviceConfig?.Clone(); + } } /// @@ -249,8 +274,8 @@ namespace Kill.Managers tasks = tasks }; - var response = await NetworkCtrl.Instance.Post( - "/api/v1/device/schedule-tasks", JsonUtility.ToJson(requestData)); + var response = await NetworkCtrl.Instance.Put( + "/api/v1/device/schedule-tasks", requestData); bool success = false; ResponseCodeHandler.HandleResponse(response, @@ -278,8 +303,8 @@ namespace Kill.Managers fingerprints = fingerprints }; - var response = await NetworkCtrl.Instance.Post( - "/api/v1/device/fingerprints", JsonUtility.ToJson(requestData)); + var response = await NetworkCtrl.Instance.Put( + "/api/v1/device/fingerprints", requestData); bool success = false; ResponseCodeHandler.HandleResponse(response, @@ -303,7 +328,7 @@ namespace Kill.Managers { var response = await NetworkCtrl.Instance.Get( "/api/v1/device/fingerprints", - new Dictionary { { "device_sn", selectedDevice.device_sn } } + new Dictionary { { "device_sn", selectedDevice.ble_mac } } ); ResponseCodeHandler.HandleResponse(response, diff --git a/Assets/Scripts/Network/HttpRequestManager.cs b/Assets/Scripts/Network/HttpRequestManager.cs index 4fb035f..cf4ef49 100644 --- a/Assets/Scripts/Network/HttpRequestManager.cs +++ b/Assets/Scripts/Network/HttpRequestManager.cs @@ -171,8 +171,8 @@ namespace Kill.Network /// public async Task> Put(string url, object data, HttpRequestConfig config = null) { - string jsonData = data != null ? JsonUtility.ToJson(data) : ""; - Debug.Log(jsonData); + string jsonData = data != null ? JsonConvert.SerializeObject(data) : ""; + Debug.Log("发送数据:" + jsonData); return await SendRequest(url, HttpMethod.PUT, jsonData, config, "application/json"); } diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs index c9ca9bf..40a1c67 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/DeviceInfoPage.cs @@ -100,12 +100,23 @@ namespace Kill.UI.Pages { Loom.QueueOnMainThread(() => { - foreach (var user in UserListResponse.Users) + // 将蓝牙用户列表同步到本地,供后续上传到服务器使用 + DataManager.Instance.fingerprintUserDatas.Clear(); + if (UserListResponse.Users != null) { - if (user.Username == nowUserid) + foreach (var user in UserListResponse.Users) { - bool isfingerOn = user.HasFingerprint; - break; + DataManager.Instance.fingerprintUserDatas.Add(new FingerprintUserData + { + username = user.Username, + fingerprint_id = user.FingerprintId, + has_fingerprint = user.HasFingerprint + }); + + if (user.Username == nowUserid) + { + isfingerOn = user.HasFingerprint; + } } } initActions.Remove(ReadFingerprint); @@ -159,7 +170,8 @@ namespace Kill.UI.Pages if (response.IsSuccess) { fingerTip.SetActive(true); - // 录制成功,同步到服务器 + // 录制成功,更新当前用户指纹状态并同步到服务器 + UpdateLocalFingerprintState(nowUserid, true); await SyncFingerprintsToServerAsync(); LoadingUI.Hide(); } @@ -171,11 +183,33 @@ namespace Kill.UI.Pages }); } + /// + /// 更新本地 fingerprintUserDatas 中指定用户的指纹状态 + /// + private void UpdateLocalFingerprintState(string username, bool hasFingerprint) + { + var list = DataManager.Instance.fingerprintUserDatas; + var existing = list.Find(u => u.username == username); + if (existing.username != null) + { + existing.has_fingerprint = hasFingerprint; + } + else + { + list.Add(new FingerprintUserData + { + username = username, + fingerprint_id = 0, + has_fingerprint = hasFingerprint + }); + } + } + private async Task SyncFingerprintsToServerAsync() { if (!DataManager.Instance.hasWifi) return; await DataManager.Instance.UpdateFingerprintsToServer( - DataManager.Instance.selectedDevice.device_sn, + DataManager.Instance.selectedDevice.ble_mac, DataManager.Instance.fingerprintUserDatas); } diff --git a/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs b/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs index d213951..079d7c9 100644 --- a/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs +++ b/Assets/Scripts/UI/Pages/DeviceInfoPage/LCDSetting.cs @@ -123,6 +123,8 @@ namespace Kill.UI.Pages { if (success) { + SyncBrightnessConfig(); + DataManager.Instance.SyncDeviceConfigToServer(); UpdateUI(); } else diff --git a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs index 893de38..a695bbc 100644 --- a/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs +++ b/Assets/Scripts/UI/Pages/HomePage/HomePageCtrl.cs @@ -873,7 +873,7 @@ namespace Kill.UI.Pages { deviceCtrl?.InitDeviceControl(false); await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac); - await DataManager.Instance.GetScheduleTasks(selectedDevice.device_sn); + await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac); scheduleSettingButton.interactable = true; moreSettingButton.interactable = true; InitDeviceUIFromConfig(); @@ -1612,7 +1612,7 @@ namespace Kill.UI.Pages Debug.Log("[HomePageCtrl] 设备WiFi上线,初始化UI"); await DataManager.Instance.GetDeviceConfig(selectedDevice.ble_mac); if (stopPolling) break; - await DataManager.Instance.GetScheduleTasks(selectedDevice.device_sn); + await DataManager.Instance.GetScheduleTasks(selectedDevice.ble_mac); if (stopPolling) break; ScheduleUIUpdate(() => { diff --git a/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs b/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs index dfb4be9..bc73a92 100644 --- a/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs +++ b/Assets/Scripts/UI/Pages/HomePage/ScheduleSetting/ScheduleSettingPage.cs @@ -112,7 +112,7 @@ namespace Kill.UI.Pages if (DataManager.Instance.hasWifi && !DataManager.Instance.hasBluetooth) { Debug.Log("[ScheduleSettingPage] WiFi模式读取定时任务..."); - await DataManager.Instance.GetScheduleTasks(DataManager.Instance.selectedDevice.device_sn); + await DataManager.Instance.GetScheduleTasks(DataManager.Instance.selectedDevice.ble_mac); Debug.Log($"[ScheduleSettingPage] WiFi获取到 {DataManager.Instance.scheduleTaskDatas.Count} 条原始数据"); // 将API数据转换为ScheduleTask,过滤全0无效任务 @@ -636,7 +636,7 @@ namespace Kill.UI.Pages }); } await DataManager.Instance.UpdateScheduleTasksToServer( - DataManager.Instance.selectedDevice.device_sn, tasksData); + DataManager.Instance.selectedDevice.ble_mac, tasksData); } } else