|
|
|
@ -1,14 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
import React from 'react';
|
|
|
|
import React, { useEffect, useRef } from 'react';
|
|
|
|
import { Card, Result, Select } from 'antd';
|
|
|
|
import { Card, Result, Select } from 'antd';
|
|
|
|
import { CheckCircleOutlined } from '@ant-design/icons';
|
|
|
|
import { CheckCircleOutlined } from '@ant-design/icons';
|
|
|
|
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
import styles from './RiskAssessment.less';
|
|
|
|
import styles from './RiskAssessment.less';
|
|
|
|
|
|
|
|
|
|
|
|
import img1 from '@/assets/safe_majorHazard/online_monitoring/img1.png';
|
|
|
|
import img1 from '@/assets/safe_majorHazard/online_monitoring/img1.png';
|
|
|
|
import img2 from '@/assets/safe_majorHazard/online_monitoring/img2.png';
|
|
|
|
import img2 from '@/assets/safe_majorHazard/online_monitoring/img2.png';
|
|
|
|
import img3 from '@/assets/safe_majorHazard/online_monitoring/img3.png';
|
|
|
|
import img3 from '@/assets/safe_majorHazard/online_monitoring/img3.png';
|
|
|
|
|
|
|
|
import map1 from '@/assets/safe_majorHazard/online_monitoring/map.png';
|
|
|
|
|
|
|
|
|
|
|
|
const RiskAssessment = () => {
|
|
|
|
const RiskAssessment = () => {
|
|
|
|
|
|
|
|
const chartRef = useRef(null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
if (chartRef.current) {
|
|
|
|
|
|
|
|
const chart = echarts.init(chartRef.current);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 强制初始化时调整大小
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
|
|
if (chart && !chart.isDisposed()) {
|
|
|
|
|
|
|
|
chart.resize();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const option = {
|
|
|
|
|
|
|
|
color: ['#FF2526', '#FF8800', '#FFC403', '#65E5F9'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
|
|
data: ['重大风险', '较高风险', '一般风险', '低风险'],
|
|
|
|
|
|
|
|
top: "-3px",
|
|
|
|
|
|
|
|
left: "center",
|
|
|
|
|
|
|
|
itemGap: 40, // 图例间距
|
|
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
|
|
fontSize: 10
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
grid: {
|
|
|
|
|
|
|
|
left: '2%',
|
|
|
|
|
|
|
|
right: '4%',
|
|
|
|
|
|
|
|
bottom: '2%',
|
|
|
|
|
|
|
|
top: '12%',
|
|
|
|
|
|
|
|
containLabel: true
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
type: 'category',
|
|
|
|
|
|
|
|
boundaryGap: false,
|
|
|
|
|
|
|
|
data: ['9/22', '9/23', '9/24', '9/25', '9/26', '9/27', '9/28'],
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
fontSize: 10
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
yAxis: {
|
|
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
|
|
max: 30,
|
|
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
|
|
formatter: '{value}',
|
|
|
|
|
|
|
|
fontSize: 10
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
series: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '重大风险',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
width: 1.5,
|
|
|
|
|
|
|
|
color: '#FF2526'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
areaStyle: {
|
|
|
|
|
|
|
|
color: {
|
|
|
|
|
|
|
|
type: 'linear',
|
|
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
|
|
x2: 0,
|
|
|
|
|
|
|
|
y2: 1,
|
|
|
|
|
|
|
|
colorStops: [
|
|
|
|
|
|
|
|
{ offset: 0, color: 'rgba(38, 12, 12, 0.4)' },
|
|
|
|
|
|
|
|
{ offset: 1, color: 'rgba(255, 37, 38, 0)' }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
symbol: 'none',
|
|
|
|
|
|
|
|
data: [8, 15, 12, 22, 18, 26, 20]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '较高风险',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
width: 1.5,
|
|
|
|
|
|
|
|
color: '#FF8800'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
areaStyle: {
|
|
|
|
|
|
|
|
color: {
|
|
|
|
|
|
|
|
type: 'linear',
|
|
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
|
|
x2: 0,
|
|
|
|
|
|
|
|
y2: 1,
|
|
|
|
|
|
|
|
colorStops: [
|
|
|
|
|
|
|
|
{ offset: 0, color: 'rgba(255, 136, 0, 0.4)' },
|
|
|
|
|
|
|
|
{ offset: 1, color: 'rgba(255, 136, 0, 0)' }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
symbol: 'none',
|
|
|
|
|
|
|
|
data: [5, 8, 6, 12, 10, 15, 13]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '一般风险',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
width: 1.5,
|
|
|
|
|
|
|
|
color: '#FFC403'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
areaStyle: {
|
|
|
|
|
|
|
|
color: {
|
|
|
|
|
|
|
|
type: 'linear',
|
|
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
|
|
x2: 0,
|
|
|
|
|
|
|
|
y2: 1,
|
|
|
|
|
|
|
|
colorStops: [
|
|
|
|
|
|
|
|
{ offset: 0, color: 'rgba(255, 196, 3, 0.4)' },
|
|
|
|
|
|
|
|
{ offset: 1, color: 'rgba(255, 196, 3, 0)' }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
symbol: 'none',
|
|
|
|
|
|
|
|
data: [12, 18, 15, 25, 22, 24, 26]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
name: '低风险',
|
|
|
|
|
|
|
|
type: 'line',
|
|
|
|
|
|
|
|
smooth: true,
|
|
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
|
|
width: 1.5,
|
|
|
|
|
|
|
|
color: '#65E5F9'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
areaStyle: {
|
|
|
|
|
|
|
|
color: {
|
|
|
|
|
|
|
|
type: 'linear',
|
|
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
|
|
x2: 0,
|
|
|
|
|
|
|
|
y2: 1,
|
|
|
|
|
|
|
|
colorStops: [
|
|
|
|
|
|
|
|
{ offset: 0, color: 'rgba(101, 229, 249, 0.4)' },
|
|
|
|
|
|
|
|
{ offset: 1, color: 'rgba(101, 229, 249, 0)' }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
symbol: 'none',
|
|
|
|
|
|
|
|
data: [3, 5, 7, 9, 6, 8, 4]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<div className={styles.Rcontainer}>
|
|
|
|
<div className={styles.Rcontainer}>
|
|
|
|
{/* 第一个div - 高度20% */}
|
|
|
|
{/* 第一个div - 高度20% */}
|
|
|
|
@ -114,41 +353,50 @@ const RiskAssessment = () => {
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
{/* 风险等级图例 */}
|
|
|
|
{/* 第二行 - 简易曲线图 */}
|
|
|
|
<div className={styles.riskLegend}>
|
|
|
|
|
|
|
|
<div className={styles.legendItem}>
|
|
|
|
|
|
|
|
<div className={styles.legendDot} style={{ backgroundColor: '#F53F3F' }}></div>
|
|
|
|
|
|
|
|
<span className={styles.legendText}>重大风险</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.legendItem}>
|
|
|
|
|
|
|
|
<div className={styles.legendDot} style={{ backgroundColor: '#FF7D00' }}></div>
|
|
|
|
|
|
|
|
<span className={styles.legendText}>较大风险</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.legendItem}>
|
|
|
|
|
|
|
|
<div className={styles.legendDot} style={{ backgroundColor: '#FFAA01' }}></div>
|
|
|
|
|
|
|
|
<span className={styles.legendText}>一般风险</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.legendItem}>
|
|
|
|
|
|
|
|
<div className={styles.legendDot} style={{ backgroundColor: '#65E5F9' }}></div>
|
|
|
|
|
|
|
|
<span className={styles.legendText}>低风险</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<div className={styles.block1Chart}>
|
|
|
|
<div className={styles.block1Chart}>
|
|
|
|
<svg width="100%" height="100%" viewBox="0 0 300 150">
|
|
|
|
|
|
|
|
{/* 坐标轴 */}
|
|
|
|
<img src={map1} alt="地图" className={styles.mapImage} />
|
|
|
|
<line x1="20" y1="130" x2="280" y2="130" stroke="#ddd" strokeWidth="1"/>
|
|
|
|
|
|
|
|
<line x1="20" y1="20" x2="20" y2="130" stroke="#ddd" strokeWidth="1"/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 曲线 */}
|
|
|
|
|
|
|
|
<path
|
|
|
|
|
|
|
|
d="M 30 100 Q 80 60 130 80 T 230 50 T 280 70"
|
|
|
|
|
|
|
|
stroke="#1269FF"
|
|
|
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 数据点 */}
|
|
|
|
|
|
|
|
<circle cx="30" cy="100" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
<circle cx="80" cy="60" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
<circle cx="130" cy="80" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
<circle cx="180" cy="50" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
<circle cx="230" cy="50" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
<circle cx="280" cy="70" r="3" fill="#1269FF"/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{/* 网格线 */}
|
|
|
|
|
|
|
|
<line x1="50" y1="20" x2="50" y2="130" stroke="#f0f0f0" strokeWidth="1"/>
|
|
|
|
|
|
|
|
<line x1="100" y1="20" x2="100" y2="130" stroke="#f0f0f0" strokeWidth="1"/>
|
|
|
|
|
|
|
|
<line x1="150" y1="20" x2="150" y2="130" stroke="#f0f0f0" strokeWidth="1"/>
|
|
|
|
|
|
|
|
<line x1="200" y1="20" x2="200" y2="130" stroke="#f0f0f0" strokeWidth="1"/>
|
|
|
|
|
|
|
|
<line x1="250" y1="20" x2="250" y2="130" stroke="#f0f0f0" strokeWidth="1"/>
|
|
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className={styles.middleBlock2}>
|
|
|
|
<div className={styles.middleBlock2}>
|
|
|
|
<p>第二个小块内容</p>
|
|
|
|
<div className={styles.middleBlock2Title}>
|
|
|
|
|
|
|
|
<div className={styles.titleLeft}>
|
|
|
|
|
|
|
|
<div className={styles.titleIcon}></div>
|
|
|
|
|
|
|
|
<div>风险等级趋势</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.titleRight}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<Select
|
|
|
|
|
|
|
|
style={{ width: 100 }}
|
|
|
|
|
|
|
|
defaultValue="近七天"
|
|
|
|
|
|
|
|
options={[
|
|
|
|
|
|
|
|
{ value: '近三天', label: '近3天' },
|
|
|
|
|
|
|
|
{ value: '近30天', label: '近30天' },
|
|
|
|
|
|
|
|
]}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className={styles.middleBlock2Chart} ref={chartRef}>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|