refactor(vimp): 重构摄像头站点处理逻辑,修正站点匹配问题

将站点聚合逻辑从摄像头store移至设备中心查询模块,基于通道编码生成正确的站点列表,解决接口返回站点编码不匹配的问题
简化buildLineTabPanes函数的参数和内部处理流程
移除未使用的@vueuse/core的objectEntries导入
This commit is contained in:
yangsy
2026-05-30 13:48:20 +08:00
parent 3e88379eb9
commit df1c7deead
2 changed files with 70 additions and 76 deletions
@@ -4,7 +4,7 @@ import type { AxiosRequestConfig } from 'axios';
import axios from 'axios';
import type { CodeArea, CodeLines, CodeSites } from '../../types';
import { useCameraStore, useAlarmStore } from '../../stores';
import { catalogAllDeviceApi, catalogChannelApi, type VimpChannel } from '../../apis';
import { catalogAllDeviceApi, catalogChannelApi, type VimpChannel, type VimpStation } from '../../apis';
const config: AxiosRequestConfig = {
headers: {
@@ -46,36 +46,65 @@ export const useDeviceCenterQuery = () => {
const codeOccAreas = (await axios.get<CodeArea[]>('/cdn/vimp/codes/codeOccAreas.json', config)).data;
const codeTrainAreas = buildTrainAreas();
const sitesFromApi = await catalogAllDeviceApi({ signal });
const siteCamerasMapFromApi = new Map<string, VimpChannel[]>();
const siteAlarmsMapFromApi = new Map<string, VimpChannel[]>();
const sitesFromApi = await catalogAllDeviceApi({ signal });
if (!!sitesFromApi) {
for (const site of sitesFromApi) {
const channels = await catalogChannelApi(site.code, { signal });
if (!channels || channels.length === 0) continue;
const cameras: VimpChannel[] = [];
const alarms: VimpChannel[] = [];
channels.forEach((channel) => {
const typeCode = Number(channel.code.substring(11, 14));
if (typeCode >= 4 && typeCode <= 6) {
cameras.push(channel);
} else if ((typeCode >= 101 && typeCode <= 108) || (typeCode >= 810 && typeCode <= 815)) {
alarms.push(channel);
}
});
const siteCode = site.code.substring(0, 6);
siteCamerasMapFromApi.set(siteCode, cameras);
siteAlarmsMapFromApi.set(siteCode, alarms);
}
for (const site of sitesFromApi ?? []) {
const channels = await catalogChannelApi(site.code, { signal });
if (!channels || channels.length === 0) continue;
const cameras: VimpChannel[] = [];
const alarms: VimpChannel[] = [];
channels.forEach((channel) => {
const typeCode = Number(channel.code.substring(11, 14));
if (typeCode >= 4 && typeCode <= 6) {
cameras.push(channel);
} else if ((typeCode >= 101 && typeCode <= 108) || (typeCode >= 810 && typeCode <= 815)) {
alarms.push(channel);
}
});
const siteCode = site.code.substring(0, 6);
siteCamerasMapFromApi.set(siteCode, cameras);
siteAlarmsMapFromApi.set(siteCode, alarms);
}
// 从 /allDevice 接口获取的站点信息并不保证真实性和完整性,
// 例如有一个站点的编码是 010699 开头,但是其下的通道是 010199 和 010599 开头,
// 而 010699 是一个不存在的站点编码,所以需要基于通道的编码来确定所有的站点。
const sites: VimpStation[] = [];
const siteCamerasMap = new Map<string, VimpChannel[]>();
const siteOnlineMap = new Map<string, boolean>();
(sitesFromApi ?? []).forEach((site) => siteOnlineMap.set(site.code.substring(0, 6), site.online));
const builtSitesSet = new Set<string>();
siteCamerasMapFromApi.forEach((cameras, siteCode) => {
for (const camera of cameras) {
const { code: cameraGbCode } = camera;
const cameraSiteCode = cameraGbCode.substring(0, 6);
// 聚合同一站点的摄像机
if (!siteCamerasMap.has(cameraSiteCode)) {
siteCamerasMap.set(cameraSiteCode, []);
}
siteCamerasMap.get(cameraSiteCode)!.push(camera);
// 如果码表中不存在该站点则跳过
if (!(cameraSiteCode in codeSites)) continue;
// 如果该站点已被添加则跳过
if (builtSitesSet.has(cameraSiteCode)) continue;
// 添加该站点到站点列表
sites.push({
code: cameraSiteCode,
name: codeSites[cameraSiteCode]?.name ?? '',
// 要用 siteCode,而不是 cameraSiteCode
// 因为 siteCode 是 010699cameraSiteCode 是 010199 和 010599
// 我们要将 010699 的状态分派给 010199 和 010599
online: siteOnlineMap.get(siteCode) ?? false,
});
// 标记该站点已被添加
builtSitesSet.add(cameraSiteCode);
}
});
cameraStore.buildLineTabPanes({
sitesFromApi,
siteCamerasMapFromApi,
sites,
siteCamerasMap,
codeLines,
codeSites,
codeStationAreas,
+15 -50
View File
@@ -6,11 +6,10 @@ import { NIcon } from 'naive-ui';
import BulletCamera from '../components/icon/bullet-camera.vue';
import PtzCamera from '../components/icon/ptz-camera.vue';
import HemiPtzCamera from '../components/icon/hemi-ptz-camera.vue';
import { objectEntries } from '@vueuse/core';
interface BuildLineTabPanesParams {
sitesFromApi: VimpStation[] | null;
siteCamerasMapFromApi: Map<string, VimpChannel[]>;
sites: VimpStation[];
siteCamerasMap: Map<string, VimpChannel[]>;
codeLines: CodeLines;
codeSites: CodeSites;
codeStationAreas: CodeArea[];
@@ -23,57 +22,23 @@ export const useCameraStore = defineStore('vimp-camera-store', () => {
const lineTabPanes = ref<CameraLineTabPane[]>([]);
const buildLineTabPanes = (params: BuildLineTabPanesParams) => {
const { sitesFromApi, siteCamerasMapFromApi, codeLines, codeSites, codeStationAreas, codeParkingAreas, codeOccAreas, codeTrainAreas } = params;
if (!sitesFromApi) {
lineTabPanes.value = [];
return;
}
// 构造线路TabPane
const _lineTabPanes: CameraLineTabPane[] = [];
const lineCode = sitesFromApi.at(0)?.code.substring(0, 3) ?? '';
const lineName = codeLines[lineCode]?.name ?? '';
if (!_lineTabPanes.some((lineNode) => lineNode.lineCode === lineCode)) {
_lineTabPanes.push({
lineCode,
lineName,
cameraTree: [],
});
}
const { sites, siteCamerasMap, codeLines, codeSites, codeStationAreas, codeParkingAreas, codeOccAreas, codeTrainAreas } = params;
// 从 /allDevice 接口获取的站点信息并不保证真实性和完整性,
// 例如有一个站点的编码是 010699 开头,但是其下的通道是 010199 和 010599 开头,
// 而 010699 是一个不存在的站点编码,所以需要基于通道的编码来确定所有的站点。
const sites: VimpStation[] = [];
const siteCamerasMap = new Map<string, VimpChannel[]>();
const siteOnlineMap = new Map<string, boolean>();
sitesFromApi.forEach((site) => siteOnlineMap.set(site.code.substring(0, 6), site.online));
const visitedSitesSet = new Set<string>();
siteCamerasMapFromApi.forEach((cameras, siteCode) => {
for (const camera of cameras) {
const { code: cameraGbCode } = camera;
const cameraSiteCode = cameraGbCode.substring(0, 6);
// 聚合同一站点的摄像机
if (!siteCamerasMap.has(cameraSiteCode)) {
siteCamerasMap.set(cameraSiteCode, []);
}
siteCamerasMap.get(cameraSiteCode)!.push(camera);
// 如果码表中不存在该站点则跳过
if (!(cameraSiteCode in codeSites)) continue;
// 如果该站点已被添加则跳过
if (visitedSitesSet.has(cameraSiteCode)) continue;
// 标记该站点已被添加
visitedSitesSet.add(cameraSiteCode);
// 添加该站点到站点列表
sites.push({
code: cameraSiteCode,
name: codeSites[cameraSiteCode]?.name ?? '',
online: siteOnlineMap.get(siteCode) ?? false,
});
}
});
// 线路TabPane
const _lineTabPanes: CameraLineTabPane[] = [];
// 遍历所有站点
for (const site of sites) {
const lineCode = site.code.substring(0, 3);
const lineName = codeLines[lineCode]?.name ?? '';
if (!_lineTabPanes.some((lineNode) => lineNode.lineCode === lineCode)) {
_lineTabPanes.push({
lineCode,
lineName,
cameraTree: [],
});
}
const siteCode = site.code;
const siteName = codeSites[siteCode]?.name;
if (!siteName) continue;