some updates

This commit is contained in:
2025-08-13 01:27:07 +08:00
parent fc50dd1127
commit 3f493794fc
3 changed files with 92 additions and 114 deletions

View File

@@ -2,15 +2,13 @@ import type { FC } from 'react';
import { AlertOutlined, ApiOutlined } from '@ant-design/icons'; import { AlertOutlined, ApiOutlined } from '@ant-design/icons';
import { Card, Col, Row, Statistic, Tag } from 'antd'; import { Card, Col, Row, Statistic, Tag } from 'antd';
import { useState } from 'react'; import { useMemo } from 'react';
import type { NdmCameraResultVO, NdmDecoderResultVO, NdmDeviceAlarmLogResultVO, NdmKeyboardResultVO, NdmMediaServerResultVO, NdmNvrResultVO, NdmSecurityBoxResultVO, NdmSwitchResultVO, NdmVideoServerResultVO } from '@/apis/models/device'; import type { NdmCameraResultVO, NdmDecoderResultVO, NdmDeviceAlarmLogResultVO, NdmKeyboardResultVO, NdmMediaServerResultVO, NdmNvrResultVO, NdmSecurityBoxResultVO, NdmSwitchResultVO, NdmVideoServerResultVO } from '@/apis/models/device';
interface StationProps { interface StationProps {
name: string; name: string;
online: boolean; online: boolean;
// offlineDeviceCount: number;
// alarmCount: number;
ndmCameraList: NdmCameraResultVO[]; ndmCameraList: NdmCameraResultVO[];
ndmDecoderList: NdmDecoderResultVO[]; ndmDecoderList: NdmDecoderResultVO[];
ndmKeyboardList: NdmKeyboardResultVO[]; ndmKeyboardList: NdmKeyboardResultVO[];
@@ -23,25 +21,24 @@ interface StationProps {
} }
export const Station: FC<StationProps> = ({ name, online, ndmCameraList, ndmDecoderList, ndmKeyboardList, ndmMediaServerList, ndmNvrList, ndmSecurityBoxList, ndmSwitchList, ndmVideoServerList, ndmDeviceAlarmLogList }) => { export const Station: FC<StationProps> = ({ name, online, ndmCameraList, ndmDecoderList, ndmKeyboardList, ndmMediaServerList, ndmNvrList, ndmSecurityBoxList, ndmSwitchList, ndmVideoServerList, ndmDeviceAlarmLogList }) => {
const [offlineDeviceCount] = useState(12); // 使用 useMemo 计算离线设备数量
const [alarmCount] = useState(3); const offlineDeviceCount = useMemo(() => {
const offlineCameraCount = ndmCameraList.filter(device => device.deviceStatus === '20').length;
const offlineDecoderCount = ndmDecoderList.filter(device => device.deviceStatus === '20').length;
const offlineKeyboardCount = ndmKeyboardList.filter(device => device.deviceStatus === '20').length;
const offlineMediaServerCount = ndmMediaServerList.filter(device => device.deviceStatus === '20').length;
const offlineNvrCount = ndmNvrList.filter(device => device.deviceStatus === '20').length;
const offlineSecurityBoxCount = ndmSecurityBoxList.filter(device => device.deviceStatus === '20').length;
const offlineSwitchCount = ndmSwitchList.filter(device => device.deviceStatus === '20').length;
const offlineVideoServerCount = ndmVideoServerList.filter(device => device.deviceStatus === '20').length;
const offlineCameraCount = ndmCameraList.filter(device => device.deviceStatus === '20').length; return offlineCameraCount + offlineDecoderCount + offlineKeyboardCount + offlineMediaServerCount + offlineNvrCount + offlineSecurityBoxCount + offlineSwitchCount + offlineVideoServerCount;
const cameraCount = ndmCameraList.length; }, [ndmCameraList, ndmDecoderList, ndmKeyboardList, ndmMediaServerList, ndmNvrList, ndmSecurityBoxList, ndmSwitchList, ndmVideoServerList]);
const offlineDecoderCount = ndmDecoderList.filter(device => device.deviceStatus === '20').length;
const decoderCount = ndmDecoderList.length; // 使用 useMemo 计算告警数量
const offlineKeyboardCount = ndmKeyboardList.filter(device => device.deviceStatus === '20').length; const alarmCount = useMemo(() => {
const keyboardCount = ndmKeyboardList.length; return ndmDeviceAlarmLogList.length;
const offlineMediaServerCount = ndmMediaServerList.filter(device => device.deviceStatus === '20').length; }, [ndmDeviceAlarmLogList]);
const mediaServerCount = ndmMediaServerList.length;
const offlineNvrCount = ndmNvrList.filter(device => device.deviceStatus === '20').length;
const nvrCount = ndmNvrList.length;
const offlineSecurityBoxCount = ndmSecurityBoxList.filter(device => device.deviceStatus === '20').length;
const securityBoxCount = ndmSecurityBoxList.length;
const switchOfflineCount = ndmSwitchList.filter(device => device.deviceStatus === '20').length;
const switchCount = ndmSwitchList.length;
const offlineVideoServerCount = ndmVideoServerList.filter(device => device.deviceStatus === '20').length;
const videoServerCount = ndmVideoServerList.length;
return ( return (
<Card <Card
@@ -50,26 +47,24 @@ export const Station: FC<StationProps> = ({ name, online, ndmCameraList, ndmDeco
styles={{ header: name.length > 7 ? { fontSize: '12px' } : {} }} styles={{ header: name.length > 7 ? { fontSize: '12px' } : {} }}
extra={<Tag color={online ? 'success' : 'error'}>{online ? '在线' : '离线'}</Tag>} extra={<Tag color={online ? 'success' : 'error'}>{online ? '在线' : '离线'}</Tag>}
> >
{online && ( <Row gutter={16}>
<Row gutter={16}> <Col span={12}>
<Col span={12}> <Statistic
<Statistic title={<span style={{ cursor: 'pointer', textDecoration: 'underline dotted' }}>线</span>}
title={<span style={{ cursor: 'pointer', textDecoration: 'underline dotted' }}>线</span>} value={online ? offlineDeviceCount : ''}
value={offlineDeviceCount} prefix={<ApiOutlined size={12} />}
prefix={<ApiOutlined />} valueStyle={{ color: offlineDeviceCount > 0 ? '#cf1322' : undefined }}
valueStyle={{ color: offlineDeviceCount > 0 ? '#cf1322' : undefined }} />
/> </Col>
</Col> <Col span={12}>
<Col span={12}> <Statistic
<Statistic title={<span style={{ cursor: 'pointer', textDecoration: 'underline dotted' }}></span>}
title={<span style={{ cursor: 'pointer', textDecoration: 'underline dotted' }}></span>} value={online ? alarmCount : ''}
value={alarmCount} prefix={<AlertOutlined />}
prefix={<AlertOutlined />} valueStyle={{ color: alarmCount > 0 ? '#faad14' : undefined }}
valueStyle={{ color: alarmCount > 0 ? '#faad14' : undefined }} />
/> </Col>
</Col> </Row>
</Row>
)}
</Card> </Card>
); );
}; };

View File

@@ -1,17 +1,15 @@
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import type { Station } from '@/apis/domains'; import type { Station } from '@/apis/domains';
import type { PageResult } from '@/apis/models/base/page';
import type { DefParameterResultVO } from '@/apis/models/system';
import { ndmClient, userClient } from '@/apis/client'; import { ndmVerify, postDefParameterPage } from '@/apis/requests';
export function useStationListQuery() { export function useStationListQuery() {
return useQuery({ return useQuery({
queryKey: ['station-list'], queryKey: ['station-list-polling'],
queryFn: async () => { queryFn: async () => {
// 第一步:获取车站基础信息 // 第一步:获取车站基础信息
const [err, data] = await userClient.post<PageResult<DefParameterResultVO>>(`/api/system/defParameter/page`, { const { records: ndmStationList } = await postDefParameterPage('', {
current: 1, current: 1,
extra: {}, extra: {},
model: { model: {
@@ -21,12 +19,9 @@ export function useStationListQuery() {
size: 100, size: 100,
sort: 'id', sort: 'id',
}); });
if (err || !data) {
throw err;
}
// 第二步:获取每个车站的在线状态 // 第二步:获取每个车站的在线状态
const stations: Station[] = data.records.map(record => ({ const stations: Station[] = ndmStationList.map(record => ({
id: record.key ?? '', id: record.key ?? '',
code: record.value ?? '', code: record.value ?? '',
name: record.name ?? '', name: record.name ?? '',
@@ -34,9 +29,7 @@ export function useStationListQuery() {
})); }));
// 第三步:并发检查所有车站的在线状态 // 第三步:并发检查所有车站的在线状态
const pingResultList = await Promise.allSettled(stations.map((station) => { const pingResultList = await Promise.allSettled(stations.map(station => ndmVerify(station.code)));
return ndmClient.post(`/${station.code}/api/ndm/ndmKeepAlive/verify`, {}, { timeout: 5000 });
}));
// 第四步:合并状态信息 // 第四步:合并状态信息
const stationsWithStatus: Station[] = stations.map((station, index) => ({ const stationsWithStatus: Station[] = stations.map((station, index) => ({

View File

@@ -2,6 +2,8 @@ import { useQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router'; import { createFileRoute } from '@tanstack/react-router';
import { Col, Row } from 'antd'; import { Col, Row } from 'antd';
import type { PageParams } from '@/apis/models/base/page';
import { import {
postNdmCameraPage, postNdmCameraPage,
postNdmDecoderPage, postNdmDecoderPage,
@@ -11,7 +13,7 @@ import {
postNdmSecurityBoxPage, postNdmSecurityBoxPage,
postNdmSwitchPage, postNdmSwitchPage,
postNdmVideoServerPage, postNdmVideoServerPage,
} from '@/apis/requests/device'; } from '@/apis/requests';
import { Station } from '@/components/dashboard/station'; import { Station } from '@/components/dashboard/station';
import { useStationStore } from '@/store/station'; import { useStationStore } from '@/store/station';
@@ -21,80 +23,68 @@ export const Route = createFileRoute('/_app/dashboard')({
function DashboardPage() { function DashboardPage() {
const stationList = useStationStore(state => state.stationList); const stationList = useStationStore(state => state.stationList);
const onlineStationList = stationList.filter(station => station.online); const onlineStationList = stationList.filter(station => station.online);
const { data } = useQuery({ const { data, error } = useQuery({
queryKey: ['device-list', 'all-type', onlineStationList.map(s => s.code)],
queryFn: async () => {
const pageQuery = { model: {}, extra: {}, size: 5000, current: 1, sort: 'id', order: 'ascending' as const };
const stationDevicePromises = onlineStationList.map(async (station) => {
const deviceRequests = [
postNdmCameraPage(station.code, pageQuery),
postNdmDecoderPage(station.code, pageQuery),
postNdmKeyboardPage(station.code, pageQuery),
postNdmMediaServerPage(station.code, pageQuery),
postNdmNvrPage(station.code, pageQuery),
postNdmSecurityBoxPage(station.code, pageQuery),
postNdmSwitchPage(station.code, pageQuery),
postNdmVideoServerPage(station.code, pageQuery),
];
const results = await Promise.all(deviceRequests);
const [
[, cameraData],
[, decoderData],
[, keyboardData],
[, mediaServerData],
[, nvrData],
[, securityBoxData],
[, switchData],
[, videoServerData],
] = results;
return {
stationCode: station.code,
ndmCameraList: cameraData?.records ?? [],
ndmDecoderList: decoderData?.records ?? [],
ndmKeyboardList: keyboardData?.records ?? [],
ndmMediaServerList: mediaServerData?.records ?? [],
ndmNvrList: nvrData?.records ?? [],
ndmSecurityBoxList: securityBoxData?.records ?? [],
ndmSwitchList: switchData?.records ?? [],
ndmVideoServerList: videoServerData?.records ?? [],
};
});
const allStationsData = await Promise.all(stationDevicePromises);
return allStationsData.reduce((acc, result) => {
acc[result.stationCode] = result;
return acc;
}, {} as Record<string, typeof allStationsData[number]>);
},
enabled: onlineStationList.length > 0, enabled: onlineStationList.length > 0,
queryKey: ['station-list', 'device-list'],
queryFn: async () => {
const pageQuery: PageParams<{}> = {
model: {},
extra: {},
size: 5000,
current: 1,
sort: 'id',
order: 'ascending',
};
const result: Record<string, any> = {};
for (const station of onlineStationList) {
const { records: ndmCameraList } = await postNdmCameraPage(station.code, pageQuery);
console.log('ndmCameraList:', ndmCameraList);
// const { records: ndmDecoderList } = await postNdmDecoderPage(station.code, pageQuery);
// console.log('ndmDecoderList:', ndmDecoderList);
// const { records: ndmKeyboardList } = await postNdmKeyboardPage(station.code, pageQuery);
// console.log('ndmKeyboardList:', ndmKeyboardList);
// const { records: ndmMediaServerList } = await postNdmMediaServerPage(station.code, pageQuery);
// console.log('ndmMediaServerList:', ndmMediaServerList);
// const { records: ndmNvrList } = await postNdmNvrPage(station.code, pageQuery);
// console.log('ndmNvrList:', ndmNvrList);
// const { records: ndmSecurityBoxList } = await postNdmSecurityBoxPage(station.code, pageQuery);
// console.log('ndmSecurityBoxList:', ndmSecurityBoxList);
// const { records: ndmSwitchList } = await postNdmSwitchPage(station.code, pageQuery);
// console.log('ndmSwitchList:', ndmSwitchList);
// const { records: ndmVideoServerList } = await postNdmVideoServerPage(station.code, pageQuery);
// console.log('ndmVideoServerList:', ndmVideoServerList);
result[station.code] = {
ndmCameraList,
};
}
return result;
},
}); });
if (error) {
return <pre>{JSON.stringify(error, null, 2)}</pre>;
}
return ( return (
<div style={{ padding: '6px' }}> <div style={{ padding: '6px' }}>
<pre>{JSON.stringify(data, null, 2)}</pre>
<Row gutter={[6, 6]}> <Row gutter={[6, 6]}>
{stationList.map((station) => { {stationList.map((station) => {
const deviceData = data?.[station.code];
return ( return (
<Col key={station.id} span={3}> <Col key={station.id} span={3}>
<Station <Station
name={station.name} name={station.name}
online={station.online} online={station.online}
ndmCameraList={deviceData?.ndmCameraList ?? []} ndmCameraList={[]}
ndmDecoderList={deviceData?.ndmDecoderList ?? []} ndmDecoderList={[]}
ndmKeyboardList={deviceData?.ndmKeyboardList ?? []} ndmKeyboardList={[]}
ndmMediaServerList={deviceData?.ndmMediaServerList ?? []} ndmMediaServerList={[]}
ndmNvrList={deviceData?.ndmNvrList ?? []} ndmNvrList={[]}
ndmSecurityBoxList={deviceData?.ndmSecurityBoxList ?? []} ndmSecurityBoxList={[]}
ndmSwitchList={deviceData?.ndmSwitchList ?? []} ndmSwitchList={[]}
ndmVideoServerList={deviceData?.ndmVideoServerList ?? []} ndmVideoServerList={[]}
ndmDeviceAlarmLogList={[]} ndmDeviceAlarmLogList={[]}
/> />
</Col> </Col>