feat(device): 新增设备在线状态查询与实时更新功能
- 新增设备在线状态视图对象类型定义 - 新增设备在线状态批量查询接口与详情页查询接口 - 表格数据加载完成后批量查询并更新设备在线状态 - 详情页独立查询在线状态并展示状态指示点 - 通过 SSE 推送实时更新表格与详情页的设备在线状态
This commit is contained in:
@@ -58,7 +58,15 @@ const contentConfig: IContentConfig<DeviceQueryParams, DeviceItem> = {
|
||||
prop: "serialno",
|
||||
templet: "custom",
|
||||
slotName: "serialno",
|
||||
width: 150,
|
||||
width: 220,
|
||||
},
|
||||
{
|
||||
label: "在线状态",
|
||||
align: "center",
|
||||
prop: "online",
|
||||
templet: "custom",
|
||||
slotName: "onlineStatus",
|
||||
width: 100,
|
||||
},
|
||||
{ label: "设备型号", align: "center", prop: "snModel", width: 200 },
|
||||
{ label: "设备昵称", align: "center", prop: "snName", width: 200 },
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
@toolbar-click="handleToolbarClick"
|
||||
@operate-click="handleOperateClick"
|
||||
@filter-change="handleFilterChange"
|
||||
@data-loaded="fetchDeviceOnlineStatus"
|
||||
>
|
||||
<template #status="scope">
|
||||
<el-tag :type="scope.row[scope.prop as string] == 1 ? 'success' : 'info'">
|
||||
@@ -48,6 +49,15 @@
|
||||
:style="{ marginLeft: '2px' }"
|
||||
/>
|
||||
</template>
|
||||
<template #onlineStatus="scope">
|
||||
<span
|
||||
class="status-dot"
|
||||
:style="{ backgroundColor: scope.row.online == 1 ? '#67c23a' : '#f56c6c' }"
|
||||
/>
|
||||
<el-tag :type="scope.row.online == 1 ? 'success' : 'info'" size="small">
|
||||
{{ scope.row.online == 1 ? "在线" : "离线" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</device-page-content>
|
||||
|
||||
<!-- 新增 -->
|
||||
@@ -92,8 +102,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, ref } from "vue";
|
||||
import DeviceAPI from "@/api/system/device";
|
||||
import type { DeviceOnlineVO } from "@/api/system/device/types";
|
||||
import type { IObject, PageModalInstance } from "@/components/DeviceSn/types";
|
||||
import { useSse } from "@/composables";
|
||||
import DeviceSnOverView from "@/components/DeviceSn/DeviceSnOverView.vue";
|
||||
import usePage from "@/components/DeviceSn/usePage";
|
||||
import addModalConfig from "./config/add";
|
||||
@@ -222,7 +235,88 @@ const dialogVisible = ref(false);
|
||||
const overviewVisible = ref(false);
|
||||
const selectedRow = ref<IObject>({});
|
||||
|
||||
/**
|
||||
* 批量查询设备在线状态并更新表格数据
|
||||
*/
|
||||
async function fetchDeviceOnlineStatus() {
|
||||
try {
|
||||
// 从 contentRef 获取当前表格 pageData
|
||||
const pageData = contentRef.value?.pageData as IObject[] | undefined;
|
||||
if (!pageData || pageData.length === 0) {
|
||||
return;
|
||||
}
|
||||
// 收集所有设备序列号
|
||||
const sns = pageData.map((item) => item.serialno as string).filter((sn) => !!sn);
|
||||
if (sns.length === 0) {
|
||||
return;
|
||||
}
|
||||
// 批量查询在线状态
|
||||
const onlineMap = await DeviceAPI.getOnlineStatusBatch(sns);
|
||||
if (onlineMap) {
|
||||
// 更新表格数据中的在线状态
|
||||
pageData.forEach((item) => {
|
||||
const sn = item.serialno as string;
|
||||
const onlineInfo = onlineMap[sn];
|
||||
if (onlineInfo) {
|
||||
item.online = onlineInfo.online;
|
||||
item.lastHeartbeatTime = onlineInfo.lastHeartbeatTime;
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("批量查询设备在线状态失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SSE 设备在线状态事件监听取消函数
|
||||
*/
|
||||
let unsubscribeDeviceOnlineStatus: (() => void) | null = null;
|
||||
|
||||
/**
|
||||
* 根据 SSE 推送的设备在线状态更新单条表格数据
|
||||
*/
|
||||
function handleDeviceOnlineStatus(data: DeviceOnlineVO) {
|
||||
if (!data || !data.serialno) {
|
||||
return;
|
||||
}
|
||||
const pageData = contentRef.value?.pageData as IObject[] | undefined;
|
||||
if (!pageData) {
|
||||
return;
|
||||
}
|
||||
const row = pageData.find((item) => item.serialno === data.serialno);
|
||||
if (row) {
|
||||
row.online = data.online;
|
||||
row.lastHeartbeatTime = data.lastHeartbeatTime;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
initOptions();
|
||||
// 监听 SSE 推送的设备在线状态,实时更新表格对应行
|
||||
const sse = useSse();
|
||||
unsubscribeDeviceOnlineStatus = sse.on<DeviceOnlineVO>(
|
||||
"device-online-status",
|
||||
handleDeviceOnlineStatus
|
||||
);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// 组件销毁时取消 SSE 事件监听
|
||||
if (unsubscribeDeviceOnlineStatus) {
|
||||
unsubscribeDeviceOnlineStatus();
|
||||
unsubscribeDeviceOnlineStatus = null;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.status-dot {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-right: 4px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user