feat(状态管理): 新增设备状态管理页面及功能

- 添加状态管理页面路由配置和导航菜单项
- 实现状态管理页面基础布局和功能组件
- 包含设备状态图表展示和列表管理功能
- 删除无用的样式文件untitled-1.txt
main
zjlnb666 3 weeks ago
parent e4eeefc275
commit d1ca918075

@ -65,7 +65,20 @@ export default [
component: './assetmangement_maintenance/Maintenance',
},
]
}
},
// 设备监控
{
path: '/topnavbar00/business/devicemonitoring',
name: 'devicemonitoring',
routes: [
// 状态管理
{
path: '/topnavbar00/business/devicemonitoring/statemanagement',
name: 'statemanagement',
component: './devicemonitoring_statemanagement/StateManagement',
},
]
},
],
},
],

@ -351,16 +351,7 @@ const AssetGrouping = () => {
</div>
</Row>
<Row style={{margin:'30px 0'}}>
{/*<AssetGroupTable ></AssetGroupTable>*/}
<Table
// rowSelection={rowSelection}
columns={columns}
dataSource={mockData} // 实际场景中替换为接口返回的dataSource
rowKey="groupId"
pagination={false} // 关闭表格自带分页使用外部Pagination组件
style={{width:'100%'}}
// className={styles.table}
/>
<AssetGroupTable ></AssetGroupTable>
</Row>
</Col>
</Row>

@ -100,7 +100,7 @@ const Maintenance = ()=>{
];
return (
<div>
<div style={{backgroundColor: '#f0f7f7', height: '100%', overflow: 'hidden'}}>
<div style={{backgroundColor: '#f0f7f7', overflow: 'hidden'}}>
<Row gutter={20} style={{height: '100%'}}>
<Col span={4}>
<div style={{padding: '20px', backgroundColor: '#fff', height: '100%'}}>
@ -143,6 +143,7 @@ const Maintenance = ()=>{
</div>
</div>
</Col>
<Col span={20}>
<Row style={{backgroundColor: '#fff',padding:'20px'}}>
<Tabs tabBarExtraContent={operations} items={items} style={{flex:'1'}}/>

@ -1,17 +0,0 @@
.item{
padding: 20px;
border: 1px solid;
border-image-slice: 1;
border-image-source: conic-gradient(from 102.21deg at 52.75% 38.75%, rgba(249, 249, 249, 0.5) -32.95deg, rgba(64, 64, 64, 0.5) 10.52deg, rgba(64, 64, 64, 0.35) 32.12deg, #FFFFFF 60.28deg, rgba(255, 255, 255, 0.5) 107.79deg, rgba(64, 64, 64, 0.35) 187.59deg, #F9F9F9 207.58deg, #FFFFFF 287.31deg, rgba(249, 249, 249, 0.5) 327.05deg, rgba(64, 64, 64, 0.5) 370.52deg);
background: #FFFFFF4D;
backdrop-filter: blur(15px);
border-radius: 8px;
// 合并多个阴影效果,用逗号分隔
box-shadow:
-2px 4px 10px 0px #9191910D,
-7px 17px 18px 0px #9191910A,
-15px 37px 24px 0px #91919108,
-27px 66px 29px 0px #91919103,
-42px 103px 31px 0px #91919100;
}

@ -0,0 +1,533 @@
import React, { useState, useEffect, useRef } from 'react';
import { Row, Col, Card, Button, Input, Select, DatePicker, Space, Tag, Progress } from 'antd';
import { SearchOutlined, InfoCircleOutlined, BellOutlined, DownloadOutlined, ReloadOutlined,PlusOutlined } from '@ant-design/icons';
import * as echarts from 'echarts';
import TableWithPagination from '@/components/assetmangement/table';
import Title from '../homepage/compontent/title';
import styles from './StateManagement.less';
const { Option } = Select;
const StateManagement = () => {
const pieChartRef = useRef(null);
const lineChartRef = useRef(null);
const barChartRef = useRef(null);
const [searchValue, setSearchValue] = useState('');
const [selectedStatus, setSelectedStatus] = useState('all');
const [selectedDate, setSelectedDate] = useState(null);
// 设备状态数据
const deviceStatusData = [
{ key: '1', deviceId: 'DEV-001', deviceName: '温度传感器A', deviceType: '传感器', status: '在线', ip: '192.168.1.10', protocol: 'MQTT', location: '车间A', uptime: '在线8小时' },
{ key: '2', deviceId: 'DEV-002', deviceName: '工业网关B', deviceType: '网关', status: '离线', ip: '192.168.1.11', protocol: 'CoAP', location: '机房B', uptime: '离线2小时' },
{ key: '3', deviceId: 'DEV-003', deviceName: '高清摄像头C', deviceType: '摄像头', status: '故障', ip: '192.168.1.12', protocol: 'HTTP', location: '园区C', uptime: '离线1天(故障)' },
{ key: '4', deviceId: 'DEV-004', deviceName: '压力传感器D', deviceType: '传感器', status: '在线', ip: '192.168.1.13', protocol: 'Modbus', location: '产线D', uptime: '在线12小时' },
{ key: '5', deviceId: 'DEV-005', deviceName: '边缘计算节点E', deviceType: '网关', status: '在线', ip: '192.168.1.14', protocol: 'MQTT', location: '机房A', uptime: '在线24小时' },
{ key: '6', deviceId: 'DEV-006', deviceName: '电磁阀F', deviceType: '执行器', status: '离线', ip: '192.168.1.15', protocol: 'Modbus', location: '车间B', uptime: '离线5小时' },
];
// 设备状态占比数据
const statusDistributionData = [
{ value: 60, name: '在线', itemStyle: { color: '#006665' } },
{ value: 25, name: '离线', itemStyle: { color: '#999999' } },
{ value: 15, name: '故障', itemStyle: { color: '#FF826D' } },
];
// 在线率趋势数据
const onlineRateData = {
dates: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
rates: [88, 85, 90, 87, 82, 89]
};
// 设备类型分布数据
const deviceTypeData = {
categories: ['传感器A', '网关A', '摄像头', '传感器B', '网关B', '执行器'],
values: [40, 88, 60, 100, 68, 58]
};
// 表格列定义
const columns = [
{ title: '', dataIndex: 'checkbox', key: 'checkbox', width: 40 },
{ title: '设备ID', dataIndex: 'deviceId', key: 'deviceId' },
{ title: '设备名称', dataIndex: 'deviceName', key: 'deviceName' },
{ title: '设备类型', dataIndex: 'deviceType', key: 'deviceType' },
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status) => {
const colorMap = {
'在线': 'green',
'离线': 'gray',
'故障': 'red'
};
const statusTextMap = {
'在线': '在线(绿色)',
'离线': '离线(灰色)',
'故障': '故障(红色)'
};
return <Tag color={colorMap[status]}>{statusTextMap[status]}</Tag>;
}
},
{ title: 'IP地址', dataIndex: 'ip', key: 'ip' },
{ title: '协议类型', dataIndex: 'protocol', key: 'protocol' },
{ title: '位置信息', dataIndex: 'location', key: 'location' },
{ title: '在线时长/离线时间', dataIndex: 'uptime', key: 'uptime' },
{
title: '操作',
key: 'action',
align: 'center',
render: (_, record) => (
<Space>
<a style={{ color: '#2C9E9D' }}>查看详情</a>
<a style={{ color: '#2C9E9D' }}>编辑</a>
<a style={{ color: '#ff4d4f' }}>删除</a>
{record.status === '在线' && <a style={{ color: '#2C9E9D' }}>巡检</a>}
{record.status === '离线' && <a style={{ color: '#2C9E9D' }}>工单</a>}
{record.status === '故障' && <a style={{ color: '#2C9E9D' }}>升级</a>}
{record.status === '离线' && record.deviceType === '执行器' && <a style={{ color: '#2C9E9D' }}>报修</a>}
</Space>
)
}
];
// 初始化图表
useEffect(() => {
// 设备状态占比饼图
if (pieChartRef.current) {
const pieChart = echarts.init(pieChartRef.current);
const pieOption = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 10,
top: 'center',
itemWidth: 14,
itemHeight: 14,
textStyle: {
fontSize: 12
},
itemGap: 30,
formatter: function(name) {
// 找到对应的数值
const item = statusDistributionData.find(item => item.name === name);
return `${name} ${item.value}%`;
}
},
series: [{
name: '设备状态',
type: 'pie',
radius: [0, '70%'],
center: ['60%', '50%'],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 0,
borderColor: '#fff',
borderWidth: 2
},
label: {
show: false
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: statusDistributionData
}]
};
pieChart.setOption(pieOption);
}
// 在线率趋势折线图
if (lineChartRef.current) {
const lineChart = echarts.init(lineChartRef.current);
const lineOption = {
tooltip: {
trigger: 'axis',
formatter: '{b}<br/>{a}: {c}%'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top:'5%',
containLabel: true
},
xAxis: {
type: 'category',
data: onlineRateData.dates,
axisLine: {
lineStyle: {
color: '#d9d9d9',
type: 'dashed'
},
show:true
},
axisLabel: {
color: '#666',
show:true
},
axisTick: {
alignWithLabel: true // 使x轴刻度与标签对齐
},
boundaryGap: false, // 设置坐标轴两端是否留白
splitLine: {
lineStyle: {
color: '#CCCCCC',
type: 'deshed'
},
show:true
}
},
yAxis: {
type: 'value',
min: 0,
max: 100,
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
},
axisLabel: {
formatter: '{value}%',
color: '#666'
},
splitLine: {
lineStyle: {
color: '#f0f0f0',
type: 'solid'
}
}
},
series: [{
name: '在线率',
type: 'line',
data: onlineRateData.rates,
smooth: false,
lineStyle: {
color: '#2C9E9D',
width: 3,
// type: 'dashed'
},
itemStyle: {
color: '#2C9E9D'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#E8F3EFcc'
}, {
offset: 1, color: '#EAF6F2cc'
}]
}
},
emphasis: {
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0, color: '#E8F3EFcc'
}, {
offset: 1, color: '#EAF6F2cc'
}]
}
}
}
}]
};
lineChart.setOption(lineOption);
}
// 设备类型分布柱状图
if (barChartRef.current) {
const barChart = echarts.init(barChartRef.current);
const barOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top:'10%',
containLabel: true
},
xAxis: {
type: 'category',
data: deviceTypeData.categories,
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
},
axisLabel: {
color: '#666',
interval: 0
},
splitLine: {
show: true,
lineStyle: {
color: '#CCCCCC',
type: 'deshed'
},
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#d9d9d9'
}
},
axisLabel: {
color: '#666'
},
splitLine: {
lineStyle: {
color: '#f0f0f0',
type: 'dashed' // 类目之间的虚线
}
},
max:()=>{
return Math.max(...deviceTypeData.values) * 1.2;
}
},
series: [{
name: '设备数量',
type: 'bar',
data: deviceTypeData.values,
itemStyle: {
color: function(params) {
// 根据数据值设置不同的颜色
const colors = ['#86bbd8', '#8884d8', '#006665', '#2e8bc0', '#a0c4e2', '#e8d4b0'];
return colors[params.dataIndex % colors.length];
}
},
barWidth: '30%',
label: {
normal: {
show: true,
position: 'top',
textStyle: {
color: '#666'
}
}
}
}]
};
barChart.setOption(barOption);
}
// 响应式处理
const handleResize = () => {
if (pieChartRef.current) {
const pieChart = echarts.getInstanceByDom(pieChartRef.current);
pieChart && pieChart.resize();
}
if (lineChartRef.current) {
const lineChart = echarts.getInstanceByDom(lineChartRef.current);
lineChart && lineChart.resize();
}
if (barChartRef.current) {
const barChart = echarts.getInstanceByDom(barChartRef.current);
barChart && barChart.resize();
}
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
// 筛选处理函数
const handleSearch = () => {
console.log('搜索条件:', { searchValue, selectedStatus, selectedDate });
};
const handleReset = () => {
setSearchValue('');
setSelectedStatus('all');
setSelectedDate(null);
};
return (
<div style={{ padding: '20px', backgroundColor: '#fff', minHeight: '100vh' }}>
{/* 筛选条件区域 */}
<Card
style={{
border:'none'
}}
bodyStyle={{ padding: '16px 24px' }}
title={
<>
<Row justify="space-between">
<Title title="筛选条件" />
<Col span={8} style={{ textAlign: 'right' }}>
<Space>
<Button
type="primary"
icon={<SearchOutlined />}
onClick={handleSearch}
style={{ borderRadius: '6px' }}
className={styles['search-button']}
>
查询
</Button>
<Button
onClick={handleReset}
style={{ borderRadius: '6px' }}
className={styles['reset-button']}
icon={<ReloadOutlined /> }
>
重置
</Button>
</Space>
</Col>
</Row>
<Row gutter={16} align="middle" style={{margin:'20px 0'}} justify='space-between'>
<Col span={6}>
<Input
placeholder="请输入设备名称或编号"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
style={{ borderRadius: '6px' }}
suffix={<SearchOutlined style={{ color: '#bfbfbf' }} />}
/>
</Col>
<Col span={4}>
<label>设备状态:</label>
<Select
value={selectedStatus}
onChange={setSelectedStatus}
style={{ width: '152px', borderRadius: '6px' ,marginLeft:'10px'}}
>
<Option value="all">全部状态</Option>
<Option value="online">在线</Option>
<Option value="offline">离线</Option>
<Option value="abnormal">异常</Option>
</Select>
</Col>
<Col span={4}>
<label>位置信息:</label>
<Select
value={selectedStatus}
// onChange={setSelectedStatus}
style={{ width: '152px', borderRadius: '6px' ,marginLeft:'10px'}}
>
<Option value="all">全部</Option>
</Select>
</Col>
<Col span={4}>
<label>设备状态:</label>
<Select
value={selectedStatus}
// onChange={setSelectedStatus}
style={{ width: '152px', borderRadius: '6px' ,marginLeft:'10px'}}
>
<Option value="all">全部</Option>
</Select>
</Col>
<Col span={4}>
<label>协议类型:</label>
<Select
value={selectedStatus}
// onChange={setSelectedStatus}
style={{ width: '152px', borderRadius: '6px' ,marginLeft:'10px'}}
>
<Option value="all">全部</Option>
</Select>
</Col>
</Row>
</>
}
>
</Card>
{/* 数据可视化区域 */}
<Row gutter={20} style={{ marginBottom: '20px' }}>
<Col span={6}>
<Card
title= {<Title title="设备状态占比饼图"/>}
style={{ borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}
bodyStyle={{ padding: '16px', height: '200px' }}
>
<div ref={pieChartRef} style={{ width: '100%', height: '100%' }} />
</Card>
</Col>
<Col span={9}>
<Card
title={<Title title="设备在线率趋势折线图"/>}
style={{ borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}
bodyStyle={{ padding: '16px', height: '200px' }}
>
<div ref={lineChartRef} style={{ width: '100%', height: '100%' }} />
</Card>
</Col>
<Col span={9}>
<Card
title={<Title title="设备类型分布柱状图"/>}
style={{ borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,0.1)' }}
bodyStyle={{ padding: '16px', height: '200px' }}
>
<div ref={barChartRef} style={{ width: '100%', height: '100%' }} />
</Card>
</Col>
</Row>
{/* 设备列表表格 */}
<Card
style={{
borderRadius: '8px',
boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
}}
bodyStyle={{ padding: '0' }}
>
<div style={{ padding: '20px 24px', borderBottom: '1px solid #f0f0f0' }}>
<Row justify="space-between" align="middle">
<Title title="设备状态列表"/>
</Row>
<Row justify="space-between" align="middle" style={{ margin: '20px 0' }}>
<Col span={12}>
<Button style={{marginRight:30}} className={styles['search-button']}>导入数据</Button>
<Button style={{marginRight:30}} className={styles['reset-button']}>导出数据</Button>
<Button className={styles['del-button']}>删除</Button>
</Col>
<Col span={12} style={{ textAlign: 'right' }}>
<Button className={styles['search-button']} icon={<PlusOutlined />}>新增设备</Button>
</Col>
</Row>
<TableWithPagination
columns={columns}
dataSource={deviceStatusData}
rowSelection={true}
style={{ padding: '0 24px' }}
/>
</div>
</Card>
</div>
);
};
export default StateManagement;

@ -0,0 +1,34 @@
.search-button{
background-image: url('../../assets/img/assetmangement1.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #fff;
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #045F5E80;
}
.reset-button{
background-image: url('../../assets/img/assetmangement2.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: rgba(0, 102, 101, 1);
border-radius: 4px;
height: 36px;
border-color:#d9d9d9 ;
background-color: #B7E5D533;
}
.del-button{
background-image: url('../../assets/img/assetmangement3.png');
background-repeat: no-repeat;
background-size: cover;
background-position:center;
color: #000;
border-radius: 4px;
height: 36px;
width:88px;
border-color:#d9d9d9 ;
background-color: #E5B7B733;
}

@ -154,7 +154,29 @@ const SystemContentList = (props) => {
"label": "维保管理"
},
]
}
},
// 设备监控
{
path: '/topnavbar00/business/devicemonitoring',
icon: <img
src={icon1}
alt="设备监控"
style={{
width: '16px',
height: '16px',
opacity: selectedKey.includes('/topnavbar00/business/devicemonitoring') ? 1 : 0.6
}}
/>,
key: "/topnavbar00/business/devicemonitoring",
"label": "设备监控",
children: [
{
path: '/topnavbar00/business/devicemonitoring/statemanagement',
key: "/topnavbar00/business/devicemonitoring/statemanagement",
"label": "状态管理"
},
]
},
]
setMenuItems(fixedMenuItems)
// 初始化默认路由

@ -34,6 +34,11 @@ const menuItem = [
label: '维保管理',
key: '/topnavbar00/business/assetmanagement/maintenance',
},
// 状态管理
{
label: '状态管理',
key: '/topnavbar00/business/devicemonitoring/statemanagement',
},
]
const TopNavBar = (props) => {

Loading…
Cancel
Save