pages_modbus_rtu_device.tsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import React, { useState, useEffect } from 'react';
  2. import {
  3. Button, Table, Form, Input, Select, message, Card, Badge,
  4. } from 'antd';
  5. import dayjs from 'dayjs';
  6. import 'dayjs/locale/zh-cn';
  7. import type {
  8. DeviceMonitorData,
  9. } from '../share/monitorTypes.ts';
  10. import {
  11. DeviceStatus, DeviceProtocolType, MetricType, DeviceStatusNameMap, DeviceProtocolTypeNameMap,
  12. MetricTypeNameMap
  13. } from '../share/monitorTypes.ts';
  14. import { getEnumOptions } from './utils.ts';
  15. import { DeviceInstanceAPI, MonitorAPI } from './api/index.ts';
  16. // Modbus RTU设备监控页面
  17. export const ModbusRtuDevicePage = () => {
  18. const [loading, setLoading] = useState(false);
  19. const [monitorData, setMonitorData] = useState<DeviceMonitorData[]>([]);
  20. const [pagination, setPagination] = useState({
  21. current: 1,
  22. pageSize: 10,
  23. total: 0,
  24. });
  25. const [deviceOptions, setDeviceOptions] = useState<{label: string, value: number}[]>([]);
  26. const [formRef] = Form.useForm();
  27. // 监控数据刷新间隔(毫秒)
  28. const REFRESH_INTERVAL = 30000;
  29. useEffect(() => {
  30. fetchDeviceOptions();
  31. fetchMonitorData();
  32. // 设置定时刷新
  33. const intervalId = setInterval(() => {
  34. fetchMonitorData();
  35. }, REFRESH_INTERVAL);
  36. return () => clearInterval(intervalId);
  37. }, [pagination.current, pagination.pageSize]);
  38. const fetchDeviceOptions = async () => {
  39. try {
  40. const response = await DeviceInstanceAPI.getDeviceInstances();
  41. if (response && response.data) {
  42. const options = response.data.map((device) => ({
  43. label: device.asset_name || `设备${device.id}`,
  44. value: device.id
  45. }));
  46. setDeviceOptions(options);
  47. }
  48. } catch (error) {
  49. console.error('获取设备列表失败:', error);
  50. message.error('获取设备列表失败');
  51. }
  52. };
  53. const fetchMonitorData = async () => {
  54. setLoading(true);
  55. try {
  56. const values = formRef.getFieldsValue();
  57. const params = {
  58. page: pagination.current,
  59. pageSize: pagination.pageSize,
  60. device_id: values.device_id,
  61. device_name: values.device_name,
  62. protocol: values.protocol,
  63. address: values.address,
  64. metric_type: values.metric_type,
  65. status: values.status,
  66. };
  67. const response = await MonitorAPI.getMonitorData(params);
  68. if (response) {
  69. setMonitorData(response.data || []);
  70. setPagination({
  71. ...pagination,
  72. total: response.total || 0,
  73. });
  74. }
  75. } catch (error) {
  76. console.error('获取监控数据失败:', error);
  77. message.error('获取监控数据失败');
  78. } finally {
  79. setLoading(false);
  80. }
  81. };
  82. const handleSearch = (values: any) => {
  83. setPagination({
  84. ...pagination,
  85. current: 1,
  86. });
  87. fetchMonitorData();
  88. };
  89. const handleTableChange = (newPagination: any) => {
  90. setPagination({
  91. ...pagination,
  92. current: newPagination.current,
  93. pageSize: newPagination.pageSize,
  94. });
  95. };
  96. const metricTypeOptions = getEnumOptions(MetricType, MetricTypeNameMap);
  97. const statusOptions = getEnumOptions(DeviceStatus, DeviceStatusNameMap);
  98. const protocolOptions = getEnumOptions(DeviceProtocolType, DeviceProtocolTypeNameMap);
  99. const getStatusBadge = (status?: DeviceStatus) => {
  100. switch (status) {
  101. case DeviceStatus.NORMAL:
  102. return <Badge status="success" text="正常" />;
  103. case DeviceStatus.MAINTAIN:
  104. return <Badge status="processing" text="维护中" />;
  105. case DeviceStatus.FAULT:
  106. return <Badge status="error" text="故障" />;
  107. case DeviceStatus.OFFLINE:
  108. return <Badge status="default" text="下线" />;
  109. default:
  110. return <Badge status="default" text="未知" />;
  111. }
  112. };
  113. const columns = [
  114. {
  115. title: '设备ID',
  116. dataIndex: 'device_id',
  117. key: 'device_id',
  118. width: 80,
  119. },
  120. {
  121. title: '设备名称',
  122. dataIndex: 'device_name',
  123. key: 'device_name',
  124. },
  125. {
  126. title: '通信协议',
  127. dataIndex: 'protocol',
  128. key: 'protocol',
  129. render: (text: string) => {
  130. const option = protocolOptions.find(opt => opt.value === text);
  131. return option ? option.label : text;
  132. },
  133. },
  134. {
  135. title: '通信地址',
  136. dataIndex: 'address',
  137. key: 'address',
  138. },
  139. {
  140. title: '监控指标',
  141. dataIndex: 'metric_type',
  142. key: 'metric_type',
  143. render: (text: string) => {
  144. const option = metricTypeOptions.find(opt => opt.value === text);
  145. return option ? option.label : text;
  146. },
  147. },
  148. {
  149. title: '监控值',
  150. dataIndex: 'metric_value',
  151. key: 'metric_value',
  152. render: (value: number, record: DeviceMonitorData) => {
  153. return `${value} ${record.unit || ''}`;
  154. },
  155. },
  156. {
  157. title: '状态',
  158. dataIndex: 'status',
  159. key: 'status',
  160. render: (status: DeviceStatus) => getStatusBadge(status),
  161. },
  162. {
  163. title: '采集时间',
  164. dataIndex: 'collect_time',
  165. key: 'collect_time',
  166. render: (text: Date) => dayjs(text).format('YYYY-MM-DD HH:mm:ss'),
  167. },
  168. ];
  169. return (
  170. <div>
  171. <Card title="Modbus RTU设备监控" style={{ marginBottom: 16 }}>
  172. <Form
  173. form={formRef}
  174. layout="inline"
  175. onFinish={handleSearch}
  176. style={{ marginBottom: 16 }}
  177. >
  178. <Form.Item name="device_id" label="设备">
  179. <Select
  180. placeholder="选择设备"
  181. style={{ width: 200 }}
  182. allowClear
  183. options={deviceOptions}
  184. />
  185. </Form.Item>
  186. <Form.Item name="device_name" label="设备名称">
  187. <Input placeholder="输入设备名称" style={{ width: 200 }} />
  188. </Form.Item>
  189. <Form.Item name="protocol" label="通信协议">
  190. <Select
  191. placeholder="选择通信协议"
  192. style={{ width: 200 }}
  193. allowClear
  194. options={protocolOptions}
  195. />
  196. </Form.Item>
  197. <Form.Item name="address" label="通信地址">
  198. <Input placeholder="输入通信地址" style={{ width: 200 }} />
  199. </Form.Item>
  200. <Form.Item name="metric_type" label="监控指标">
  201. <Select
  202. placeholder="选择监控指标"
  203. style={{ width: 200 }}
  204. allowClear
  205. options={metricTypeOptions}
  206. />
  207. </Form.Item>
  208. <Form.Item name="status" label="状态">
  209. <Select
  210. placeholder="选择状态"
  211. style={{ width: 120 }}
  212. allowClear
  213. options={statusOptions}
  214. />
  215. </Form.Item>
  216. <Form.Item>
  217. <Button type="primary" htmlType="submit">
  218. 查询
  219. </Button>
  220. </Form.Item>
  221. </Form>
  222. <Table
  223. columns={columns}
  224. dataSource={monitorData}
  225. rowKey="id"
  226. pagination={pagination}
  227. loading={loading}
  228. onChange={handleTableChange}
  229. />
  230. </Card>
  231. </div>
  232. );
  233. };