Files
d8d-vite-starter/src/client/admin/pages/pages_modbus_rtu_device.tsx
D8D Developer b9a3c991d0 update
2025-06-27 01:56:30 +00:00

252 lines
7.0 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import {
Button, Table, Form, Input, Select, message, Card, Badge,
} from 'antd';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import type {
DeviceMonitorData,
} from '@/share/monitorTypes';
import {
DeviceStatus, DeviceProtocolType, MetricType, DeviceStatusNameMap, DeviceProtocolTypeNameMap,
MetricTypeNameMap
} from '@/share/monitorTypes';
import { getEnumOptions } from '../utils';
import { DeviceInstanceAPI, MonitorAPI } from '../api/index';
// Modbus RTU设备监控页面
export const ModbusRtuDevicePage = () => {
const [loading, setLoading] = useState(false);
const [monitorData, setMonitorData] = useState<DeviceMonitorData[]>([]);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
const [deviceOptions, setDeviceOptions] = useState<{label: string, value: number}[]>([]);
const [formRef] = Form.useForm();
// 监控数据刷新间隔(毫秒)
const REFRESH_INTERVAL = 30000;
useEffect(() => {
fetchDeviceOptions();
fetchMonitorData();
// 设置定时刷新
const intervalId = setInterval(() => {
fetchMonitorData();
}, REFRESH_INTERVAL);
return () => clearInterval(intervalId);
}, [pagination.current, pagination.pageSize]);
const fetchDeviceOptions = async () => {
try {
const response = await DeviceInstanceAPI.getDeviceInstances();
if (response && response.data) {
const options = response.data.map((device) => ({
label: device.asset_name || `设备${device.id}`,
value: device.id
}));
setDeviceOptions(options);
}
} catch (error) {
console.error('获取设备列表失败:', error);
message.error('获取设备列表失败');
}
};
const fetchMonitorData = async () => {
setLoading(true);
try {
const values = formRef.getFieldsValue();
const params = {
page: pagination.current,
pageSize: pagination.pageSize,
device_id: values.device_id,
device_name: values.device_name,
protocol: values.protocol,
address: values.address,
metric_type: values.metric_type,
status: values.status,
};
const response = await MonitorAPI.getMonitorData(params);
if (response) {
setMonitorData(response.data || []);
setPagination({
...pagination,
total: response.total || 0,
});
}
} catch (error) {
console.error('获取监控数据失败:', error);
message.error('获取监控数据失败');
} finally {
setLoading(false);
}
};
const handleSearch = (values: any) => {
setPagination({
...pagination,
current: 1,
});
fetchMonitorData();
};
const handleTableChange = (newPagination: any) => {
setPagination({
...pagination,
current: newPagination.current,
pageSize: newPagination.pageSize,
});
};
const metricTypeOptions = getEnumOptions(MetricType, MetricTypeNameMap);
const statusOptions = getEnumOptions(DeviceStatus, DeviceStatusNameMap);
const protocolOptions = getEnumOptions(DeviceProtocolType, DeviceProtocolTypeNameMap);
const getStatusBadge = (status?: DeviceStatus) => {
switch (status) {
case DeviceStatus.NORMAL:
return <Badge status="success" text="正常" />;
case DeviceStatus.MAINTAIN:
return <Badge status="processing" text="维护中" />;
case DeviceStatus.FAULT:
return <Badge status="error" text="故障" />;
case DeviceStatus.OFFLINE:
return <Badge status="default" text="下线" />;
default:
return <Badge status="default" text="未知" />;
}
};
const columns = [
{
title: '设备ID',
dataIndex: 'device_id',
key: 'device_id',
width: 80,
},
{
title: '设备名称',
dataIndex: 'device_name',
key: 'device_name',
},
{
title: '通信协议',
dataIndex: 'protocol',
key: 'protocol',
render: (text: string) => {
const option = protocolOptions.find(opt => opt.value === text);
return option ? option.label : text;
},
},
{
title: '通信地址',
dataIndex: 'address',
key: 'address',
},
{
title: '监控指标',
dataIndex: 'metric_type',
key: 'metric_type',
render: (text: string) => {
const option = metricTypeOptions.find(opt => opt.value === text);
return option ? option.label : text;
},
},
{
title: '监控值',
dataIndex: 'metric_value',
key: 'metric_value',
render: (value: number, record: DeviceMonitorData) => {
return `${value} ${record.unit || ''}`;
},
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: DeviceStatus) => getStatusBadge(status),
},
{
title: '采集时间',
dataIndex: 'collect_time',
key: 'collect_time',
render: (text: Date) => dayjs(text).format('YYYY-MM-DD HH:mm:ss'),
},
];
return (
<div>
<Card title="Modbus RTU设备监控" style={{ marginBottom: 16 }}>
<Form
form={formRef}
layout="inline"
onFinish={handleSearch}
style={{ marginBottom: 16 }}
>
<Form.Item name="device_id" label="设备">
<Select
placeholder="选择设备"
style={{ width: 200 }}
allowClear
options={deviceOptions}
/>
</Form.Item>
<Form.Item name="device_name" label="设备名称">
<Input placeholder="输入设备名称" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="protocol" label="通信协议">
<Select
placeholder="选择通信协议"
style={{ width: 200 }}
allowClear
options={protocolOptions}
/>
</Form.Item>
<Form.Item name="address" label="通信地址">
<Input placeholder="输入通信地址" style={{ width: 200 }} />
</Form.Item>
<Form.Item name="metric_type" label="监控指标">
<Select
placeholder="选择监控指标"
style={{ width: 200 }}
allowClear
options={metricTypeOptions}
/>
</Form.Item>
<Form.Item name="status" label="状态">
<Select
placeholder="选择状态"
style={{ width: 120 }}
allowClear
options={statusOptions}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Form>
<Table
columns={columns}
dataSource={monitorData}
rowKey="id"
pagination={pagination}
loading={loading}
onChange={handleTableChange}
/>
</Card>
</div>
);
};