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