Compare commits
4 Commits
547ac67af6
...
b5e2b21d0a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5e2b21d0a | ||
|
|
b8c3878ece | ||
|
|
b109bd97db | ||
|
|
918e933435 |
@@ -1,5 +1,9 @@
|
|||||||
export interface SnapResult {
|
export interface SnapResult {
|
||||||
|
code: number;
|
||||||
|
msg: string;
|
||||||
|
data: {
|
||||||
absoluteFilePath: string;
|
absoluteFilePath: string;
|
||||||
path: string;
|
path: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export const importCameraApi = async (file: File, options?: { stationCode?: Stat
|
|||||||
export const getCameraSnapApi = async (deviceId: string, options?: { signal?: AbortSignal }) => {
|
export const getCameraSnapApi = async (deviceId: string, options?: { signal?: AbortSignal }) => {
|
||||||
const { signal } = options ?? {};
|
const { signal } = options ?? {};
|
||||||
const endpoint = `/api/ndm/ndmCamera/getSnapByDeviceId`;
|
const endpoint = `/api/ndm/ndmCamera/getSnapByDeviceId`;
|
||||||
const resp = await ndmClient.get<SnapResult>(endpoint, { params: { deviceId }, signal });
|
const resp = await ndmClient.get<SnapResult>(endpoint, { params: { deviceId }, retRaw: true, signal });
|
||||||
const data = unwrapResponse(resp);
|
const data = unwrapResponse(resp);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const saveVideoServerApi = async (saveVO: NdmVideoServerSaveVO, options?:
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateVideoServerApi = async (id: string, updateVO: NdmVideoServerUpdateVO, options?: { stationCode?: Station['code']; signal?: AbortSignal }) => {
|
export const updateVideoServerApi = async (updateVO: NdmVideoServerUpdateVO, options?: { stationCode?: Station['code']; signal?: AbortSignal }) => {
|
||||||
const { stationCode, signal } = options ?? {};
|
const { stationCode, signal } = options ?? {};
|
||||||
const client = stationCode ? ndmClient : userClient;
|
const client = stationCode ? ndmClient : userClient;
|
||||||
const prefix = stationCode ? `/${stationCode}` : '';
|
const prefix = stationCode ? `/${stationCode}` : '';
|
||||||
|
|||||||
@@ -1,7 +1,28 @@
|
|||||||
|
<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">
|
<script setup lang="ts">
|
||||||
import type { NdmCameraResultVO, Station } from '@/apis';
|
import type { NdmCameraResultVO, Station } from '@/apis';
|
||||||
import { DeviceCommonCard, DeviceHeaderCard } from '@/components';
|
import { DeviceCommonCard, DeviceHeaderCard } from '@/components';
|
||||||
import { NFlex } from 'naive-ui';
|
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';
|
import { computed, toRefs } from 'vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -9,8 +30,80 @@ const props = defineProps<{
|
|||||||
station: Station;
|
station: Station;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const { offlineDev } = storeToRefs(settingStore);
|
||||||
|
|
||||||
const { ndmDevice, station } = toRefs(props);
|
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 commonInfo = computed(() => {
|
||||||
const {
|
const {
|
||||||
createdTime,
|
createdTime,
|
||||||
@@ -44,7 +137,14 @@ const commonInfo = computed(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NFlex vertical>
|
<NFlex vertical>
|
||||||
<DeviceHeaderCard :ndm-device="ndmDevice" :station="station" />
|
<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" />
|
<DeviceCommonCard :common-info="commonInfo" />
|
||||||
</NFlex>
|
</NFlex>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const {
|
|||||||
selectedStationCode,
|
selectedStationCode,
|
||||||
selectedDeviceType,
|
selectedDeviceType,
|
||||||
selectedDevice,
|
selectedDevice,
|
||||||
hasFromPage,
|
|
||||||
selectDevice,
|
selectDevice,
|
||||||
routeDevice,
|
routeDevice,
|
||||||
// 设备管理
|
// 设备管理
|
||||||
@@ -461,16 +460,11 @@ const onLocateDeviceTree = async () => {
|
|||||||
|
|
||||||
animated.value = true;
|
animated.value = true;
|
||||||
};
|
};
|
||||||
// 渲染全线设备树时,若是首次经过路由跳转而来选择设备,则定位设备树
|
// 渲染全线设备树时,当选择的设备发生变化,则定位设备树
|
||||||
const unwatchLocate = watch(selectedDevice, async (newDevice, oldDevice) => {
|
// 暂时不考虑多次执行的问题,因为当选择的设备在设备树视口内时,不会发生滚动
|
||||||
|
watch(selectedDevice, async () => {
|
||||||
if (!!station.value) return;
|
if (!!station.value) return;
|
||||||
if (!hasFromPage.value) return;
|
|
||||||
if (!!newDevice && !oldDevice) {
|
|
||||||
if (!!deviceTreeInst.value) {
|
|
||||||
await onLocateDeviceTree();
|
await onLocateDeviceTree();
|
||||||
unwatchLocate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const useCameraSnapColumn = (tableData: Ref<DataTableRowData[]>) => {
|
|||||||
loadingMap.value[id] = true;
|
loadingMap.value[id] = true;
|
||||||
try {
|
try {
|
||||||
const snap = await getSnapByDeviceId({ deviceAlarmLog: rowData });
|
const snap = await getSnapByDeviceId({ deviceAlarmLog: rowData });
|
||||||
rowData.snapUrl = snap.url;
|
rowData.snapUrl = snap.data.url;
|
||||||
} finally {
|
} finally {
|
||||||
loadingMap.value[id] = false;
|
loadingMap.value[id] = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { tryGetDeviceType, type DeviceType } from '@/enums';
|
|||||||
import { useDeviceStore } from '@/stores';
|
import { useDeviceStore } from '@/stores';
|
||||||
import { watchDebounced } from '@vueuse/core';
|
import { watchDebounced } from '@vueuse/core';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
export const useDeviceSelection = () => {
|
export const useDeviceSelection = () => {
|
||||||
@@ -17,8 +17,6 @@ export const useDeviceSelection = () => {
|
|||||||
const selectedDeviceType = ref<DeviceType>();
|
const selectedDeviceType = ref<DeviceType>();
|
||||||
const selectedDevice = ref<NdmDeviceResultVO>();
|
const selectedDevice = ref<NdmDeviceResultVO>();
|
||||||
|
|
||||||
const hasFromPage = computed(() => !!route.query['fromPage']);
|
|
||||||
|
|
||||||
const initFromRoute = (lineDevices: LineDevices) => {
|
const initFromRoute = (lineDevices: LineDevices) => {
|
||||||
const { stationCode, deviceType, deviceDbId } = route.query;
|
const { stationCode, deviceType, deviceDbId } = route.query;
|
||||||
if (stationCode) {
|
if (stationCode) {
|
||||||
@@ -107,8 +105,6 @@ export const useDeviceSelection = () => {
|
|||||||
selectedDeviceType,
|
selectedDeviceType,
|
||||||
selectedDevice,
|
selectedDevice,
|
||||||
|
|
||||||
hasFromPage,
|
|
||||||
|
|
||||||
initFromRoute,
|
initFromRoute,
|
||||||
selectDevice,
|
selectDevice,
|
||||||
routeDevice,
|
routeDevice,
|
||||||
|
|||||||
Reference in New Issue
Block a user