refactor: 重构项目结构

- 优化 `车站-设备-告警`  轮询机制
- 改进设备卡片的布局
- 支持修改设备
- 告警轮询中获取完整告警数据
- 车站告警详情支持导出完整的 `今日告警列表`
- 支持将状态持久化到 `IndexedDB`
- 新增轮询控制 (调试模式)
- 新增离线开发模式 (调试模式)
- 新增 `IndexedDB` 数据控制 (调试模式)
This commit is contained in:
yangsy
2025-12-11 13:42:22 +08:00
commit 37781216b2
278 changed files with 17988 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import {
detailCameraApi,
detailDecoderApi,
detailKeyboardApi,
detailMediaServerApi,
detailNvrApi,
detailSecurityBoxApi,
detailSwitchApi,
detailVideoServerApi,
type NdmDeviceResultVO,
type Station,
} from '@/apis';
import { DEVICE_TYPE_LITERALS, tryGetDeviceType } from '@/enums';
import { detailAlarmHostApi } from '../alarm/ndm-alarm-host';
export const detailDeviceApi = async (device: NdmDeviceResultVO, options?: { stationCode?: Station['code']; signal?: AbortSignal }): Promise<NdmDeviceResultVO | undefined> => {
const { stationCode, signal } = options ?? {};
const { id, deviceType: deviceTypeCode } = device;
if (!id || !deviceTypeCode) throw new Error('未知的设备');
const deviceType = tryGetDeviceType(deviceTypeCode);
if (!deviceType) throw new Error('未知的设备');
if (deviceType === DEVICE_TYPE_LITERALS.ndmAlarmHost) {
await detailAlarmHostApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmCamera) {
await detailCameraApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmDecoder) {
await detailDecoderApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmKeyboard) {
await detailKeyboardApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmMediaServer) {
await detailMediaServerApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmNvr) {
await detailNvrApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmSecurityBox) {
await detailSecurityBoxApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmSwitch) {
await detailSwitchApi(id, { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmVideoServer) {
await detailVideoServerApi(id, { stationCode, signal });
return;
}
return undefined;
};

View File

@@ -0,0 +1,2 @@
export * from './detail-device';
export * from './probe-device';

View File

@@ -0,0 +1,33 @@
import { probeDecoderApi, probeMediaServerApi, probeNvrApi, probeSecurityBoxApi, probeSwitchApi, probeVideoServerApi, type NdmDeviceResultVO, type Station } from '@/apis';
import { DEVICE_TYPE_LITERALS, tryGetDeviceType } from '@/enums';
export const probeDeviceApi = async (device: NdmDeviceResultVO, options?: { stationCode?: Station['code']; signal?: AbortSignal }) => {
const { stationCode, signal } = options ?? {};
const deviceType = tryGetDeviceType(device.deviceType);
const deviceDbId = device.id;
if (!deviceType || !deviceDbId) throw new Error('未知的设备');
if (deviceType === DEVICE_TYPE_LITERALS.ndmDecoder) {
await probeDecoderApi([deviceDbId], { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmNvr) {
await probeNvrApi([deviceDbId], { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmSecurityBox) {
await probeSecurityBoxApi([deviceDbId], { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmMediaServer) {
await probeMediaServerApi([deviceDbId], { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmSwitch) {
await probeSwitchApi([deviceDbId], { stationCode, signal });
return;
}
if (deviceType === DEVICE_TYPE_LITERALS.ndmVideoServer) {
await probeVideoServerApi([deviceDbId], { stationCode, signal });
return;
}
};