From 96533b63f190e1fab4215621ae11924e8ce4aa3e Mon Sep 17 00:00:00 2001 From: wangyunfei888 <1224056307@qq.com> Date: Fri, 26 Dec 2025 17:09:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E6=97=B6=E6=95=B0=E6=8D=AE=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HistoryTrend.js | 320 ++++++++++-------- .../HistoryTrend.less | 71 ++-- .../RealtimeData.js | 7 +- .../RealtimeData.less | 3 +- 4 files changed, 239 insertions(+), 162 deletions(-) diff --git a/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.js b/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.js index 10ed672..acaac97 100644 --- a/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.js +++ b/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.js @@ -1,9 +1,9 @@ import React, { useMemo, useState } from 'react'; -import { Select, Tree, Button } from 'antd'; -import { PlusOutlined } from '@ant-design/icons'; +import { Select, Tree } from 'antd'; +import ReactECharts from 'echarts-for-react'; +import * as echarts from 'echarts'; import { ReactComponent as Icon1 } from '@/assets/business_basic/icon1.svg'; import { ReactComponent as Icon2 } from '@/assets/business_basic/icon2.svg'; -import StandardTable from '@/components/StandardTable'; import styles from './HistoryTrend.less'; const buildingOptions = [ @@ -17,6 +17,12 @@ const factoryOptions = [ { label: '南京油库', value: 'nanjing' }, ]; +const rangeOptions = [ + { label: '近24小时', value: '24h' }, + { label: '近7天', value: '7d' }, + { label: '近30天', value: '30d' }, +]; + const rawTreeData = [ { title: '上海油库', @@ -116,133 +122,152 @@ const formatTreeNodes = data => children: item.children ? formatTreeNodes(item.children) : undefined, })); -const tableColumns = [ - { - title: '层级', - dataIndex: 'level', - key: 'level', - width: 110, - align: 'center', - }, - { - title: '名称', - dataIndex: 'name', - key: 'name', - width: 120, - align: 'center', - }, - { - title: '代码', - dataIndex: 'code', - key: 'code', - align: 'center', - }, - { - title: '类型', - dataIndex: 'type', - key: 'type', - align: 'center', - }, - { - title: '状态', - dataIndex: 'status', - key: 'status', - align: 'center', - }, - { - title: '最后更新', - dataIndex: 'updatedAt', - key: 'updatedAt', - align: 'center', - }, - { - title: '操作', - dataIndex: 'operation', - key: 'operation', - width: 140, - align: 'center', - render: () => ( - <> - 查看详情 - 编辑 - - ), - }, -]; +const timeAxis = ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00']; -const tableDataSource = [ - { - id: 1, - level: '工厂', - name: '华东油库', - code: 'CN-EAST-OIL', - type: '原油存储', - status: '已激活', - updatedAt: '2025-10-25 22:30:16', - }, - { - id: 2, - level: '罐区', - name: '汽油罐区', - code: 'GASOLINE-AREA', - type: '成品油', - status: '已激活', - updatedAt: '2025-10-25 10:28:14', - }, - { - id: 3, - level: '罐区', - name: '柴油罐区', - code: 'DIESEL-AREA', - type: '成品油', - status: '已激活', - updatedAt: '2025-10-23 20:58:24', - }, - { - id: 4, - level: '罐组', - name: '92汽油调合罐组', - code: 'G92-GROUP', - type: '调合罐组', - status: '维护中', - updatedAt: '2025-10-23 04:59:13', - }, - { - id: 5, - level: '储罐', - name: 'T-101', - code: 'TANK-101', - type: '浮顶罐', - status: '维护中', - updatedAt: '2025-10-22 03:03:13', - }, - { - id: 6, - level: '设备', - name: 'LT-101', - code: 'LEVEL-101', - type: '液位计', - status: '已激活', - updatedAt: '2025-10-22 03:03:13', - }, -]; +const liquidLevelSeries = [79, 18, 76, 45, 36, 69, 43, 74, 48, 53, 55, 21]; +const temperatureSeries = [32.2, 31.1, 32.0, 30.6, 30.9, 32.1, 30.7, 32.8, 30.8, 31.7, 31.1, 30.6]; +const pressureSeries = [0.116, 0.114, 0.113, 0.112, 0.114, 0.113, 0.116, 0.115, 0.111, 0.114, 0.115, 0.114]; const HistoryTrend = () => { const [buildingType, setBuildingType] = useState('plant'); const [factory, setFactory] = useState('all'); const [selectedKeys, setSelectedKeys] = useState(['t101']); const [checkedKeys, setCheckedKeys] = useState(['t101']); + const [levelRange, setLevelRange] = useState('24h'); + const [tempRange, setTempRange] = useState('24h'); const treeData = useMemo(() => formatTreeNodes(rawTreeData), []); - const tableData = useMemo( + const levelTrendOption = useMemo(() => { + const areaGradient = new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: 'rgba(45, 158, 157, 0.35)' }, + { offset: 1, color: 'rgba(45, 158, 157, 0.02)' }, + ]); + + return { + color: ['#2d9e9d'], + tooltip: { + trigger: 'axis', + backgroundColor: '#0f3030', + borderColor: 'rgba(45, 158, 157, 0.4)', + textStyle: { color: '#dff4f2' }, + axisPointer: { + lineStyle: { + color: '#2d9e9d', + }, + }, + }, + legend: { + data: ['液位 (%)'], + right: 20, + top: 10, + icon: 'circle', + textStyle: { color: '#4e5856' }, + }, + grid: { left: 40, right: 20, top: 50, bottom: 30 }, + xAxis: { + type: 'category', + data: timeAxis, + boundaryGap: false, + axisTick: { show: false }, + axisLine: { lineStyle: { color: '#d6e5df' } }, + axisLabel: { color: '#76807d' }, + }, + yAxis: { + type: 'value', + min: 0, + max: 100, + axisLabel: { formatter: '{value}%', color: '#76807d' }, + splitLine: { lineStyle: { color: '#e6f1ec' } }, + }, + series: [ + { + name: '液位 (%)', + type: 'line', + smooth: true, + symbol: 'circle', + symbolSize: 8, + lineStyle: { width: 3 }, + itemStyle: { color: '#2d9e9d' }, + areaStyle: { color: areaGradient }, + data: liquidLevelSeries, + }, + ], + }; + }, []); + + const temperaturePressureOption = useMemo( () => ({ - list: tableDataSource, - pagination: { - currentPage: 1, - pageSize: 10, - total: tableDataSource.length, + color: ['#2a7b8d', '#c2b453'], + tooltip: { + trigger: 'axis', + backgroundColor: '#0f3030', + borderColor: 'rgba(42, 123, 141, 0.4)', + textStyle: { color: '#dff4f2' }, + axisPointer: { type: 'cross', link: [{ xAxisIndex: 'all' }] }, + }, + legend: { + data: ['温度 (℃)', '压力 (MPa)'], + right: 20, + top: 10, + icon: 'circle', + textStyle: { color: '#4e5856' }, }, + grid: { left: 50, right: 50, top: 50, bottom: 30 }, + xAxis: [ + { + type: 'category', + data: timeAxis, + boundaryGap: false, + axisTick: { show: false }, + axisLine: { lineStyle: { color: '#d6e5df' } }, + axisLabel: { color: '#76807d' }, + }, + ], + yAxis: [ + { + type: 'value', + name: '温度 (℃)', + min: 28, + max: 33, + axisLabel: { formatter: '{value}', color: '#76807d' }, + nameTextStyle: { color: '#76807d' }, + splitLine: { lineStyle: { color: '#e6f1ec' } }, + }, + { + type: 'value', + name: '压力 (MPa)', + min: 0.11, + max: 0.12, + position: 'right', + axisLabel: { formatter: '{value}', color: '#76807d' }, + nameTextStyle: { color: '#76807d' }, + splitLine: { show: false }, + }, + ], + series: [ + { + name: '温度 (℃)', + type: 'line', + smooth: true, + symbol: 'circle', + symbolSize: 7, + lineStyle: { width: 3, color: '#2a7b8d' }, + itemStyle: { color: '#2a7b8d' }, + data: temperatureSeries, + }, + { + name: '压力 (MPa)', + type: 'line', + smooth: true, + symbol: 'diamond', + symbolSize: 7, + lineStyle: { width: 3, color: '#c2b453' }, + itemStyle: { color: '#c2b453' }, + yAxisIndex: 1, + data: pressureSeries, + }, + ], }), [], ); @@ -298,28 +323,49 @@ const HistoryTrend = () => {
-
- - 层级结构 -
-
diff --git a/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.less b/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.less index 123b70e..3964c1f 100644 --- a/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.less +++ b/src/pages/business_basic/components/second_datamodel_components/HistoryTrend.less @@ -23,6 +23,7 @@ box-shadow: 0 4px 20px rgba(21, 32, 66, 0.04); display: flex; flex-direction: column; + gap: 16px; } .blockHeader { @@ -44,15 +45,6 @@ font-weight: 500; color: #333333; } - - .headerAction { - margin-left: auto; - - :global(&.ant-btn-sm) { - height: 28px !important; - line-height: 28px; - } - } } .filters { @@ -149,23 +141,56 @@ } } - .tableWrapper { - flex: 1; + .trendCard { + background: #fff; + border-radius: 10px; + border: 1px solid #e0eeea; + padding: 12px 12px 16px; + box-shadow: 0 6px 16px rgba(12, 49, 41, 0.06); + display: flex; + flex-direction: column; + gap: 12px; + } - :global { - .ant-table-thead>tr>th { - text-align: center; - background: #f0f7f7; - font-weight: 450; - color: #333333; - } + .trendHeader { + display: flex; + align-items: center; + justify-content: space-between; + } - .ant-table-tbody>tr>td { - text-align: center; - font-weight: 400; - color: #4e5856; - } + .headerTitle { + display: flex; + align-items: center; + gap: 8px; + } + + .rangeSelect { + width: 120px; + + :global(.ant-select-selector) { + border: 1px solid rgba(45, 158, 157, 1); + border-radius: 4px; + height: 28px; } + + :global(.ant-select-focused .ant-select-selector) { + border-color: rgba(45, 158, 157, 1) !important; + box-shadow: 0 0 0 2px rgba(45, 158, 157, 0.2) !important; + } + + :global(.ant-select:hover .ant-select-selector) { + border-color: rgba(45, 158, 157, 1) !important; + } + } + + .chartWrapper { + width: 100%; + height: 280px; + background: linear-gradient(180deg, #f8fbfa 0%, #ffffff 100%); + border-radius: 8px; + border: 1px solid #e6f1ec; + padding: 6px; + box-sizing: border-box; } } diff --git a/src/pages/business_basic/components/second_datamodel_components/RealtimeData.js b/src/pages/business_basic/components/second_datamodel_components/RealtimeData.js index f841614..b7143a6 100644 --- a/src/pages/business_basic/components/second_datamodel_components/RealtimeData.js +++ b/src/pages/business_basic/components/second_datamodel_components/RealtimeData.js @@ -301,8 +301,13 @@ const RealtimeData = () => {
-
实时监测点数据
+
+ + 实时数据 +
+ {/* 从这里开始下面的内容 */} + {/* 从这里开始下面的内容 */}