feat: 新增多厂商安防箱支持并重构相关逻辑

- 新增安防箱适配器模块,统一封装不同厂商的设备操作逻辑
- 拆分原有安防箱API为beidian、ningtech两个厂商的专属实现
- 扩展安防箱诊断信息接口,补充设备ID、版本等元数据字段
- 更新安防箱设备卡片组件,支持自动识别厂商并适配空开控制逻辑
This commit is contained in:
yangsy
2026-05-19 15:01:27 +08:00
parent a43a8b24e3
commit c3f3844cd5
7 changed files with 139 additions and 14 deletions
@@ -2,8 +2,6 @@
import {
detailDeviceApi,
probeDeviceApi,
rebootSecurityBoxApi,
turnCitcuitStatusApi,
updateDeviceApi,
type LinkDescription,
type NdmDeviceResultVO,
@@ -16,6 +14,7 @@ import { SecurityBoxCircuitLinkModal } from '@/components';
import { usePermission } from '@/composables';
import { SELECT_DEVICE_FN_INJECTION_KEY } from '@/constants';
import { PERMISSION_TYPE_LITERALS } from '@/enums';
import { normalizeSecurityBoxWriteCommunity, dispatchRebootSecurityBoxApi, dispatchTurnCircuitStatusApi, normalizeSecurityBoxCircuitIndex } from '@/helpers';
import { useDeviceStore, useSettingStore } from '@/stores';
import { parseErrorFeedback } from '@/utils';
import { useMutation } from '@tanstack/vue-query';
@@ -31,6 +30,7 @@ import { computed, inject, ref, toRefs } from 'vue';
const props = defineProps<{
ndmDevice: NdmSecurityBoxResultVO;
station: Station;
vendor?: string;
circuits?: NdmSecurityBoxCircuit[];
}>();
@@ -44,7 +44,7 @@ const { useLocalDB } = storeToRefs(settingStore);
const { hasPermission } = usePermission();
const { ndmDevice, station, circuits } = toRefs(props);
const { ndmDevice, station, vendor, circuits } = toRefs(props);
const showCard = computed(() => !!circuits.value && circuits.value.length > 0);
@@ -52,6 +52,10 @@ const localCircuits = ref<NdmSecurityBoxCircuit[]>([]);
watchImmediate(circuits, (newCircuits) => {
localCircuits.value = newCircuits?.map((circuit) => ({ ...circuit })) ?? [];
const circuitCount = ndmDevice.value.circuitCount;
if (!!circuitCount) {
localCircuits.value = localCircuits.value.slice(0, circuitCount);
}
});
const getCircuitStatusTagType = (circuit: NdmSecurityBoxCircuit): TagProps['type'] => {
@@ -79,13 +83,19 @@ const { mutate: turnStatus, isPending: turning } = useMutation({
window.$loadingBar.start();
const { circuitIndex, newStatus } = params;
if (!ndmDevice.value.ipAddress) {
const community = normalizeSecurityBoxWriteCommunity(ndmDevice.value, vendor.value);
const ipAddress = ndmDevice.value.ipAddress;
if (!ipAddress) {
throw new Error('设备IP地址不存在');
}
const status = newStatus ? 1 : 0;
const stationCode = station.value.code;
const signal = abortController.value.signal;
await turnCitcuitStatusApi(ndmDevice.value.ipAddress, circuitIndex, status, { stationCode, signal });
const turnCircuitStatusApi = dispatchTurnCircuitStatusApi(vendor.value);
const normalizedCircuitIndex = normalizeSecurityBoxCircuitIndex(circuitIndex, vendor.value);
await turnCircuitStatusApi(community, ipAddress, normalizedCircuitIndex, status, { stationCode, signal });
await probeDeviceApi(ndmDevice.value, { stationCode, signal });
return status;
},
@@ -110,13 +120,17 @@ const { mutate: reboot, isPending: rebooting } = useMutation({
window.$loadingBar.start();
if (!ndmDevice.value.ipAddress) {
const community = normalizeSecurityBoxWriteCommunity(ndmDevice.value, vendor.value);
const ipAddress = ndmDevice.value.ipAddress;
if (!ipAddress) {
throw new Error('设备IP地址不存在');
}
const stationCode = station.value.code;
const signal = abortController.value.signal;
await rebootSecurityBoxApi(ndmDevice.value.ipAddress, { stationCode, signal });
const rebootSecurityBoxApi = dispatchRebootSecurityBoxApi(vendor.value);
await rebootSecurityBoxApi(community, ipAddress, { stationCode, signal });
},
onSuccess: () => {
window.$loadingBar.finish();
@@ -1,6 +1,7 @@
<script setup lang="ts">
import type { NdmSecurityBoxDiagInfo, NdmSecurityBoxResultVO, Station } from '@/apis';
import { DeviceCommonCard, DeviceHardwareCard, DeviceHeaderCard, SecurityBoxCircuitCard, SecurityBoxEnvCard, type DeviceCommonCardProps } from '@/components';
import { SECURITY_BOX_VENDOR_LITERALS } from '@/helpers';
import destr from 'destr';
import { NFlex } from 'naive-ui';
import { computed, toRefs } from 'vue';
@@ -19,6 +20,20 @@ const lastDiagInfo = computed(() => {
return result as NdmSecurityBoxDiagInfo;
});
// 解析安防箱厂商
const vendor = computed(() => {
// 先读取诊断信息中的 stCommonInfo 中的设备厂商
if (!!lastDiagInfo.value?.stCommonInfo?.设备厂商) {
return lastDiagInfo.value.stCommonInfo.设备厂商.trim().toLocaleLowerCase();
}
// 如果 stCommonInfo 中没有设备厂商,再读取 ndmDevice 中的 manufacturer
if (!!ndmDevice.value.manufacturer) {
return ndmDevice.value.manufacturer.trim().toLocaleLowerCase();
}
// 如果 ndmDevice 中也没有 manufacturer,返回 beidian 作为兜底
return SECURITY_BOX_VENDOR_LITERALS.beidian;
});
const commonInfo = computed<DeviceCommonCardProps['commonInfo']>(() => {
const { stCommonInfo } = lastDiagInfo.value ?? {};
const { 设备ID, 软件版本, 设备厂商, 设备别名, 设备型号, 硬件版本 } = stCommonInfo ?? {};
@@ -55,7 +70,7 @@ const circuits = computed(() => lastDiagInfo.value?.info?.at(0)?.circuits);
<DeviceCommonCard :common-info="commonInfo" />
<DeviceHardwareCard :cpu-usage="cpuUsage" :mem-usage="memUsage" />
<SecurityBoxEnvCard :fan-speeds="fanSpeeds" :temperature="temperature" :humidity="humidity" :switches="switches" />
<SecurityBoxCircuitCard :ndm-device="ndmDevice" :station="station" :circuits="circuits" />
<SecurityBoxCircuitCard :ndm-device="ndmDevice" :station="station" :vendor="vendor" :circuits="circuits" />
</NFlex>
</template>