feat(area-edit): 将门区域设备ID输入框改为下拉选择,通过查询设备映射列表实现设备绑定以提升用户体验

This commit is contained in:
xudan 2025-12-01 15:09:07 +08:00
parent db5b2275f7
commit 22cf89f7e9
4 changed files with 122 additions and 17 deletions

View File

@ -4,5 +4,5 @@ ENV_WEBSOCKET_BASE=/ws
ENV_STORAGE_WEBSOCKET_BASE=/vwedWs
# 开发环境token配置 - 可以手动设置或从另一个项目获取后填入
ENV_DEV_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NjQxNjM2MzIsInVzZXJuYW1lIjoiYWRtaW4ifQ.IC24_YwD10DPM6PYyB-aBHoN4BMmDnQYe_8ZGI-Cyzg
ENV_DEV_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3NjQ3MDExNDcsInVzZXJuYW1lIjoiYWRtaW4ifQ.NHLOjXm9JblCXXaDmc8PRvqB-uIpjwltrFh2EH4usIc
ENV_DEV_TENANT_ID=1000

48
src/apis/device/api.ts Normal file
View File

@ -0,0 +1,48 @@
import http from '@core/http';
const enum API {
= '/device/mapping/queryByType',
}
/**
*
*/
export interface DeviceMappingDTO {
id: string;
deviceUniqueName: string;
protocolType: string;
mappingType: string;
brandName: string | null;
ipAddress: string | null;
port: number;
slaveId: number;
enabled: number;
sceneId: string | null;
}
/**
*
*/
export const DeviceTypeMapping = {
'0': '非保持呼叫器',
'4': '保持呼叫器',
'1': '门',
'2': '电梯',
'3': '光电传感器'
} as const;
/**
*
* @param type
* @returns DeviceMappingDTO[]
*/
export async function queryDeviceMappingByType(type: string): Promise<DeviceMappingDTO[]> {
type ResponseType = DeviceMappingDTO[];
try {
const response = await http.get<ResponseType>(`${API.}?type=${type}`);
return response || [];
} catch (error) {
console.error('根据设备类型查询映射关系失败:', error);
return [];
}
}

1
src/apis/device/index.ts Normal file
View File

@ -0,0 +1 @@
export * from './api';

View File

@ -1,10 +1,11 @@
<script setup lang="ts">
import { type DeviceMappingDTO,queryDeviceMappingByType } from '@api/device';
import { type MapAreaInfo, MapAreaType, type MapPen, MapPointType } from '@api/map';
import { DOOR_AREA_TYPE } from '@api/map/door-area';
import type { PointBindModalRef } from '@common/modal/point-bind-modal.vue';
import type { EditorService } from '@core/editor.service';
import sTheme from '@core/theme.service';
import { ref, shallowRef } from 'vue';
import { ref, shallowRef, watch } from 'vue';
import { computed, inject, type InjectionKey, type ShallowRef } from 'vue';
type Props = {
@ -54,6 +55,60 @@ const points = computed<MapPen[]>(
);
const actions = computed<MapPen[]>(() => points.value?.filter(({ point }) => point?.type === MapPointType.动作点));
//
const deviceMappings = ref<DeviceMappingDTO[]>([]);
const selectedDeviceId = ref<string>('');
const loading = ref<boolean>(false);
//
const fetchDeviceMappings = async () => {
if (!area.value || (area.value?.type as any) !== DOOR_AREA_TYPE) return;
loading.value = true;
try {
//
const deviceType = '1'; // "1"
deviceMappings.value = await queryDeviceMappingByType(deviceType);
// ID
if (area.value.doorDeviceId) {
selectedDeviceId.value = area.value.doorDeviceId;
}
} catch (error) {
console.error('获取设备映射失败:', error);
deviceMappings.value = [];
} finally {
loading.value = false;
}
};
//
watch(area, (newArea) => {
if (newArea && (newArea.type as any) === DOOR_AREA_TYPE) {
fetchDeviceMappings();
}
}, { immediate: true });
//
const handleDeviceChange = (deviceId: string) => {
if (!props.id) return;
selectedDeviceId.value = deviceId;
// ID
editor.value.updateArea(props.id, { doorDeviceId: deviceId });
// ID
if (area.value?.routes) {
area.value.routes.forEach((rid: string) => {
const rpen = editor.value.getPenById(rid) as any;
const merged = { ...(rpen?.route || {}), deviceId };
editor.value.updatePen(rid, { route: merged }, true);
});
}
};
</script>
<template>
@ -196,21 +251,22 @@ const actions = computed<MapPen[]>(() => points.value?.filter(({ point }) => poi
<a-typography-text>{{ $t('设备ID') }}:</a-typography-text>
</a-col>
<a-col :span="24">
<a-input
:placeholder="$t('请输入设备ID')"
:value="area.doorDeviceId"
@change="
(e: any) => {
const v = e?.target?.value;
editor.updateArea(id, { doorDeviceId: v });
(area.routes || []).forEach((rid: string) => {
const rpen = editor.getPenById(rid) as any;
const merged = { ...(rpen?.route || {}), deviceId: v };
editor.updatePen(rid, { route: merged }, true);
});
}
"
/>
<a-select
v-model:value="selectedDeviceId"
:placeholder="$t('请选择设备')"
:loading="loading"
allow-clear
@change="handleDeviceChange"
>
<a-select-option
v-for="device in deviceMappings"
:key="device.id"
:value="device.id"
:label="device.deviceUniqueName"
>
{{ device.deviceUniqueName }}
</a-select-option>
</a-select>
</a-col>
</a-row>