import React, { useEffect, useRef, useState } from 'react'; import { Card, Result, Select, Button, Segmented } from 'antd'; import { CheckCircleOutlined, ExportOutlined } from '@ant-design/icons'; import * as echarts from 'echarts'; import StandardTable from '@/components/StandardTable'; import styles from './RiskAssessment.less'; // import './RiskAssessment.less'; import img1 from '@/assets/safe_majorHazard/online_monitoring/img1.png'; import img2 from '@/assets/safe_majorHazard/online_monitoring/img2.png'; import img3 from '@/assets/safe_majorHazard/online_monitoring/img3.png'; import map1 from '@/assets/safe_majorHazard/online_monitoring/map.png'; import risk1 from '@/assets/safe_majorHazard/online_monitoring/risk1.png'; import risk2 from '@/assets/safe_majorHazard/online_monitoring/risk2.png'; import risk3 from '@/assets/safe_majorHazard/online_monitoring/risk3.png'; import eqicon1 from '@/assets/business_basic/eqicon1.png'; import eqicon2 from '@/assets/business_basic/eqicon2.png'; import eqicon3 from '@/assets/business_basic/eqicon3.png'; import eqicon4 from '@/assets/business_basic/eqicon4.png'; const RiskAssessment = () => { const chartRef = useRef(null); const pieChartRef = useRef(null); const faultPieChartRef = useRef(null); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [selectedRows, setSelectedRows] = useState([]); const [loading, setLoading] = useState(false); const [dataSource, setDataSource] = useState([]); const [pagination, setPagination] = useState({ current: 1, pageSize: 5, total: 0, }); // 饼图初始化 useEffect(() => { if (pieChartRef.current) { const pieChart = echarts.init(pieChartRef.current); const pieOption = { color: ['#44BB5F', '#F8C541', '#A493FB', '#4B69F1', '#949FD0'], legend: { orient: 'vertical', right: '10%', top: 'center', itemWidth: 8, itemHeight: 8, textStyle: { fontSize: 12, color: '#333' } }, series: [{ name: '设备状态', type: 'pie', radius: ['40%', '70%'], center: ['35%', '50%'], avoidLabelOverlap: false, label: { show: false, position: 'center' }, emphasis: { label: { show: true, fontSize: '14', fontWeight: 'bold' } }, labelLine: { show: false }, data: [ { value: 480, name: '正常' }, { value: 289, name: '故障' }, { value: 200, name: '维修中' }, { value: 150, name: '待验收' }, { value: 161, name: '停用' } ] }] }; pieChart.setOption(pieOption); // 响应式调整 const handlePieResize = () => { if (pieChart && !pieChart.isDisposed()) { pieChart.resize(); } }; window.addEventListener('resize', handlePieResize); return () => { window.removeEventListener('resize', handlePieResize); if (pieChart && !pieChart.isDisposed()) { pieChart.dispose(); } }; } }, []); // 故障类型饼图初始化 useEffect(() => { if (faultPieChartRef.current) { const faultPieChart = echarts.init(faultPieChartRef.current); const faultPieOption = { color: ['#FF3E48', '#FF8800', '#FFC403'], legend: { orient: 'vertical', right: '10%', top: 'center', itemWidth: 8, itemHeight: 8, textStyle: { fontSize: 12, color: '#333' } }, series: [{ name: '设备故障类型', type: 'pie', radius: '70%', center: ['35%', '50%'], avoidLabelOverlap: false, label: { show: true, position: 'outside', formatter: '{b}: {c}', fontSize: 12 }, emphasis: { label: { show: true, fontSize: '14', fontWeight: 'bold' } }, labelLine: { show: true }, data: [ { value: 120, name: '紧急' }, { value: 80, name: '重要' }, { value: 60, name: '一般' } ] }] }; faultPieChart.setOption(faultPieOption); // 响应式调整 const handleFaultPieResize = () => { if (faultPieChart && !faultPieChart.isDisposed()) { faultPieChart.resize(); } }; window.addEventListener('resize', handleFaultPieResize); return () => { window.removeEventListener('resize', handleFaultPieResize); if (faultPieChart && !faultPieChart.isDisposed()) { faultPieChart.dispose(); } }; } }, []); useEffect(() => { if (chartRef.current) { const chart = echarts.init(chartRef.current); // 强制初始化时调整大小 setTimeout(() => { if (chart && !chart.isDisposed()) { chart.resize(); } }, 100); const option = { color: ['#8979FF', '#3CC3DF'], legend: { // data: ['消防水泵1', '消防水泵2'], top: "-3px", // left: "center", // itemGap: 40, itemWidth: 20, itemHeight: 8, // icon: 'path://M902 472.7H747.9c-19.1-113.3-117.7-200-236.4-200s-217.3 86.7-236.4 200H119.7c-4.4 0-8 3.6-8 8v64c0 4.4 3.6 8 8 8h155.5c19.1 113.3 117.7 200 236.4 200S728.9 666 748 552.7h154c4.4 0 8-3.6 8-8v-64c0-4.4-3.6-8-8-8z m-390.5 200c-88.2 0-160-71.8-160-160s71.8-160 160-160 160 71.8 160 160-71.8 160-160 160z', textStyle: { fontSize: 10 } }, grid: { left: '2%', right: '4%', bottom: '2%', top: '12%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, data: ['9:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00'], axisLabel: { fontSize: 10 } }, yAxis: { type: 'value', min: 0, max: 30, axisLabel: { formatter: '{value}', fontSize: 10 } }, series: [ { name: '消防水泵1', type: 'line', smooth: false, lineStyle: { width: 2, color: '#8979FF' }, areaStyle: { color: { type: 'linear', x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: 'rgba(137, 121, 255, 0.3)' }, { offset: 1, color: 'rgba(137, 121, 255, 0.05)' } ] } }, symbol: 'circle', symbolSize: 4, itemStyle: { color: '#fff', borderColor: '#8979FF', borderWidth: 1 }, data: [12, 15, 18, 14, 16, 20, 22, 19, 17, 21, 23, 25] }, { name: '消防水泵2', type: 'line', smooth: false, lineStyle: { width: 2, color: '#3CC3DF' }, areaStyle: { color: { type: 'linear', x: 0, y: 0, x2: 0, y2: 1, colorStops: [ { offset: 0, color: 'rgba(60, 195, 223, 0.3)' }, { offset: 1, color: 'rgba(60, 195, 223, 0.05)' } ] } }, symbol: 'circle', symbolSize: 4, itemStyle: { color: '#fff', borderColor: '#3CC3DF', borderWidth: 1 }, data: [8, 11, 14, 10, 13, 17, 19, 16, 14, 18, 20, 22] } ] }; chart.setOption(option); // 响应式调整 - 使用多种方式监听容器尺寸变化 let resizeTimer = null; const handleResize = () => { // 防抖处理,避免频繁调用resize if (resizeTimer) { clearTimeout(resizeTimer); } resizeTimer = setTimeout(() => { if (chart && !chart.isDisposed()) { chart.resize(); } }, 50); // 减少延迟时间 }; // 监听窗口大小变化 window.addEventListener('resize', handleResize); // 监听容器尺寸变化(解决菜单栏伸缩时的自适应问题) let resizeObserver = null; if (window.ResizeObserver) { resizeObserver = new ResizeObserver((entries) => { for (let entry of entries) { // 使用requestAnimationFrame确保在下一帧执行 requestAnimationFrame(() => { handleResize(); }); } }); resizeObserver.observe(chartRef.current); } // 额外监听父容器的尺寸变化 const parentContainer = chartRef.current?.parentElement; let parentObserver = null; if (parentContainer && window.ResizeObserver) { parentObserver = new ResizeObserver((entries) => { for (let entry of entries) { requestAnimationFrame(() => { handleResize(); }); } }); parentObserver.observe(parentContainer); } // 使用MutationObserver监听DOM结构变化(菜单展开收起时) const mutationObserver = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && (mutation.attributeName === 'class' || mutation.attributeName === 'style')) { // 延迟执行,确保DOM更新完成 setTimeout(() => { handleResize(); }, 200); } }); }); // 监听整个页面的class和style变化 mutationObserver.observe(document.body, { attributes: true, attributeFilter: ['class', 'style'], subtree: true }); return () => { window.removeEventListener('resize', handleResize); if (resizeObserver) { resizeObserver.disconnect(); } if (parentObserver) { parentObserver.disconnect(); } if (mutationObserver) { mutationObserver.disconnect(); } if (resizeTimer) { clearTimeout(resizeTimer); } if (chart && !chart.isDisposed()) { chart.dispose(); } }; } }, []); // 表格列定义 const columns = [ { title: '编号', dataIndex: 'id', key: 'id', width: 60, render: (text, record, index) => { const page = pagination.current || 1; const pageSize = pagination.pageSize || 5; const number = (page - 1) * pageSize + index + 1; return `0${number}`.slice(-2); } }, { title: '设备编号', dataIndex: 'deviceId', key: 'deviceId', width: 140, }, { title: '设备名称', dataIndex: 'deviceName', key: 'deviceName', width: 110, }, { title: '型号规格', dataIndex: 'modelSpec', key: 'modelSpec', width: 140, }, { title: '安装位置', dataIndex: 'installLocation', key: 'installLocation', width: 200, }, { title: '状态', dataIndex: 'status', key: 'status', width: 80, render: (text) => { const statusMap = { '故障': { color: '#FF4D4F', bg: '#FFF2F0' }, '预警': { color: '#FAAD14', bg: '#FFF3E9' }, '正常': { color: '#44BB5F', bg: '#D8F7DE' } }; const status = statusMap[text] || { color: '#333', bg: '#F5F5F5' }; return ( {text} ); } }, { title: '最后维护', dataIndex: 'lastMaintenance', key: 'lastMaintenance', width: 150, }, { title: '操作', key: 'action', width: 140, render: (_, record) => (
), }, ]; // 模拟数据 const mockData = [ { key: '1', id: '001', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼1层大厅', status: '故障', lastMaintenance: '2025-09-10', }, { key: '2', id: '002', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼3层 东区', status: '预警', lastMaintenance: '2025-09-10', }, { key: '3', id: '003', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '正常', lastMaintenance: '2025-09-10', }, { key: '4', id: '004', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '故障', lastMaintenance: '2025-09-10', }, { key: '5', id: '005', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '正常', lastMaintenance: '2025-09-10', }, { key: '6', id: '006', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '预警', lastMaintenance: '2025-09-10', }, { key: '7', id: '007', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '故障', lastMaintenance: '2025-09-10', }, { key: '8', id: '008', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '正常', lastMaintenance: '2025-09-10', }, { key: '9', id: '009', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '预警', lastMaintenance: '2025-09-10', }, { key: '10', id: '010', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '故障', lastMaintenance: '2025-09-10', }, { key: '11', id: '011', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '正常', lastMaintenance: '2025-09-10', }, { key: '12', id: '012', deviceId: 'HQ-XF-01-001', deviceName: '消防水泵', modelSpec: 'XBD5.0/30-125', installLocation: '总部大楼地下一层', status: '预警', lastMaintenance: '2025-09-10', }, ]; // 初始化数据 useEffect(() => { setPagination(prev => ({ ...prev, total: mockData.length })); }, []); // 根据分页获取当前页数据 const getCurrentPageData = () => { const { current, pageSize } = pagination; const startIndex = (current - 1) * pageSize; const endIndex = startIndex + pageSize; return mockData.slice(startIndex, endIndex); }; // 表格选择变化 const onSelectChange = (newSelectedRowKeys, newSelectedRows) => { setSelectedRowKeys(newSelectedRowKeys); setSelectedRows(newSelectedRows); }; // 新增设备按钮点击事件 const handleAddDevice = () => { console.log('新增设备'); // TODO: 实现新增设备逻辑 }; // 导出数据按钮点击事件 const handleExportData = () => { console.log('导出数据'); // TODO: 实现导出数据逻辑 }; // 分页变化处理 const handleTableChange = (pagination) => { setPagination(prev => ({ ...prev, current: pagination.current, pageSize: pagination.pageSize, })); }; return (
{/* 第一个div - 高度20% */}
{/* 块1 */}
设备总数
1280
设备总数
{/* 块2 */}
正常运行
480
高风险设备
{/* 块3 */}
需要维护
347
今日预警次数
{/* 块4 */}
故障设备
289
未处理预警
设备状态分布
{ console.log(value); }} />
{/* 设备状态饼图 */}
设备故障类型分布
{/* 第三个div - 占满剩余位置 */}
{/* 第一行块 - 蓝色方块加标题 */}
预警信息
灭火器压力不足
2号楼3层 丨 15分钟前
重要
烟雾探测器电池低电量
1号楼5层 丨 1小时前
重要
消防栓维护到期
3号楼1层 丨 2小时前
一般
应急照明故障
地下停车场 丨 3小时前
一般
{/* 表格 */}
消防设备台账
{/* 表格 */}
`共 ${total} 条`, }} // scroll={{ x: 1200 }} />
); }; export default RiskAssessment;