import dayjs from "dayjs"; import { message } from "@/utils/message"; import { addDialog } from "@/components/ReDialog"; import type { PaginationProps } from "@pureadmin/table"; import { deviceDetection } from "@pureadmin/utils"; import { getDeviceList, openDoor, setTemperature, setVolume, getDoorRecords, type DoorRecordItem } from "@/api/device"; import { getEnabledShops } from "@/api/shop"; import { type Ref, ref, toRaw, reactive, onMounted } from "vue"; import { ElForm, ElFormItem, ElInput, ElInputNumber, ElSelect, ElOption, ElMessageBox } from "element-plus"; import type { DeviceItem, DeviceSearchForm } from "./types"; export function useDevice(tableRef: Ref) { const form = reactive({ deviceId: "", shopId: "", status: "", storeName: "" }); const formRef = ref(); const ruleFormRef = ref(); const dataList = ref([]); const loading = ref(true); const shopOptions = ref([]); // 操作按钮的加载状态 const operatingIds = ref>(new Set()); // 开关门记录相关 const dialogVisible = ref(false); const recordLoading = ref(false); const recordList = ref([]); const currentDeviceId = ref(""); const recordPagination = reactive({ total: 0, pageSize: 10, currentPage: 1, background: true }); const pagination = reactive({ total: 0, pageSize: 10, currentPage: 1, background: true }); const columns: TableColumnList = [ { label: "设备ID", prop: "deviceId", minWidth: 120 }, { label: "设备名称", prop: "deviceName", minWidth: 120 }, { label: "所属门店", prop: "shopName", minWidth: 120 }, { label: "货柜名称", prop: "storeName", minWidth: 100 }, { label: "温度(℃)", prop: "temperature", minWidth: 80 }, { label: "音量", prop: "volume", minWidth: 60 }, { label: "门状态", prop: "doorStatus", minWidth: 80, cellRenderer: ({ row }) => ( {row.doorStatus === 1 ? "已开门" : "已关门"} ) }, { label: "状态", prop: "status", minWidth: 80, cellRenderer: ({ row }) => ( {row.status === 1 ? "在线" : "离线"} ) }, { label: "最后在线时间", prop: "lastOnlineTime", minWidth: 160, formatter: ({ lastOnlineTime }) => lastOnlineTime ? dayjs(lastOnlineTime).format("YYYY-MM-DD HH:mm:ss") : "-" }, { label: "操作", fixed: "right", width: 200, slot: "operation" } ]; // 搜索 async function onSearch() { loading.value = true; try { const searchParams: any = { page: pagination.currentPage, pageSize: pagination.pageSize }; // 只添加非空的搜索条件 if (form.deviceId) searchParams.deviceId = form.deviceId; if (form.shopId) searchParams.shopId = form.shopId; if (form.status) searchParams.status = form.status; if (form.storeName) searchParams.storeName = form.storeName; const { data } = await getDeviceList(searchParams); dataList.value = data.list; pagination.total = data.total; } catch (error) { console.error("获取设备列表失败:", error); dataList.value = []; pagination.total = 0; } finally { setTimeout(() => { loading.value = false; }, 300); } } // 重置表单 const resetForm = formEl => { if (!formEl) return; formEl.resetFields(); pagination.currentPage = 1; onSearch(); }; // 分页 function handleSizeChange(val: number) { pagination.pageSize = val; onSearch(); } function handleCurrentChange(val: number) { pagination.currentPage = val; onSearch(); } // 远程开门 async function handleOpenDoor(row: DeviceItem) { try { const deviceName = row.deviceName || row.storeName || `设备${row.deviceId}`; await ElMessageBox.confirm(`确认要远程开启 ${deviceName} 的门吗?`, "系统提示", { confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" }); // 添加 loading 状态 operatingIds.value.add(row.id); // 传递 doorIndex 参数,默认为 A 门 const res = await openDoor(row.id, { doorIndex: "A" }); if (res.code === 0) { message(`已发送开门指令到设备 ${deviceName}`, { type: "success" }); // 开门成功后刷新列表,更新门状态 await onSearch(); } else { message(res.message || "开门失败", { type: "error" }); } } catch (error) { // 用户取消或请求失败 if (error !== "cancel") { console.error("开门失败:", error); message("操作失败", { type: "error" }); } } finally { // 移除 loading 状态 operatingIds.value.delete(row.id); } } // 设置温度 const tempForm = reactive({ temperature: 0 }); function handleSetTemperature(row: DeviceItem) { tempForm.temperature = row.temperature; addDialog({ title: `设置 ${row.deviceName} 的温度`, width: "30%", draggable: true, closeOnClickModal: false, fullscreen: deviceDetection(), contentRenderer: () => ( ), beforeSure: async (done) => { try { // 添加 loading 状态 operatingIds.value.add(row.id); const res = await setTemperature(row.id, { temperature: tempForm.temperature }); if (res.code === 0) { message(`已设置温度为 ${tempForm.temperature}℃`, { type: "success" }); done(); // 温度设置成功后刷新列表,更新温度显示 await onSearch(); } else { message(res.message || "设置失败", { type: "error" }); } } catch (error) { console.error("设置温度失败:", error); message("设置失败", { type: "error" }); } finally { // 移除 loading 状态 operatingIds.value.delete(row.id); } } }); } // 设置音量 const volumeForm = reactive({ volume: 0 }); function handleSetVolume(row: DeviceItem) { volumeForm.volume = row.volume; addDialog({ title: `设置 ${row.deviceName} 的音量`, width: "30%", draggable: true, closeOnClickModal: false, fullscreen: deviceDetection(), contentRenderer: () => ( ), beforeSure: async (done) => { try { // 添加 loading 状态 operatingIds.value.add(row.id); const res = await setVolume(row.id, { volume: volumeForm.volume }); if (res.code === 0) { message(`已设置音量为 ${volumeForm.volume}`, { type: "success" }); done(); // 音量设置成功后刷新列表,更新音量显示 await onSearch(); } else { message(res.message || "设置失败", { type: "error" }); } } catch (error) { console.error("设置音量失败:", error); message("设置失败", { type: "error" }); } finally { // 移除 loading 状态 operatingIds.value.delete(row.id); } } }); } const recordColumns: TableColumnList = [ { label: "活动 ID", prop: "activityId", minWidth: 180 }, { label: "用户 ID", prop: "userId", minWidth: 100 }, { label: "门索引", prop: "doorIndex", minWidth: 80 }, { label: "类型", prop: "openType", minWidth: 80, cellRenderer: ({ row }) => ( {row.openType === "IN" ? "上货" : "消费"} ) }, { label: "门状态", prop: "doorStatus", minWidth: 100, cellRenderer: ({ row }) => ( { row.doorStatus === "OPENED" ? "已开门" : row.doorStatus === "CLOSED" ? "已关门" : "异常" } ) }, { label: "是否有消费", prop: "nobuy", minWidth: 100, cellRenderer: ({ row }) => ( {row.nobuy === 0 ? "有消费" : "无消费"} ) }, { label: "开门时间", prop: "openTime", minWidth: 160, formatter: ({ openTime }) => dayjs(openTime).format("YYYY-MM-DD HH:mm:ss") }, { label: "关门时间", prop: "closeTime", minWidth: 160, formatter: ({ closeTime }) => closeTime ? dayjs(closeTime).format("YYYY-MM-DD HH:mm:ss") : "-" }, { label: "持续时长 (秒)", prop: "duration", minWidth: 100 }, { label: "来源", prop: "source", minWidth: 100, cellRenderer: ({ row }) => ( {row.source === "MINIAPP" ? "小程序" : row.source === "ADMIN" ? "管理后台" : row.source || "-"} ) } ]; // 查询开关门记录 async function fetchDoorRecords() { if (!currentDeviceId.value) return; recordLoading.value = true; try { const res = await getDoorRecords(currentDeviceId.value, { page: recordPagination.currentPage, pageSize: recordPagination.pageSize }); if (res.code === 0 && res.data) { recordList.value = res.data.list || []; recordPagination.total = res.data.total || 0; } } catch (error) { console.error("查询开关门记录失败:", error); message("查询失败", { type: "error" }); } finally { recordLoading.value = false; } } // 显示开关门记录弹窗 function showDoorRecords(row: DeviceItem) { currentDeviceId.value = row.deviceId; recordPagination.currentPage = 1; recordPagination.pageSize = 10; dialogVisible.value = true; fetchDoorRecords(); } // 记录分页大小变化 function handleRecordSizeChange(val: number) { recordPagination.pageSize = val; recordPagination.currentPage = 1; fetchDoorRecords(); } // 记录页码变化 function handleRecordCurrentChange(val: number) { recordPagination.currentPage = val; fetchDoorRecords(); } async function fetchShopOptions() { try { const { data } = await getEnabledShops(); shopOptions.value = data || []; } catch (error) { console.error("获取门店列表失败:", error); } } onMounted(async () => { await fetchShopOptions(); onSearch(); }); return { form, loading, columns, dataList, pagination, shopOptions, onSearch, resetForm, handleOpenDoor, handleSetTemperature, handleSetVolume, handleSizeChange, handleCurrentChange, operatingIds, // 开关门记录相关 dialogVisible, recordLoading, recordList, recordColumns, recordPagination, showDoorRecords, handleRecordSizeChange, handleRecordCurrentChange }; }