import { onLoad } from '@dcloudio/uni-app' import { computed, ref } from 'vue' import { getErrorMessage } from '@/utils/api-error' import { fetchDeviceList } from '../device.api' import { fetchDeviceRuntime, updateDeviceRuntime } from './device-detail.api' import type { AppDeviceRuntimeVo, DeviceDetailRouteQuery, FanLevel, RunMode } from './device-detail.types' import { AUTO_FAN_LEVEL_OPTIONS, formatConnectionText, formatPowerMode, formatTvocLevel, formatTvocValue, isAutoRunMode, isBluetoothConnected, mapRuntimeToView, RUN_MODE_OPTIONS, } from './device-detail.utils' import { useDeviceBluetoothSync } from './use-device-bluetooth-sync' export function useDeviceDetail() { const deviceId = ref(0) const deviceMac = ref() const deviceName = ref('') const locationName = ref('客厅') const deviceStatus = ref() const bluetoothConnected = ref(false) const charging = ref(false) const isOnline = ref(false) const loading = ref(false) const updating = ref(false) const runMode = ref('0') const fanLevel = ref('0') const tvoc = ref(null) const powerMode = ref('0') const filterLife = ref(0) const filterRemainText = ref('预计还可使用 -- 天') const filterReplaced = ref(false) const filterReplaceDialogVisible = ref(false) const batteryLevel = ref(null) const syncText = ref('数据实时同步中') const tvocDisplay = computed(() => formatTvocValue(tvoc.value ?? undefined)) const tvocLevel = computed(() => formatTvocLevel(tvoc.value ?? undefined)) const powerModeText = computed(() => formatPowerMode(powerMode.value)) const batteryDisplay = computed(() => batteryLevel.value != null ? `${batteryLevel.value}%` : '--', ) const connectionText = computed(() => formatConnectionText({ status: deviceStatus.value, bluetoothConnected: bluetoothConnected.value ? '1' : '0', locationName: locationName.value, }), ) const showFanLevelControl = computed(() => isAutoRunMode(runMode.value)) const fanLevelOptions = computed(() => showFanLevelControl.value ? AUTO_FAN_LEVEL_OPTIONS : [], ) function applyRuntime(data: AppDeviceRuntimeVo) { const view = mapRuntimeToView(data, deviceName.value) deviceName.value = view.deviceName runMode.value = view.runMode fanLevel.value = view.fanLevel tvoc.value = view.tvoc powerMode.value = view.powerMode filterLife.value = view.filterLife filterRemainText.value = view.filterRemainText filterReplaced.value = view.filterReplaced isOnline.value = view.isOnline if (data.status !== undefined) deviceStatus.value = data.status syncText.value = '刚刚更新 · 数据实时同步中' } async function refreshDeviceMeta() { if (!deviceId.value) return try { const list = await fetchDeviceList() const device = list?.find((item) => item.deviceId === deviceId.value) if (!device) return if (device.mac) deviceMac.value = device.mac bluetoothConnected.value = isBluetoothConnected(device.bluetoothConnected) charging.value = device.charging === '1' if (device.status !== undefined) deviceStatus.value = device.status isOnline.value = device.status === '1' } catch { // 列表刷新失败时保留路由参数状态 } } async function loadRuntime() { if (!deviceId.value) return loading.value = true try { const [runtime] = await Promise.all([ fetchDeviceRuntime({ deviceId: deviceId.value }), refreshDeviceMeta(), ]) applyRuntime(runtime) } catch (err) { uni.showToast({ title: getErrorMessage(err, '加载设备数据失败'), icon: 'none' }) } finally { loading.value = false } } async function patchRuntime(patch: { runMode?: RunMode; fanLevel?: FanLevel }) { if (!deviceId.value || updating.value) return updating.value = true try { await updateDeviceRuntime({ deviceId: deviceId.value, ...patch, }) const data = await fetchDeviceRuntime({ deviceId: deviceId.value }) applyRuntime(data) await refreshDeviceMeta() } catch (err) { uni.showToast({ title: getErrorMessage(err, '设置失败'), icon: 'none' }) } finally { updating.value = false } } function onSelectRunMode(mode: RunMode) { if (runMode.value === mode) return void patchRuntime({ runMode: mode }) } function onSelectFanLevel(level: FanLevel) { if (!isAutoRunMode(runMode.value)) return if (fanLevel.value === level) return void patchRuntime({ fanLevel: level }) } function onSettings() { uni.showToast({ title: '设备设置功能开发中', icon: 'none' }) } function onFilterReplace() { if (filterReplaced.value) return filterReplaceDialogVisible.value = true } function onConfirmFilterReplace() { filterReplaced.value = true uni.showToast({ title: '操作成功', icon: 'success' }) } const { startSyncLoop } = useDeviceBluetoothSync({ getDeviceId: () => deviceId.value, getMac: () => deviceMac.value, getRuntimePatch: () => ({ runMode: runMode.value, fanLevel: fanLevel.value, tvoc: tvoc.value ?? undefined, powerMode: powerMode.value, charging: charging.value ? '1' : '0', }), onBluetoothConnectedChange: (connected) => { bluetoothConnected.value = connected if (connected) { isOnline.value = true deviceStatus.value = '1' } }, onSyncTextChange: (text) => { syncText.value = text }, onSynced: async () => { await refreshDeviceMeta() const data = await fetchDeviceRuntime({ deviceId: deviceId.value }) applyRuntime(data) }, }) onLoad((query?: DeviceDetailRouteQuery) => { deviceId.value = Number(query?.deviceId) || 0 if (query?.name) deviceName.value = decodeURIComponent(String(query.name)) if (query?.locationName) { locationName.value = decodeURIComponent(String(query.locationName)) } if (query?.status) { deviceStatus.value = String(query.status) isOnline.value = query.status === '1' } if (query?.mac) deviceMac.value = decodeURIComponent(String(query.mac)) bluetoothConnected.value = isBluetoothConnected(query?.bluetoothConnected) charging.value = query?.charging === '1' void loadRuntime().then(() => { startSyncLoop() }) }) return { deviceName, connectionText, isOnline, tvocDisplay, tvocLevel, syncText, runMode, fanLevel, powerModeText, filterLife, filterRemainText, filterReplaced, filterReplaceDialogVisible, batteryDisplay, batteryLevel, charging, loading, showFanLevelControl, runModeOptions: RUN_MODE_OPTIONS, fanLevelOptions, onSelectRunMode, onSelectFanLevel, onSettings, onFilterReplace, onConfirmFilterReplace, } }