main
wangyunfei 1 month ago
parent 653a9dac0b
commit 44f658e032

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 KiB

@ -1,14 +1,253 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { Card, Result, Select } from 'antd';
import { CheckCircleOutlined } from '@ant-design/icons';
import * as echarts from 'echarts';
import styles from './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';
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 (
<div className={styles.Rcontainer}>
{/* 第一个div - 高度20% */}
@ -114,41 +353,50 @@ const RiskAssessment = () => {
]}
/>
</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}>
<svg width="100%" height="100%" viewBox="0 0 300 150">
{/* 坐标轴 */}
<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>
<img src={map1} alt="地图" className={styles.mapImage} />
</div>
</div>
<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>

@ -158,7 +158,47 @@
}
.block1Select {
width: 120px;
width: 100px;
:global(.ant-select-selector) {
height: 28px !important;
font-size: 12px !important;
}
:global(.ant-select-selection-item) {
line-height: 26px !important;
font-size: 12px !important;
}
}
}
.riskLegend {
position: absolute;
Top: 18px;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
z-index: 10;
.legendItem {
display: flex;
align-items: center;
gap: 5px;
.legendDot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.legendText {
font-size: 12px;
color: #333;
font-weight: 400;
}
}
}
@ -166,21 +206,68 @@
width: 100%;
height: 100%;
margin-top: 20px;
.mapImage {
margin-top: 7%;
width: 90%;
height: 77%;
object-fit: cover;
border-radius: 4px;
display: block;
margin-left: auto;
margin-right: auto;
}
}
}
.middleBlock2 {
flex: 1;
height: 100%;
background-color: pink;
background: linear-gradient(170.5deg, #EBEFF4 6.87%, #FFFFFF 53.01%);
border: 2px solid #fff;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-family: PingFang SC;
font-size: 14px;
color: #333333;
padding: 5px 10px 5px 10px;
.middleBlock2Title {
display: flex;
justify-content: space-between;
align-items: center;
// margin-bottom: 10px;
.titleLeft {
display: flex;
align-items: center;
gap: 8px;
font-weight: 500;
font-size: 14px;
color: #333333;
.titleIcon {
width: 3px;
height: 14px;
background-color: #2E4CD4;
}
}
.titleRight {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: #666;
}
}
.middleBlock2Chart {
width: 100%;
height: 100%;
// min-height: 200px;
}
}
}

Loading…
Cancel
Save