using System; using System.Collections; using System.Collections.Generic; using System.Threading.Tasks; using Kill.Network; using Kill.Managers.ResponseModels; using Kill.UI.Components; using UnityEngine; namespace Kill.Managers { public class DataManager : MonoBehaviour { public string selectedDeviceMac=""; public static DataManager Instance { get; private set; } public DeviceInfo selectedDevice; public List OwnedDevices = new List(); public List SharedDevices = new List(); public bool isOwner; public bool hasWifi; public bool hasBluetooth; public FingerprintListResponseData fingerprintListData = new FingerprintListResponseData(); public List fingerprintUserDatas = new List(); public List scheduleTaskDatas = new List(); private void Awake() { Instance = this; } public async Task Init() { InitUser(); GetSelectedDeviceMac(); } public string token = ""; public UserInfo userInfo = new UserInfo(); public void SetToken(string token,UserInfo userInfo) { this.token = token; this.userInfo = userInfo; string userData =JsonUtility.ToJson(userInfo); Debug.Log(userData); PlayerPrefs.SetString("token", token); PlayerPrefs.SetString("userData", userData); NetworkCtrl.Instance.RemoveGlobalHeader("token"); NetworkCtrl.Instance.AddGlobalHeader("token", token); } public void SavaSelectedDeviceMac(string mac) { selectedDeviceMac=mac; PlayerPrefs.SetString("selectedDeviceMac", selectedDeviceMac); } public void GetSelectedDeviceMac() { selectedDeviceMac=PlayerPrefs.GetString("selectedDeviceMac", ""); } public void InitUser() { token = PlayerPrefs.GetString("token", ""); string userData = PlayerPrefs.GetString("userData", ""); userInfo = JsonUtility.FromJson(userData); NetworkCtrl.Instance.RemoveGlobalHeader("token"); NetworkCtrl.Instance.AddGlobalHeader("token",token); Debug.Log(token); } public void ClearInfo() { token = ""; userInfo = new UserInfo(); PlayerPrefs.DeleteKey("token"); PlayerPrefs.DeleteKey("userData"); } public async Task TokenLogin() { LoadingUI.Show(); try { // 获取用户详情 var response = await NetworkCtrl.Instance.Post("/api/v1/auth/token-login"); LoadingUI.Hide(); if(response.Data.code==200) { SetToken(response.Data.data.token,response.Data.data.user); return true; } else { ClearInfo(); return false; } } catch (Exception ex) { LoadingUI.Hide(); Debug.LogError($"TokenLogin 异常: {ex.Message}"); return false; } } public DeviceConfig deviceConfig; // 从服务器获取的原始配置快照,用于比对变化字段 private DeviceConfig _originalDeviceConfig; #region 设备配置 /// /// 获取设备配置 /// public async Task GetDeviceConfig(string deviceSn) { var response = await NetworkCtrl.Instance.Get( "/api/v1/device/config", new Dictionary { { "device_sn", deviceSn } } ); DeviceConfig result = null; ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { result = data.data; deviceConfig = result; // 保存原始快照,用于后续差异对比 _originalDeviceConfig = result?.Clone(); }, onError: (code, msg) => { Debug.LogError($"[DataManager] 获取设备配置失败: {msg}"); } ); } /// /// 修改设备配置(只提交与原始配置相比发生变化的字段) /// /// 设备 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; if (changedFields.Count == 0) { Debug.Log("[DataManager] UpdateDeviceConfig: 没有字段变化,跳过同步"); return true; } var response = await NetworkCtrl.Instance.Put("/api/v1/device/config", changedFields); bool success = false; ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { success = true; }, onError: (code, msg) => { Debug.LogError($"[DataManager] 修改设备配置失败: {msg}"); } ); return success; } /// /// 构建设备配置JSON(只包含非null字段) /// private string BuildDeviceConfigJson(DeviceConfig config) { var sb = new System.Text.StringBuilder(); sb.Append("{"); AppendField(sb, "device_sn", config.device_sn); AppendField(sb, "language", config.language); AppendField(sb, "is_locked", config.is_locked); AppendField(sb, "fov_angle", config.fov_angle); AppendField(sb, "detection_distance", config.detection_distance); AppendField(sb, "aim_distance", config.aim_distance); AppendField(sb, "work_mode", config.work_mode); AppendField(sb, "fill_light_enable", config.fill_light_enable); AppendField(sb, "fill_light_type", config.fill_light_type); AppendField(sb, "fill_light_intensity", config.fill_light_intensity); AppendField(sb, "laser_visible_enable", config.laser_visible_enable); AppendField(sb, "visual_detect_enable", config.visual_detect_enable); AppendField(sb, "visual_sensitivity", config.visual_sensitivity); AppendField(sb, "radar_enable", config.radar_enable); AppendField(sb, "radar_sensitivity", config.radar_sensitivity); AppendField(sb, "radar_safe_distance", config.radar_safe_distance); AppendField(sb, "rgb_enable", config.rgb_enable); AppendField(sb, "rgb_red", config.rgb_red); AppendField(sb, "rgb_green", config.rgb_green); AppendField(sb, "rgb_blue", config.rgb_blue); AppendField(sb, "rgb_effect", config.rgb_effect); AppendField(sb, "lcd_auto_brightness", config.lcd_auto_brightness); AppendField(sb, "lcd_brightness", config.lcd_brightness); AppendField(sb, "lcd_sleep_enable", config.lcd_sleep_enable); AppendField(sb, "lcd_sleep_time", config.lcd_sleep_time); AppendField(sb, "wifi_enable", config.wifi_enable); AppendField(sb, "wifi_ssid", config.wifi_ssid); AppendField(sb, "wifi_password", config.wifi_password); AppendField(sb, "video_record_enable", config.video_record_enable); AppendField(sb, "record_duration", config.record_duration); AppendField(sb, "sound_enable", config.sound_enable); AppendField(sb, "sound_type", config.sound_type); AppendField(sb, "volume", config.volume); // 移除末尾逗号 if (sb[sb.Length - 1] == ',') sb.Length--; sb.Append("}"); return sb.ToString(); } private void AppendField(System.Text.StringBuilder sb, string key, object value) { if (value == null) return; sb.Append("\""); sb.Append(key); sb.Append("\":"); if (value is string s) { sb.Append("\""); sb.Append(s); sb.Append("\""); } else if (value is bool b) { sb.Append(b ? "true" : "false"); } else { sb.Append(value.ToString()); } sb.Append(","); } #endregion /// /// 同步设备配置到服务器(WiFi在线时调用,由各设置页面Sync方法调用) /// 只提交与原始配置相比发生变化的字段 /// public async void SyncDeviceConfigToServer() { if (!hasWifi) return; bool success = await UpdateDeviceConfig(selectedDevice.ble_mac, deviceConfig, _originalDeviceConfig); if (success) { // 同步成功后刷新原始快照 _originalDeviceConfig = deviceConfig?.Clone(); } } /// /// 更新定时任务到服务器 /// public async Task UpdateScheduleTasksToServer(string deviceSn, List tasks) { var requestData = new ScheduleTasksUploadRequest { device_sn = deviceSn, tasks = tasks }; var response = await NetworkCtrl.Instance.Put( "/api/v1/device/schedule-tasks", requestData); bool success = false; ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { success = true; Debug.Log($"[DataManager] 定时任务已同步到服务器,共 {tasks.Count} 条"); }, onError: (code, msg) => { Debug.LogError($"[DataManager] 同步定时任务失败: {msg}"); } ); return success; } /// /// 更新指纹列表到服务器 /// public async Task UpdateFingerprintsToServer(string deviceSn, List fingerprints) { var requestData = new FingerprintsUploadRequest { device_sn = deviceSn, fingerprints = fingerprints }; var response = await NetworkCtrl.Instance.Put( "/api/v1/device/fingerprints", requestData); bool success = false; ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { success = true; Debug.Log($"[DataManager] 指纹列表已同步到服务器,共 {fingerprints.Count} 条"); }, onError: (code, msg) => { Debug.LogError($"[DataManager] 同步指纹列表失败: {msg}"); } ); return success; } /// /// 通过WiFi获取指纹列表 /// public async Task GetFingerprints() { var response = await NetworkCtrl.Instance.Get( "/api/v1/device/fingerprints", new Dictionary { { "device_sn", selectedDevice.ble_mac } } ); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { fingerprintUserDatas.Clear(); if (data.data?.list != null) { fingerprintUserDatas.AddRange(data.data.list); } Debug.Log($"[DataManager] 获取到 {fingerprintUserDatas.Count} 条指纹记录"); }, onError: (code, msg) => { Debug.LogError($"[DataManager] 获取指纹列表失败: {msg}"); } ); } /// /// 通过WiFi获取定时任务列表 /// public async Task GetScheduleTasks(string deviceSn) { var response = await NetworkCtrl.Instance.Get( "/api/v1/device/schedule-tasks", new Dictionary { { "device_sn", deviceSn } } ); ResponseCodeHandler.HandleResponse(response, onSuccess: (data) => { scheduleTaskDatas.Clear(); Debug.Log($"[DataManager] 定时任务API返回: total={data.data?.total}, list count={data.data?.list?.Count ?? 0}"); if (data.data?.list != null) { scheduleTaskDatas.AddRange(data.data.list); foreach (var d in scheduleTaskDatas) { Debug.Log($"[DataManager] 任务 ID={d.task_id}, enabled={d.enabled}, start={d.start_hour}:{d.start_minute:D2}, end={d.end_hour}:{d.end_minute:D2}, mode={d.mode}, repeat={d.repeat_mask}"); } } Debug.Log($"[DataManager] 获取到 {scheduleTaskDatas.Count} 条定时任务"); }, onError: (code, msg) => { Debug.LogError($"[DataManager] 获取定时任务列表失败: {msg}"); } ); } } /// /// 指纹用户数据(从服务器获取) /// [System.Serializable] public class FingerprintUserData { public string username; public int fingerprint_id; public bool has_fingerprint; } } // 响应模型 namespace Kill.Managers.ResponseModels { [System.Serializable] public class FingerprintListResponse { public int code; public string message; public FingerprintListResponseData data; } [System.Serializable] public class FingerprintListResponseData { public int total; public int pages; public int limit; public int page; public List list; } [System.Serializable] public class ScheduleTaskListDataResponse { public int code; public string message; public ScheduleTaskListData data; } [System.Serializable] public class ScheduleTaskListData { public int total; public int pages; public int limit; public int page; public List list; } [System.Serializable] public class ScheduleTaskData { public byte task_id; public bool enabled; public byte start_hour; public byte start_minute; public byte end_hour; public byte end_minute; public string mode; public byte repeat_mask; } [System.Serializable] public class ScheduleTasksUploadRequest { public string device_sn; public List tasks; } [System.Serializable] public class FingerprintsUploadRequest { public string device_sn; public List fingerprints; } }