在线监测预警页面开发

main
wangyunfei 1 month ago
parent e99dce364a
commit 0ca0c0d490

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

@ -1,7 +1,9 @@
import React, { useEffect, useRef } from 'react';
import { Card, Result, Select } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import { Card, Result, Select, Button } from 'antd';
import { DownloadOutlined, DeleteOutlined } from '@ant-design/icons';
import * as echarts from 'echarts';
import StandardTable from '@/components/StandardTable';
import styles from './OnlineMonitoring.less';
import alarm0 from '@/assets/safe_majorHazard/online_monitoring/alarm0.png';
@ -10,9 +12,17 @@ import alarm2 from '@/assets/safe_majorHazard/online_monitoring/alarm2.png';
import alarm3 from '@/assets/safe_majorHazard/online_monitoring/alarm3.png';
const OnlineMonitoring = () => {
const chartRef = 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 (chartRef.current) {
@ -48,7 +58,7 @@ const OnlineMonitoring = () => {
yAxis: {
type: 'value',
min: 0,
max:500,
max: 500,
axisLabel: {
formatter: '{value}',
fontSize: 10
@ -124,7 +134,7 @@ const OnlineMonitoring = () => {
]
}
},
symbol: 'none', // 不显示数据点
symbol: 'none',
data: [200, 300, 250, 450, 400, 430, 480, 420, 480, 280, 320, 260, 240]
}
]
@ -145,6 +155,191 @@ const OnlineMonitoring = () => {
}
}, []);
// 表格列定义
const columns = [
{
title: '编号',
dataIndex: 'id',
key: 'id',
width: 80,
},
{
title: '报警时间',
dataIndex: 'alarmTime',
key: 'alarmTime',
width: 150,
},
{
title: '报警传感器名称',
dataIndex: 'sensorName',
key: 'sensorName',
width: 150,
},
{
title: '报警类型',
dataIndex: 'alarmType',
key: 'alarmType',
width: 120,
},
{
title: '报警内容',
dataIndex: 'alarmContent',
key: 'alarmContent',
width: 200,
},
{
title: '优先级',
dataIndex: 'priority',
key: 'priority',
width: 80,
render: (text) => {
const colorMap = {
'高': '#FF4D4F',
'中': '#FAAD14',
'低': '#52C41A'
};
return <span style={{ color: colorMap[text] || '#333' }}>{text}</span>;
}
},
{
title: '处理状态',
dataIndex: 'status',
key: 'status',
width: 100,
render: (text) => {
const statusMap = {
'未处理': { color: '#FF4D4F', bg: '#FFF2F0' },
'处理中': { color: '#FAAD14', bg: '#FFFBE6' },
'已处理': { color: '#52C41A', bg: '#F6FFED' }
};
const status = statusMap[text] || { color: '#333', bg: '#F5F5F5' };
return (
<span style={{
color: status.color,
backgroundColor: status.bg,
padding: '2px 8px',
borderRadius: '4px',
fontSize: '12px'
}}>
{text}
</span>
);
}
},
{
title: '处理时间',
dataIndex: 'processTime',
key: 'processTime',
width: 150,
},
{
title: '处理人',
dataIndex: 'processor',
key: 'processor',
width: 100,
},
{
title: '操作',
key: 'action',
width: 120,
render: (_, record) => (
<div>
<Button type="link" size="small" style={{ padding: 0, marginRight: 8 }}>
查看
</Button>
</div>
),
},
];
// 模拟数据
const mockData = [
{
key: '1',
id: '001',
alarmTime: '2024-01-15 08:30:25',
sensorName: 'LNG储罐',
alarmType: '温度超限',
alarmContent: '储罐温度超过安全阈值',
priority: '高',
status: '未处理',
processTime: '-',
processor: '-',
},
{
key: '2',
id: '002',
alarmTime: '2024-01-15 09:15:10',
sensorName: 'LNG储罐',
alarmType: '压力异常',
alarmContent: '管道压力异常波动',
priority: '中',
status: '处理中',
processTime: '2024-01-15 09:20:00',
processor: '张三',
},
{
key: '3',
id: '003',
alarmTime: '2024-01-15 10:45:30',
sensorName: 'LNG储罐',
alarmType: '液位异常',
alarmContent: '储罐液位低于警戒线',
priority: '高',
status: '已处理',
processTime: '2024-01-15 11:00:15',
processor: '李四',
},
{
key: '4',
id: '004',
alarmTime: '2024-01-15 11:20:45',
sensorName: 'LNG储罐',
alarmType: '气体泄漏',
alarmContent: '检测到可燃气体泄漏',
priority: '高',
status: '未处理',
processTime: '-',
processor: '-',
},
{
key: '5',
id: '005',
alarmTime: '2024-01-15 12:10:20',
sensorName: 'LNG储罐',
alarmType: '设备振动',
alarmContent: '设备异常振动',
priority: '低',
status: '已处理',
processTime: '2024-01-15 12:30:00',
processor: '王五',
},
];
// 初始化数据
useEffect(() => {
setDataSource(mockData);
setPagination(prev => ({ ...prev, total: mockData.length }));
}, []);
// 表格选择变化
const onSelectChange = (newSelectedRowKeys, newSelectedRows) => {
setSelectedRowKeys(newSelectedRowKeys);
setSelectedRows(newSelectedRows);
};
// 导出功能
const handleExport = () => {
console.log('导出数据');
// 这里可以添加导出逻辑
};
// 批量删除功能
const handleBatchDelete = () => {
console.log('批量删除', selectedRowKeys);
// 这里可以添加批量删除逻辑
};
return (
<div className={styles.Ocontainer}>
<div className={styles.OcontainerTop}>
@ -243,9 +438,135 @@ const OnlineMonitoring = () => {
</div>
</div>
</div>
<div className={styles.OcontainerRight}></div>
<div className={styles.OcontainerTopRight}>
<div className={styles.realTimeDataHeader}>
<div className={styles.titleLeft}>
<div className={styles.titleIcon}></div>
<div>实时数据采集</div>
</div>
<div className={styles.totalCount}>
总数 <text style={{ color: '#2e4cd4' }}>1378</text>
</div>
</div>
<div className={styles.dataItem1}>
<div className={styles.dataItemLeft}>
<div className={styles.areaName}>储罐液化装置区</div>
<div className={styles.rValue}>R值: 1765</div>
<div className={styles.codeNumber}>编号:XXXXXXXX</div>
</div>
<div className={styles.dataItemRight}>
<div className={styles.circleContainer}>
<div className={styles.outerCircle}>
<div className={styles.innerCircle}>
<div className={styles.levelText}>三级</div>
<div className={styles.riskText}>危险等级</div>
</div>
</div>
</div>
</div>
</div>
<div className={styles.dataItem2}>
<div className={styles.dataItemLeft}>
<div className={styles.areaName}>储罐液化装置区</div>
<div className={styles.rValue}>R值: 1765</div>
<div className={styles.codeNumber}>编号:XXXXXXXX</div>
</div>
<div className={styles.dataItemRight}>
<div className={styles.circleContainer}>
<div className={styles.outerCircle}>
<div className={styles.innerCircle}>
<div className={styles.levelText}>一级</div>
<div className={styles.riskText}>危险等级</div>
</div>
</div>
</div>
</div>
</div>
<div className={styles.dataItem3}>
<div className={styles.dataItemLeft}>
<div className={styles.areaName}>储罐液化装置区</div>
<div className={styles.rValue}>R值: 1765</div>
<div className={styles.codeNumber}>编号:XXXXXXXX</div>
</div>
<div className={styles.dataItemRight}>
<div className={styles.circleContainer}>
<div className={styles.outerCircle}>
<div className={styles.innerCircle}>
<div className={styles.levelText}>二级</div>
<div className={styles.riskText}>危险等级</div>
</div>
</div>
</div>
</div>
</div>
<div className={styles.dataItem4}>
<div className={styles.dataItemLeft}>
<div className={styles.areaName}>储罐液化装置区</div>
<div className={styles.rValue}>R值: 1765</div>
<div className={styles.codeNumber}>编号:XXXXXXXX</div>
</div>
<div className={styles.dataItemRight}>
<div className={styles.circleContainer}>
<div className={styles.outerCircle}>
<div className={styles.innerCircle}>
<div className={styles.levelText}>三级</div>
<div className={styles.riskText}>危险等级</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{/* 表格 */}
<div className={styles.OcontainerBottom}>
{/* 首行 左侧标题左对齐 右侧按钮右对齐 */}
<div className={styles.tableHeader}>
<div className={styles.tableTitle}>
<div className={styles.titleIcon}></div>
<div>报警信息列表</div>
</div>
<div className={styles.tableActions}>
<Button
type="primary"
icon={<DownloadOutlined />}
onClick={handleExport}
style={{ marginRight: 8 }}
>
导出
</Button>
<Button
danger
icon={<DeleteOutlined />}
onClick={handleBatchDelete}
disabled={selectedRowKeys.length === 0}
>
批量删除
</Button>
</div>
</div>
{/* 表格 5行10列 带页码 每页5条数据 */}
<div className={styles.tableContainer}>
<StandardTable
columns={columns}
dataSource={dataSource}
loading={loading}
selectedRows={selectedRows}
selectedRowKeys={selectedRowKeys}
onSelectRow={onSelectChange}
pagination={{
...pagination,
showSizeChanger: false,
showQuickJumper: true,
showTotal: (total, range) =>
`${range[0]}-${range[1]} 条/共 ${total}`,
}}
scroll={{ x: 1200 }}
/>
</div>
</div>
<div className={styles.OcontainerBottom}></div>
</div>
);
};

