Files
ndm-web-platform/src/components/device/device-card/ndm-camera/camera-current-diag.vue

153 lines
5.0 KiB
Vue

<script lang="ts">
const CAMERA_TYPES = {
'001': '模拟彩色云台摄像机',
'002': '模拟彩色半球摄像机',
'003': '模拟彩色固定摄像机',
'004': '数字高清云台摄像机',
'005': '数字高清半球摄像机',
'006': '数字高清固定摄像机',
} as const;
type CameraType = keyof typeof CAMERA_TYPES;
const isCameraTypeCode = (code: string): code is CameraType => {
return code in CAMERA_TYPES;
};
</script>
<script setup lang="ts">
import type { NdmCameraResultVO, Station } from '@/apis';
import { DeviceCommonCard, DeviceHeaderCard } from '@/components';
import { useSettingStore } from '@/stores';
import { computedAsync } from '@vueuse/core';
import axios from 'axios';
import { NDescriptions, NDescriptionsItem, NFlex } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, toRefs } from 'vue';
const props = defineProps<{
ndmDevice: NdmCameraResultVO;
station: Station;
}>();
const settingStore = useSettingStore();
const { offlineDev } = storeToRefs(settingStore);
const { ndmDevice, station } = toRefs(props);
const cameraType = computed(() => {
const gbCode = ndmDevice.value.gbCode;
if (!gbCode) return '-';
const cameraTypeCode = gbCode.slice(11, 14);
if (!isCameraTypeCode(cameraTypeCode)) return '-';
return CAMERA_TYPES[cameraTypeCode];
});
const installationArea = computedAsync(async (onCancel) => {
const UNKNOWN_NAME = '-';
if (offlineDev.value) return UNKNOWN_NAME;
const abortController = new AbortController();
onCancel(() => abortController.abort());
const gbCode = ndmDevice.value.gbCode;
if (!gbCode) return UNKNOWN_NAME;
const MINIO_PREFIX = `/minio`;
const CDN_VIMP_CODES_PREFIX = `${MINIO_PREFIX}/cdn/vimp/codes`;
const CODE_STATIONS_JSON_PATH = `${CDN_VIMP_CODES_PREFIX}/codeStations.json`;
const CODE_STATION_AREAS_JSON_PATH = `${CDN_VIMP_CODES_PREFIX}/codeStationAreas.json`;
const CODE_PARKING_AREAS_JSON_PATH = `${CDN_VIMP_CODES_PREFIX}/codeParkingAreas.json`;
const CODE_OCC_AREAS_JSON_PATH = `${CDN_VIMP_CODES_PREFIX}/codeOccAreas.json`;
// minio中的编码表结构
type Unit = { name: string; type: 'train' | 'station' | 'parking' | 'occ' };
type Area = { code: string; name: string; subs: Array<{ code: string; name: string }> };
const { data: unitCodes } = await axios.get<Record<string, Unit>>(CODE_STATIONS_JSON_PATH, { signal: abortController.signal });
// 根据国标编码的前6位匹配minio中的编码表
const unitCode = gbCode.slice(0, 6);
const unit = unitCodes[unitCode];
if (!unit) return UNKNOWN_NAME;
// 获取编码表中的线路/单位类型
const unitType = unit.type;
// 国标编码的第7位到第8位为1级区域编码
const tier1AreaCode = gbCode.slice(6, 8);
// 国标编码的第9位到第11位为2级区域编码
const tier2AreaCode = gbCode.slice(8, 11);
if (unitType === 'train') {
return unit.name;
}
const areaJsonPaths: Record<string, string> = {
station: CODE_STATION_AREAS_JSON_PATH,
parking: CODE_PARKING_AREAS_JSON_PATH,
occ: CODE_OCC_AREAS_JSON_PATH,
};
const jsonPath = areaJsonPaths[unitType];
if (!jsonPath) return UNKNOWN_NAME;
// 获取1级区域
const { data: areaCodes } = await axios.get<Area[]>(jsonPath, { signal: abortController.signal });
const tier1Area = areaCodes.find((area) => area.code === tier1AreaCode);
if (!tier1Area) return UNKNOWN_NAME;
// 获取2级区域
const tier2Area = tier1Area.subs.find((area) => area.code === `${tier1AreaCode}${tier2AreaCode}`);
if (!tier2Area) return UNKNOWN_NAME;
// 拼接1级和2级区域名称
return `${tier1Area.name}-${tier2Area.name}`;
});
const commonInfo = computed(() => {
const {
createdTime,
updatedTime,
manufacturer,
gb28181Enabled,
onvifPort,
onvifUsername,
onvifPassword,
onvifMajorIndex,
onvifMinorIndex,
icmpEnabled,
community,
//
} = ndmDevice.value;
return {
创建时间: createdTime ?? '-',
更新时间: updatedTime ?? '-',
制造商: manufacturer ?? '-',
GB28181启用: `${!!gb28181Enabled ? '是' : '否'}`,
ONVIF端口: `${onvifPort ?? '-'}`,
ONVIF用户名: onvifUsername ?? '-',
ONVIF密码: onvifPassword ?? '-',
ONVIF主流索引: `${onvifMajorIndex ?? '-'}`,
ONVIF辅流索引: `${onvifMinorIndex ?? '-'}`,
ICMP启用: `${!!icmpEnabled ? '是' : '否'}`,
团体字符串: community ?? '-',
};
});
</script>
<template>
<NFlex vertical>
<DeviceHeaderCard :ndm-device="ndmDevice" :station="station">
<template #append-info>
<NDescriptions bordered size="small" label-placement="left" :columns="1" style="width: 60%; min-width: 400px">
<NDescriptionsItem label="摄像机类型" :span="1">{{ cameraType }}</NDescriptionsItem>
<NDescriptionsItem label="建议安装区域" :span="1">{{ installationArea ?? '-' }}</NDescriptionsItem>
</NDescriptions>
</template>
</DeviceHeaderCard>
<DeviceCommonCard :common-info="commonInfo" />
</NFlex>
</template>
<style scoped lang="scss"></style>