Files
ndm-web-platform/src/pages/vimp/stores/alarm.ts
T
yangsy ad9a0011a5 feat(vimp): 新增摄像头和告警通道的全局索引记录及构建方法
在摄像头、告警的Pinia存储中新增对应的数据记录与构建函数,并在渠道查询组合式函数中调用生成全局索引映射数据
2026-06-09 13:17:59 +08:00

176 lines
6.3 KiB
TypeScript

import { defineStore } from 'pinia';
import type { VimpChannel, VimpSite } from '../apis';
import { shallowRef } from 'vue';
import type { AlarmMainAreaNodeOption, AlarmNodeOption, CodeLines, CodeSites, AlarmLineTabPane, AlarmSiteNodeOption, AlarmSubAreaNodeOption, CompiledCodeAreas } from '../types';
interface BuildLineTabPanesParams {
sites: VimpSite[];
siteCodeToAlarmsMap: Map<string, VimpChannel[]>;
codeLines: CodeLines;
codeSites: CodeSites;
compiledCodeAreas: CompiledCodeAreas;
}
const buildMainAreaNodeKey = (siteCode: string, mainAreaCode: string) => `${siteCode}${mainAreaCode}`;
const buildSubAreaNodeKey = (siteCode: string, areaCode: string) => `${siteCode}${areaCode}`;
export const useAlarmStore = defineStore('vimp-alarm-store', () => {
const lineTabPanes = shallowRef<AlarmLineTabPane[]>([]);
const alarmRecord = shallowRef<Record<string, VimpChannel>>({});
const buildLineTabPanes = (params: BuildLineTabPanesParams) => {
const { sites, siteCodeToAlarmsMap, codeLines, codeSites, compiledCodeAreas } = params;
const result: AlarmLineTabPane[] = [];
// 1. 线路索引 lineCode -> AlarmLineTabPane
const linePaneMap = new Map<string, AlarmLineTabPane>();
// 遍历所有站点
for (const site of sites) {
// 2. 站点节点 siteNode 只在当前轮次中顺序创建,不需要建立索引
const lineCode = site.code.substring(0, 3);
const lineName = codeLines[lineCode]?.name ?? '';
let linePane = linePaneMap.get(lineCode);
if (!linePane) {
linePane = { lineCode, lineName, alarmTree: [] };
linePaneMap.set(lineCode, linePane);
result.push(linePane);
}
const siteCode = site.code;
const siteMeta = codeSites[siteCode];
if (!siteMeta) continue;
const siteName = siteMeta.name;
const siteType = siteMeta.type;
const compiledCodeAreaMaps = compiledCodeAreas[siteType];
const mainAreaCodeLength = siteType === 'train' ? 3 : 2;
// 构造站点节点
const siteNode: AlarmSiteNodeOption = {
key: siteCode,
label: siteName,
children: [],
stats: { online: 0, offline: 0, total: 0 },
online: site.online,
};
linePane.alarmTree.push(siteNode);
// 获取所有警报器
const alarms = siteCodeToAlarmsMap.get(siteCode);
if (!alarms) continue;
// 3. 1级区域索引 mainAreaNodeKey -> AlarmMainAreaNodeOption
// mainAreaNodeKey = ${siteCode}${alarmMainAreaCode}
const mainAreaNodeMap = new Map<string, AlarmMainAreaNodeOption>();
// 4. 2级区域索引 subAreaNodeKey -> AlarmSubAreaNodeOption
// subAreaNodeKey = ${siteCode}${alarmAreaCode}
const subAreaNodeMap = new Map<string, AlarmSubAreaNodeOption>();
// 5. 警报器索引 subAreaNodeKey -> Set<AlarmGbCode>
const subAreaNodeKeyToAlarmGbCodeSetMap = new Map<string, Set<string>>();
// 遍历警报器
for (const alarm of alarms) {
// 计算相关编码
const { code: alarmGbCode, name: alarmName } = alarm;
const alarmAreaCode = alarmGbCode.substring(6, 11);
const alarmMainAreaCode = alarmAreaCode.slice(0, mainAreaCodeLength);
// 查找1级区域,如果未找到则跳过该警报器
const mainArea = compiledCodeAreaMaps.mainAreaMap.get(alarmMainAreaCode);
if (!mainArea) continue;
// 尝试从索引中获取1级区域节点,若不存在则创建
const mainAreaNodeKey = buildMainAreaNodeKey(siteCode, alarmMainAreaCode);
let mainAreaNode = mainAreaNodeMap.get(mainAreaNodeKey);
if (!mainAreaNode) {
mainAreaNode = {
key: mainAreaNodeKey,
label: mainArea.name,
children: [],
stats: { online: 0, offline: 0, total: 0 },
site: site,
areaLevel: 1,
};
mainAreaNodeMap.set(mainAreaNodeKey, mainAreaNode);
siteNode.children?.push(mainAreaNode);
}
// 查找2级区域,如果未找到则跳过该警报器
const subArea = compiledCodeAreaMaps.subAreaMap.get(alarmAreaCode);
if (!subArea) continue;
// 尝试从索引中获取2级区域节点,若不存在则创建
const subAreaNodeKey = buildSubAreaNodeKey(siteCode, alarmAreaCode);
let subAreaNode = subAreaNodeMap.get(subAreaNodeKey);
if (!subAreaNode) {
subAreaNode = {
key: subAreaNodeKey,
label: subArea.name,
children: [],
stats: { online: 0, offline: 0, total: 0 },
site: site,
areaLevel: 2,
};
subAreaNodeMap.set(subAreaNodeKey, subAreaNode);
mainAreaNode.children?.push(subAreaNode);
}
// 构造警报器节点
let alarmGbCodeSet = subAreaNodeKeyToAlarmGbCodeSetMap.get(subAreaNodeKey);
if (!alarmGbCodeSet) {
alarmGbCodeSet = new Set<string>();
subAreaNodeKeyToAlarmGbCodeSetMap.set(subAreaNodeKey, alarmGbCodeSet);
}
if (alarmGbCodeSet.has(alarmGbCode)) continue;
alarmGbCodeSet.add(alarmGbCode);
const alarmType = alarm.code.substring(11, 14);
const alarmNode: AlarmNodeOption = {
key: alarmGbCode,
label: alarmName,
type: alarmType,
alarm: alarm,
site: site,
};
subAreaNode.children?.push(alarmNode);
// 统计站点、区域、子区域的在线/离线/总警报器数量
siteNode.stats.total++;
mainAreaNode.stats.total++;
subAreaNode.stats.total++;
if (alarm.status === 1) {
siteNode.stats.online++;
mainAreaNode.stats.online++;
subAreaNode.stats.online++;
} else if (alarm.status === 0) {
siteNode.stats.offline++;
mainAreaNode.stats.offline++;
subAreaNode.stats.offline++;
}
}
}
lineTabPanes.value = result;
};
const buildAlarmRecord = (siteCodeToAlarmsMap: Map<string, VimpChannel[]>) => {
const record: Record<string, VimpChannel> = {};
for (const [, alarms] of siteCodeToAlarmsMap) {
for (const alarm of alarms) {
record[alarm.code] = alarm;
}
}
alarmRecord.value = record;
};
return {
lineTabPanes,
alarmRecord,
buildLineTabPanes,
buildAlarmRecord,
};
});