@ -6,7 +6,7 @@
.OcontainerTop {
display: flex;
gap: 12px;
height: 50%;
margin-bottom: 5px;
@ -295,20 +295,529 @@
.OcontainerTopLeftBottomChart {
flex: 1;
// padding: 15px;
width: 100%;
// height: 100%;
height: 75%;
}
}
}
.OcontainerTopRight {
flex: 1;
height: calc(100% - 3.3px);
background-color: #fff;
background-image: url('@/assets/safe_majorHazard/online_monitoring/backTopRight.png');
background-size: 100% auto;
display: flex;
flex-direction: column;
overflow-y: auto;
.realTimeDataHeader {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 15px;
margin-bottom: 10px;
.titleLeft {
display: flex;
align-items: center;
gap: 8px;
font-family: PingFang SC;
font-weight: 500;
font-style: Medium;
font-size: 14px;
line-height: 100%;
letter-spacing: 0%;
.titleIcon {
width: 3px;
height: 16px;
background-color: #2E4CD4;
}
}
.totalCount {
font-family: PingFang SC;
font-weight: 400;
font-size: 13px;
color: #333333;
}
}
.dataItem {
height: 23%;
flex-shrink: 0;
border: 1px solid #89E1FF;
border-radius: 2px;
margin: 0 15px;
margin-bottom: 6px;
display: flex;
align-items: center;
justify-content: center;
font-family: PingFang SC;
font-size: 14px;
// color: #666;
background-color: #EFF9FF;
&:last-child {
// margin-bottom: 1px;
}
}
.dataItem1 {
height: 25%;
flex-shrink: 0;
border: 1px solid #89E1FF;
border-radius: 4px;
margin: 0 15px;
margin-bottom: 6px;
display: flex;
align-items: center;
padding: 0px 15px;
background-color: #EFF9FF;
.dataItemLeft {
width: 65%;
display: flex;
flex-direction: column;
gap: 8px;
.areaName {
font-family: PingFang SC;
font-weight: 400;
font-size: 13px;
color: #333333;
line-height: 2.2;
}
.rValue {
font-family: PingFang SC;
font-weight: 400;
font-size: 14px;
color: #666666;
line-height: 0.2;
}
.codeNumber {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #666666;
}
}
.dataItemRight {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.circleContainer {
position: relative;
height: 80%;
aspect-ratio: 1; // 强制宽高比1:1
.outerCircle {
width: 100%;
height: 100%;
background-color: rgba(51, 176, 253, 0.3);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.innerCircle {
width: 70%;
height: 70%;
background-color: rgba(4, 128, 251, 0.8);
border-radius: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.levelText {
font-family: PingFang SC;
font-weight: 500;
font-size: 11px;
color: #FFFFFF;
line-height: 1.4;
margin-top: -4px;
}
.riskText {
font-family: PingFang SC;
font-weight: 300;
font-size: 8px;
color: #FFFFFF;
line-height: 1;
}
}
}
}
}
}
.dataItem2 {
height: 25%;
flex-shrink: 0;
border: 1px solid rgba(255, 197, 188, 1);
border-radius: 4px;
margin: 0 15px;
margin-bottom: 6px;
display: flex;
align-items: center;
padding: 0px 15px;
background-color: #fff5f4;
.dataItemLeft {
width: 65%;
display: flex;
flex-direction: column;
gap: 8px;
.areaName {
font-family: PingFang SC;
font-weight: 400;
font-size: 13px;
color: #333333;
line-height: 2.2;
}
.rValue {
font-family: PingFang SC;
font-weight: 400;
font-size: 14px;
color: #666666;
line-height: 0.2;
}
.codeNumber {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #666666;
}
}
.dataItemRight {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.circleContainer {
position: relative;
height: 80%;
aspect-ratio: 1;
.outerCircle {
width: 100%;
height: 100%;
background-color: rgba(254, 214, 209, 1);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.innerCircle {
width: 70%;
height: 70%;
background-color: rgba(253, 41, 14, 1);
border-radius: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.levelText {
font-family: PingFang SC;
font-weight: 500;
font-size: 11px;
color: #FFFFFF;
line-height: 1.4;
margin-top: -4px;
}
.riskText {
font-family: PingFang SC;
font-weight: 300;
font-size: 8px;
color: #FFFFFF;
line-height: 1;
}
}
}
}
}
}
.dataItem3 {
height: 25%;
flex-shrink: 0;
border: 1px solid rgba(255, 217, 178, 1);
border-radius: 4px;
margin: 0 15px;
margin-bottom: 6px;
display: flex;
align-items: center;
padding: 0px 15px;
background-color: #fef6f1;
.dataItemLeft {
width: 65%;
display: flex;
flex-direction: column;
gap: 8px;
.areaName {
font-family: PingFang SC;
font-weight: 400;
font-size: 13px;
color: #333333;
line-height: 2.2;
}
.rValue {
font-family: PingFang SC;
font-weight: 400;
font-size: 14px;
color: #666666;
line-height: 0.2;
}
.codeNumber {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #666666;
}
}
.dataItemRight {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.circleContainer {
position: relative;
height: 80%;
aspect-ratio: 1;
.outerCircle {
width: 100%;
height: 100%;
background-color: rgba(255, 234, 218, 1);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.innerCircle {
width: 70%;
height: 70%;
background-color: rgba(252, 103, 18, 1);
border-radius: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.levelText {
font-family: PingFang SC;
font-weight: 500;
font-size: 11px;
color: #FFFFFF;
line-height: 1.4;
margin-top: -4px;
}
.riskText {
font-family: PingFang SC;
font-weight: 300;
font-size: 8px;
color: #FFFFFF;
line-height: 1;
}
}
}
}
}
}
.dataItem4 {
height: 25%;
flex-shrink: 0;
border: 1px solid #89E1FF;
border-radius: 4px;
margin: 0 15px;
margin-bottom: 6px;
display: flex;
align-items: center;
padding: 0px 15px;
background-color: #EFF9FF;
.dataItemLeft {
width: 65%;
display: flex;
flex-direction: column;
gap: 8px;
.areaName {
font-family: PingFang SC;
font-weight: 400;
font-size: 13px;
color: #333333;
line-height: 2.2;
}
.rValue {
font-family: PingFang SC;
font-weight: 400;
font-size: 14px;
color: #666666;
line-height: 0.2;
}
.codeNumber {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #666666;
}
}
.dataItemRight {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.circleContainer {
position: relative;
height: 80%;
aspect-ratio: 1;
.outerCircle {
width: 100%;
height: 100%;
background-color: rgba(51, 176, 253, 0.3);
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
.innerCircle {
width: 70%;
height: 70%;
background-color: rgba(4, 128, 251, 0.8);
border-radius: 50%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.levelText {
font-family: PingFang SC;
font-weight: 500;
font-size: 11px;
color: #FFFFFF;
line-height: 1.4;
margin-top: -4px;
}
.riskText {
font-family: PingFang SC;
font-weight: 300;
font-size: 8px;
color: #FFFFFF;
line-height: 1;
}
}
}
}
}
}
}
}
.OcontainerBottom {
background-color: #666;
background-color: #fff;
flex: 1;
padding: 8px 15px 5px 15px;
display: flex;
flex-direction: column;
.tableHeader {
display: flex;
justify-content: space-between;
align-items: center;
// margin-bottom: 15px;
padding-bottom: 5px;
// border-bottom: 1px solid #f0f0f0;
.tableTitle {
display: flex;
align-items: center;
gap: 8px;
font-family: PingFang SC;
font-weight: 500;
font-size: 16px;
color: #333333;
.titleIcon {
width: 3px;
height: 16px;
background-color: #2E4CD4;
}
}
.tableActions {
display: flex;
gap: 8px;
}
}
.tableContainer {
flex: 1;
overflow: hidden;
:global(.ant-table) {
font-size: 12px;
}
:global(.ant-table-thead > tr > th) {
background-color: #fafafa;
font-weight: 500;
color: #333;
border-bottom: 1px solid #f0f0f0;
padding: 8px 12px;
text-align: center;
}
:global(.ant-table-tbody > tr > td) {
padding: 8px 12px;
border-bottom: 1px solid #f0f0f0;
text-align: center;
}
:global(.ant-table-tbody > tr:hover > td) {
background-color: #f5f5f5;
}
:global(.ant-pagination) {
margin-top: 16px;
text-align: right;
}
}
}
}
Loading…
Cancel
Save