import { computed, ref } from "vue"; import { getDeviceDetailAPI, getMyDevicesAPI, unbindDeviceAPI, } from "@/apis"; export const DEVICE_NAME_STORAGE_KEY = "device_name_overrides"; export function useDeviceStatus({ user, device, deviceStatus, online, updateDevice, clearDevice, unbindDialogVisible, }) { const deviceDetails = ref({}); let deviceDetailRequestVersion = 0; const isDeviceOnline = computed( () => deviceStatus.value.online === true || online.value === true ); const isDeviceCharging = computed( () => isDeviceOnline.value && deviceStatus.value.charging === true ); const statusText = computed(() => { if (!isDeviceOnline.value) return "未连接"; return isDeviceCharging.value ? "已连接(充电中)" : "已连接"; }); const statusClass = computed(() => isDeviceOnline.value ? "device-status--online" : "device-status--offline" ); const battery = computed(() => { const rawValue = deviceStatus.value.battery ?? deviceStatus.value.power; if (rawValue === null || rawValue === undefined || rawValue === "") return null; const value = Number(rawValue); return Number.isFinite(value) ? Math.min(100, Math.max(0, value)) : null; }); const batteryText = computed(() => battery.value === null ? "暂无数据" : `${battery.value}%` ); const onlineDurationText = computed(() => { const rawDuration = deviceStatus.value.onlineDuration; if (rawDuration == null || String(rawDuration).trim() === "") return "--"; const seconds = Number(rawDuration); if (!Number.isFinite(seconds) || seconds < 0) return "--"; // WS 推送秒数,页面按完整分钟展示累计使用时间。 const totalMinutes = Math.floor(seconds / 60); const hours = Math.floor(totalMinutes / 60); const minutes = totalMinutes % 60; return hours > 0 ? `${hours}小时${minutes}分钟` : `${minutes}分钟`; }); const networkType = computed(() => String(deviceStatus.value.netType ?? "").trim().toLowerCase() ); const networkText = computed(() => { const netType = networkType.value; if (netType === "wifi") return "WiFi"; if (netType === "4g") return "4G"; return isDeviceOnline.value ? "在线" : "未连接"; }); const maskedDeviceId = computed(() => { const id = String(device.value.deviceId || ""); if (!id) return "暂无设备编号"; if (id.length <= 3) return id; return `${"*".repeat(Math.min(5, id.length - 3))}${id.slice(-3)}`; }); const deviceRows = computed(() => [ { label: "设备型号", value: deviceDetails.value.model || "射灵智能弓" }, { label: "当前电量", value: batteryText.value }, { label: "连接方式", value: networkText.value }, { label: "设备编号", value: maskedDeviceId.value }, ]); const getDeviceNameOverrides = () => { const value = uni.getStorageSync(DEVICE_NAME_STORAGE_KEY); return value && typeof value === "object" ? value : {}; }; const refreshDeviceDetails = async () => { const deviceId = device.value.deviceId; if (!deviceId) return; const requestVersion = ++deviceDetailRequestVersion; try { const detailResponse = await getDeviceDetailAPI(deviceId); const detail = detailResponse?.detail || detailResponse?.data?.detail; if ( !detail || typeof detail !== "object" || requestVersion !== deviceDetailRequestVersion || device.value.deviceId !== deviceId ) { return; } deviceDetails.value = { ...deviceDetails.value, ...detail, deviceModelName: detail.deviceModelName ?? "", bindTime: String( detail.bindTime ?? deviceDetails.value.bindTime ?? "" ).trim(), qrCodeUrl: String( detail.qrCodeUrl ?? deviceDetails.value.qrCodeUrl ?? "" ).trim(), }; } catch (error) { // 实时刷新失败时保留当前页面数据,等待下次通知或页面重新显示。 console.log("刷新设备详情失败", error); } }; const syncDeviceBinding = async () => { if (!user.value.id) return; try { const devices = await getMyDevicesAPI(); if (Array.isArray(devices?.bindings) && devices.bindings.length > 0) { const currentDevice = devices.bindings[0]; const nameOverrides = getDeviceNameOverrides(); // 二维码和绑定时间仅取详情接口,绑定列表不能作为这两项的回退数据。 let latestDevice = { ...currentDevice, deviceModelName: "", bindTime: "", qrCodeUrl: "", }; try { const detailResponse = await getDeviceDetailAPI(currentDevice.deviceId); const detail = detailResponse?.detail || detailResponse?.data?.detail; if (detail && typeof detail === "object") { latestDevice = { ...currentDevice, ...detail, deviceModelName: detail.deviceModelName ?? "", bindTime: String(detail.bindTime ?? "").trim(), qrCodeUrl: String(detail.qrCodeUrl ?? "").trim(), deviceName: detail.deviceAlias || detail.deviceName || currentDevice.deviceName, }; } } catch (error) { // 详情接口失败时保留绑定关系,二维码和绑定时间仍保持为空。 console.log("获取设备详情失败", error); } deviceDetails.value = latestDevice; updateDevice( latestDevice.deviceId, nameOverrides[latestDevice.deviceId] || latestDevice.deviceAlias || latestDevice.deviceName || latestDevice.name || "我的智能弓" ); return; } clearDevice(); deviceDetailRequestVersion += 1; deviceDetails.value = {}; } catch (error) { console.log("同步设备绑定失败", error); } }; const unbindDevice = async () => { if (!device.value.deviceId) return; try { await unbindDeviceAPI(device.value.deviceId); uni.setStorageSync("calibration", false); clearDevice(); deviceDetailRequestVersion += 1; deviceDetails.value = {}; unbindDialogVisible.value = false; uni.showToast({ title: "解绑成功", icon: "success" }); } catch (error) { console.error("解绑设备失败", error); if (error?.type === "DEVICE_BIND_INVALID") { clearDevice(); unbindDialogVisible.value = false; } } }; return { batteryText, deviceDetails, deviceRows, getDeviceNameOverrides, isDeviceCharging, isDeviceOnline, maskedDeviceId, networkText, networkType, onlineDurationText, refreshDeviceDetails, statusClass, statusText, syncDeviceBinding, unbindDevice, }; }