feat:新增自动门点连接状态卡片详情显示

This commit is contained in:
xudan 2025-09-01 18:09:27 +08:00
parent fbdcc718c4
commit 95f7894328
6 changed files with 68 additions and 7 deletions

View File

@ -32,6 +32,7 @@ export interface MapPointInfo {
deviceId?: string; // 设备ID
enabled?: 0 | 1; // 是否启用仅停靠点使用0=禁用1=启用)
deviceStatus?: number; // 设备状态仅自动门点使用0=关门1=开门)
isConnected?: boolean; // 连接状态仅自动门点使用true=已连接false=未连接)
active?: boolean; // 是否激活状态,用于控制光圈显示
}
//#endregion

View File

@ -198,6 +198,19 @@ const binTaskData = computed(() => {
<a-typography-text type="secondary">{{ $t('设备ID') }}</a-typography-text>
<a-typography-text>{{ point.deviceId }}</a-typography-text>
</a-list-item>
<a-list-item v-if="point.type === MapPointType.自动门点">
<a-typography-text type="secondary">{{ $t('连接状态') }}</a-typography-text>
<a-flex align="center" :gap="8" class="conn-status">
<span
class="status-dot"
:class="point.isConnected ? 'online' : 'offline'"
:title="point.isConnected ? $t('已连接') : $t('未连接')"
/>
<a-typography-text>
{{ point.isConnected ? $t('已连接') : $t('未连接') }}
</a-typography-text>
</a-flex>
</a-list-item>
<a-list-item v-if="point.extensionType">
<a-typography-text type="secondary">{{ $t('扩展类型') }}</a-typography-text>
<a-typography-text>{{ $t(MapPointType[point.extensionType]) }}</a-typography-text>
@ -315,6 +328,24 @@ const binTaskData = computed(() => {
@use '/src/assets/themes/theme' as *;
@include themed {
.conn-status {
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.05);
&.online {
background-color: get-color(success);
box-shadow: 0 0 0 2px rgba(82, 196, 26, 0.15);
}
&.offline {
background-color: get-color(error);
box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.15);
}
}
}
.storage-locations {
.storage-item {
display: flex;

View File

@ -312,6 +312,11 @@ const handleAutoSaveAndRestoreViewState = async () => {
//#region UI
const show = ref<boolean>(true);
//#endregion
// iframe
const backToCards = () => {
window.parent?.postMessage({ type: 'scene_return_to_cards' }, '*');
};
</script>
<template>
@ -319,7 +324,10 @@ const show = ref<boolean>(true);
<a-layout-header class="p-16" style="height: 64px">
<a-flex justify="space-between" align="center">
<a-typography-text class="title">{{ title }}--{{ isMonitorMode ? '场景监控' : '场景仿真' }}</a-typography-text>
<a-button type="primary" :loading="isSaving" @click="handleSaveViewState"> 保存比例 </a-button>
<a-space align="center">
<!-- <a-button @click="backToCards"> 返回 </a-button> -->
<a-button type="primary" :loading="isSaving" @click="handleSaveViewState"> 保存比例 </a-button>
</a-space>
</a-flex>
</a-layout-header>

View File

@ -157,6 +157,10 @@ const handleAutoSaveAndRestoreViewState = async () => {
await autoSaveAndRestoreViewState(editor.value, props.id);
};
// iframe
const backToCards = () => {
window.parent?.postMessage({ type: 'scene_return_to_cards' }, '*');
};
</script>
<template>
@ -165,6 +169,7 @@ const handleAutoSaveAndRestoreViewState = async () => {
<a-flex justify="space-between" align="center">
<a-typography-text class="title">{{ title }} --场景编辑</a-typography-text>
<a-space align="center">
<!-- <a-button @click="backToCards"> 返回 </a-button> -->
<a-button type="primary" :loading="isSaving" @click="handleSaveViewState"> 保存比例 </a-button>
<a-button v-if="editable" class="warning" @click="editable = false">
<i class="icon exit size-18 mr-8" />

View File

@ -88,7 +88,10 @@ export class AutoDoorService {
private timers = new Map<string, NodeJS.Timeout>();
private statusMap = new Map<string, 0 | 1>();
private editorService: EditorService | null = null;
private latestAutoDoorData = new Map<string, { deviceId: string; deviceStatus: number; active: boolean }>();
private latestAutoDoorData = new Map<
string,
{ deviceId: string; deviceStatus: number; active: boolean; isConnected: boolean }
>();
// 设备ID到自动门点ID的映射缓存避免每次都遍历查找
private deviceIdToPointIdMap = new Map<string, string>();
@ -250,7 +253,7 @@ export class AutoDoorService {
* @param data WebSocket推送的数据
*/
handleWebSocketData(data: AutoDoorWebSocketData): void {
const { label: deviceId, deviceStatus, active = true } = data;
const { label: deviceId, deviceStatus, active = true, isConnected = true } = data;
if (!deviceId || deviceStatus === undefined) {
console.warn('⚠️ 自动门点数据格式不正确', data);
@ -258,7 +261,7 @@ export class AutoDoorService {
}
// 缓存最新数据
this.latestAutoDoorData.set(deviceId, { deviceId, deviceStatus, active });
this.latestAutoDoorData.set(deviceId, { deviceId, deviceStatus, active, isConnected });
console.log(
`🚪 收到自动门点WebSocket数据: ${deviceStatus === 0 ? '关门(红色)' : '开门(蓝色)'} (deviceId: ${deviceId})`,
@ -291,7 +294,13 @@ export class AutoDoorService {
// 更新自动门点状态使用pointId直接更新避免查找
if (this.editorService) {
this.editorService.updateAutoDoorByDeviceId(data.deviceId, data.deviceStatus, data.active, pointId);
this.editorService.updateAutoDoorByDeviceId(
data.deviceId,
data.deviceStatus,
data.isConnected,
data.active,
pointId,
);
}
}

View File

@ -866,7 +866,6 @@ export class EditorService extends Meta2d {
public updatePointBorderColor(pointId: string, color: string): void {
const pen = this.getPenById(pointId);
if (!pen || pen.name !== 'point') return;
this.updatePen(pointId, { statusStyle: color }, false);
}
@ -874,10 +873,17 @@ export class EditorService extends Meta2d {
* ID更新自动门点状态
* @param deviceId ID
* @param deviceStatus 0=1=
* @param isConnected true=false=
* @param active
* @param pointId ID使
*/
public updateAutoDoorByDeviceId(deviceId: string, deviceStatus: number, active = true, pointId?: string): void {
public updateAutoDoorByDeviceId(
deviceId: string,
deviceStatus: number,
isConnected: boolean,
active = true,
pointId?: string,
): void {
let autoDoorPointId = pointId;
// 如果没有提供pointId则通过deviceId查找
@ -912,6 +918,7 @@ export class EditorService extends Meta2d {
point: {
...autoDoorPoint.point,
deviceStatus,
isConnected,
active,
},
},