消防基础页面

main
wangyunfei 3 weeks ago
parent 90a1992550
commit 8036251eed

@ -1,6 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Card, Result, Select, Button, Segmented } from 'antd'; import { Card, Result, Select, Button, Segmented, Progress, Input } from 'antd';
import { CheckCircleOutlined, ExportOutlined, HeartFilled, LineHeightOutlined } from '@ant-design/icons'; import { CheckCircleOutlined, ExportOutlined, HeartFilled, LineHeightOutlined, ExclamationCircleOutlined, SearchOutlined } from '@ant-design/icons';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import StandardTable from '@/components/StandardTable'; import StandardTable from '@/components/StandardTable';
import styles from './EvaluationReport.less'; import styles from './EvaluationReport.less';
@ -27,9 +27,10 @@ const EvaluationReport = () => {
const [dataSource, setDataSource] = useState([]); const [dataSource, setDataSource] = useState([]);
const [pagination, setPagination] = useState({ const [pagination, setPagination] = useState({
current: 1, current: 1,
pageSize: 5, pageSize: 8,
total: 0, total: 0,
}); });
const [searchText, setSearchText] = useState('');
// 柱状图初始化 // 柱状图初始化
useEffect(() => { useEffect(() => {
@ -140,7 +141,7 @@ const EvaluationReport = () => {
axisPointer: { axisPointer: {
type: 'shadow' type: 'shadow'
}, },
formatter: function(params) { formatter: function (params) {
return `${params[0].name}<br/>使用次数: ${params[0].value}`; return `${params[0].name}<br/>使用次数: ${params[0].value}`;
} }
} }
@ -175,6 +176,7 @@ const EvaluationReport = () => {
legend: { legend: {
show: true, show: true,
top: '5%',
left: 'center', left: 'center',
itemWidth: 20, itemWidth: 20,
itemHeight: 8, itemHeight: 8,
@ -187,7 +189,7 @@ const EvaluationReport = () => {
left: '5%', left: '5%',
right: '5%', right: '5%',
bottom: '10%', bottom: '10%',
top: '15%', top: '20%',
containLabel: true containLabel: true
}, },
xAxis: { xAxis: {
@ -444,7 +446,7 @@ const EvaluationReport = () => {
width: 60, width: 60,
render: (text, record, index) => { render: (text, record, index) => {
const page = pagination.current || 1; const page = pagination.current || 1;
const pageSize = pagination.pageSize || 5; const pageSize = pagination.pageSize || 8;
const number = (page - 1) * pageSize + index + 1; const number = (page - 1) * pageSize + index + 1;
return `0${number}`.slice(-2); return `0${number}`.slice(-2);
} }
@ -462,26 +464,27 @@ const EvaluationReport = () => {
width: 110, width: 110,
}, },
{ {
title: '号规格', title: '型',
dataIndex: 'modelSpec', dataIndex: 'modelSpec',
key: 'modelSpec', key: 'modelSpec',
width: 140, width: 120,
}, },
{ {
title: '安装位置', title: '安装位置',
dataIndex: 'installLocation', dataIndex: 'installLocation',
key: 'installLocation', key: 'installLocation',
width: 200, width: 100,
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
key: 'status', key: 'status',
width: 80, width: 100,
render: (text) => { render: (text) => {
const statusMap = { const statusMap = {
'故障': { color: '#FF4D4F', bg: '#FFF2F0' }, '报废': { color: '#FF3E48', bg: '#FFE0E2' },
'预警': { color: '#FAAD14', bg: '#FFF3E9' }, '待维修': { color: '#FF8800', bg: '#FFF3E9' },
'已使用': { color: '#00AAFA', bg: '#DAF3FF' },
'正常': { color: '#44BB5F', bg: '#D8F7DE' } '正常': { color: '#44BB5F', bg: '#D8F7DE' }
}; };
const status = statusMap[text] || { color: '#333', bg: '#F5F5F5' }; const status = statusMap[text] || { color: '#333', bg: '#F5F5F5' };
@ -499,7 +502,7 @@ const EvaluationReport = () => {
} }
}, },
{ {
title: '最后维护', title: '最后维护时间',
dataIndex: 'lastMaintenance', dataIndex: 'lastMaintenance',
key: 'lastMaintenance', key: 'lastMaintenance',
width: 150, width: 150,
@ -510,9 +513,9 @@ const EvaluationReport = () => {
width: 140, width: 140,
render: (_, record) => ( render: (_, record) => (
<div> <div>
<Button type="link" size="small" style={{ <Button type="link" size="small" style={{
padding: '2px 8px', padding: '2px 8px',
fontSize: 12, fontSize: 12,
marginRight: 8, marginRight: 8,
border: '1px solid #E6E9FB', border: '1px solid #E6E9FB',
backgroundColor: 'transparent', backgroundColor: 'transparent',
@ -520,14 +523,15 @@ const EvaluationReport = () => {
}}> }}>
编辑 编辑
</Button> </Button>
<Button type="link" size="small" style={{ <Button type="link" size="small" style={{
padding: '2px 8px', padding: '2px 8px',
fontSize: 12, fontSize: 12,
border: '1px solid #E6E9FB', color: '#FF2526',
border: '1px solid #FFE0E2',
backgroundColor: 'transparent', backgroundColor: 'transparent',
borderRadius: '4px' borderRadius: '4px'
}}> }}>
详情 删除
</Button> </Button>
</div> </div>
), ),
@ -540,122 +544,162 @@ const EvaluationReport = () => {
key: '1', key: '1',
id: '001', id: '001',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-001',
deviceName: '消防水泵', deviceName: '干粉灭火器',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼1层大厅', installLocation: '1层大厅',
status: '故障', status: '报废',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '2', key: '2',
id: '002', id: '002',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-02-015',
deviceName: '消防水泵', deviceName: '室内消火栓',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼3层 东区', installLocation: '3层东区',
status: '预警', status: '已使用',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '3', key: '3',
id: '003', id: '003',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-03-007',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '正常', status: '正常',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '4', key: '4',
id: '004', id: '004',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-03-008',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '故障', status: '待维修',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '5', key: '5',
id: '005', id: '005',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-009',
deviceName: '消防水泵', deviceName: '干粉灭火器',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '正常', status: '报废',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '6', key: '6',
id: '006', id: '006',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-010',
deviceName: '消防水泵', deviceName: '室内消火栓',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '预警', status: '已使用',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '7', key: '7',
id: '007', id: '007',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-011',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '故障', status: '待维修',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '8', key: '8',
id: '008', id: '008',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-012',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '正常', status: '正常',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '9', key: '9',
id: '009', id: '009',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-013',
deviceName: '消防水泵', deviceName: '干粉灭火器',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '预警', status: '已使用',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '10', key: '10',
id: '010', id: '010',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-014',
deviceName: '消防水泵', deviceName: '室内消火栓',
modelSpec: 'XBD5.0/30-125', modelSpec: '灭火设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '故障', status: '待维修',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '11', key: '11',
id: '011', id: '011',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-015',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '正常', status: '正常',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{ {
key: '12', key: '12',
id: '012', id: '012',
deviceId: 'HQ-XF-01-001', deviceId: 'HQ-XF-01-016',
deviceName: '消防水泵', deviceName: '火警报警器',
modelSpec: 'XBD5.0/30-125', modelSpec: '报警设备',
installLocation: '总部大楼地下一层', installLocation: '地下一层',
status: '预警', status: '已使用',
lastMaintenance: '2025-09-10', lastMaintenance: '2025-09-10',
}, },
{
key: '13',
id: '013',
deviceId: 'HQ-XF-01-017',
deviceName: '干粉灭火器',
modelSpec: '灭火设备',
installLocation: '2层西区',
status: '报废',
lastMaintenance: '2024-08-15',
},
{
key: '14',
id: '014',
deviceId: 'HQ-XF-02-018',
deviceName: '室内消火栓',
modelSpec: '灭火设备',
installLocation: '4层南区',
status: '报废',
lastMaintenance: '2024-07-20',
},
{
key: '15',
id: '015',
deviceId: 'HQ-XF-03-019',
deviceName: '火警报警器',
modelSpec: '报警设备',
installLocation: '地下二层',
status: '报废',
lastMaintenance: '2024-06-10',
},
{
key: '16',
id: '016',
deviceId: 'HQ-XF-01-020',
deviceName: '干粉灭火器',
modelSpec: '灭火设备',
installLocation: '5层北区',
status: '报废',
lastMaintenance: '2024-05-05',
},
]; ];
// 初始化数据 // 初始化数据
@ -698,9 +742,16 @@ const EvaluationReport = () => {
})); }));
}; };
// 搜索处理
const handleSearchChange = (e) => {
setSearchText(e.target.value);
console.log('搜索:', e.target.value);
// TODO: 实现搜索逻辑,根据设备名称、编号等筛选数据
};
return ( return (
<div className={styles.Econtainer}> <div className={styles.Econtainer}>
{/* 第二个div - 高度39% */} {/* 第1个div - 高度39% */}
<div className={styles.EcontainerMiddle}> <div className={styles.EcontainerMiddle}>
<div className={styles.sectionContent}> <div className={styles.sectionContent}>
<div className={styles.middleBlock1}> <div className={styles.middleBlock1}>
@ -741,7 +792,7 @@ const EvaluationReport = () => {
</div> </div>
</div> </div>
{/* 第个div - 占满剩余位置 */} {/* 第2个div - 占满剩余位置 */}
<div className={styles.EcontainerBottom}> <div className={styles.EcontainerBottom}>
<div className={styles.sectionContent}> <div className={styles.sectionContent}>
<div className={styles.leftBlock}> <div className={styles.leftBlock}>
@ -751,14 +802,57 @@ const EvaluationReport = () => {
<div className={styles.titleIcon}></div> <div className={styles.titleIcon}></div>
<div>近期维护提醒</div> <div>近期维护提醒</div>
</div> </div>
<div className={styles.maintenanceContent}></div> <div className={styles.maintenanceContent1}>
<div className={styles.maintenanceItem}>
<div className={styles.maintenanceLeft}>
<div className={styles.maintenanceText1}>SH-MHQ-023-C 干粉灭火器</div>
<div className={styles.maintenanceText2}>位置: 4楼办公区丨维护类型: 季度检查</div>
<div className={styles.maintenanceText3}>负责人: 张三</div>
</div>
<div className={styles.maintenanceRight}>
<div className={styles.maintenanceStatus}>3天后到期</div>
</div>
</div>
<div className={styles.maintenanceItem}>
<div className={styles.maintenanceLeft}>
<div className={styles.maintenanceText1}>SH-XHS-045-D 室内消火栓</div>
<div className={styles.maintenanceText2}>位置: 2楼东侧走廊丨维护类型: 水压测试</div>
<div className={styles.maintenanceText3}>负责人: 李四</div>
</div>
<div className={styles.maintenanceRight2}>
<div className={styles.maintenanceStatus}>8天后到期</div>
</div>
</div>
</div>
</div> </div>
<div className={styles.maintenanceSection}> <div className={styles.maintenanceSection}>
<div className={styles.maintenanceTitle}> <div className={styles.maintenanceTitle}>
<div className={styles.titleIcon}></div> <div className={styles.titleIcon}></div>
<div>维护任务进度</div> <div>维护任务进度</div>
</div> </div>
<div className={styles.maintenanceContent}></div> <div className={styles.maintenanceContent2}>
{/* 进度条区域 */}
<div className={styles.progressSection}>
<div className={styles.progressLabel}>月度维护计划</div>
<Progress percent={75} status="active" />
<div className={styles.progressLabel}>季度维护计划</div>
<Progress percent={60} status="active" />
<div className={styles.progressLabel}>年度维护计划</div>
<Progress percent={85} status="active" />
{/* 警告提示框 */}
<div className={styles.warningBox}>
<ExclamationCircleOutlined className={styles.warningIcon} />
<span className={styles.warningText}>本月有5项维护任务即将到期</span>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -768,21 +862,35 @@ const EvaluationReport = () => {
<div className={styles.tableHeader}> <div className={styles.tableHeader}>
<div className={styles.tableTitle}> <div className={styles.tableTitle}>
<div className={styles.titleIcon}></div> <div className={styles.titleIcon}></div>
<div>消防设备台账</div> <div>消防设施与器材列表</div>
</div>
<div className={styles.tableActions}>
<button className={styles.actionButton} onClick={handleAddDevice}>
<span className={styles.buttonIcon}>+</span>
<span>新增设备</span>
</button>
<button className={styles.actionButton} onClick={handleExportData}>
<span className={styles.buttonIcon}><ExportOutlined /></span>
<span>导出数据</span>
</button>
</div> </div>
</div> </div>
{/* 操作按钮 */}
<div className={styles.tableActions}>
<div className={styles.leftActions}>
<Input
placeholder="搜索设备名称、编号..."
onChange={handleSearchChange}
value={searchText}
style={{ width: 250, fontSize: 12 }}
allowClear
suffix={<SearchOutlined />}
/>
</div>
<div className={styles.rightActions}>
<button className={styles.actionButton} onClick={handleAddDevice}>
<span className={styles.buttonIcon}>+</span>
<span>新增设备</span>
</button>
<button className={styles.actionButton} onClick={handleExportData}>
<span className={styles.buttonIcon}><ExportOutlined /></span>
<span>导出数据</span>
</button>
</div>
</div>
{/* 表格 */} {/* 表格 */}
<div className={styles.tableContainer}> <div className={styles.tableContainer}>
<StandardTable <StandardTable

@ -5,9 +5,10 @@
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
// 第二个div - 高度39% // 第二个div - 高度35%
.EcontainerMiddle { .EcontainerMiddle {
height: 33%; // height: 400px;
min-height: 35%;
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -208,19 +209,16 @@
.middleBlock2Chart { .middleBlock2Chart {
width: 100%; width: 100%;
height: 100%; height: 100%;
// min-height: 200px;
} }
} }
} }
} }
// 第三个div - 高度不超过45% // 第三个div - 占满剩余位置
.EcontainerBottom { .EcontainerBottom {
// height: 45%; // 限制高度不超过45%
// max-height: 45%; // 确保最大高度不超过45%
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex-shrink: 0;
.sectionContent { .sectionContent {
display: flex; display: flex;
@ -233,13 +231,10 @@
width: 30%; width: 30%;
flex-shrink: 0; flex-shrink: 0;
height: 100%; height: 100%;
// background: #fff;
// background-size: cover;
padding: 0; padding: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
// padding: 15px;
.leftBlockTitle { .leftBlockTitle {
display: flex; display: flex;
@ -295,6 +290,148 @@
flex: 1; flex: 1;
width: 100%; width: 100%;
} }
.maintenanceContent1 {
flex: 1;
width: 100%;
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 8px;
.maintenanceItem {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #F1F7FF;
border-radius: 4px;
padding: 16px 16px;
.maintenanceLeft {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
.maintenanceText1 {
font-size: 14px;
font-weight: 500;
color: #333333;
font-family: PingFang SC;
}
.maintenanceText2 {
font-size: 12px;
color: #666666;
font-family: PingFang SC;
}
.maintenanceText3 {
font-size: 12px;
color: #666666;
font-family: PingFang SC;
}
}
.maintenanceRight {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
.maintenanceStatus {
font-size: 12px;
color: #FF3E48;
font-weight: 500;
font-family: PingFang SC;
background-color: #FFE0E2;
padding: 4px 8px;
border-radius: 4px;
// border: 1px solid #FFE0E2;
}
}
.maintenanceRight2 {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
.maintenanceStatus {
font-size: 12px;
color: #FF8800;
font-weight: 500;
font-family: PingFang SC;
background-color: #FFF3E9;
padding: 4px 8px;
border-radius: 4px;
// padding-right: 2px;
}
}
}
}
.maintenanceContent2 {
flex: 1;
width: 100%;
display: flex;
flex-direction: column;
gap: 15px;
padding: 8px 0;
.warningBox {
display: flex;
align-items: center;
gap: 8px;
background-color: #FFF3CD;
border: 1px solid #F4E3AE;
border-radius: 4px;
padding: 8px 12px;
// margin-bottom: 8px;
// margin-top: 10px;
.warningIcon {
color: #8C6C0B;
font-size: 14px;
}
.warningText {
color: #8C6C0B;
font-size: 12px;
font-family: PingFang SC;
font-weight: 400;
}
}
.progressSection {
width: 100%;
display: flex;
flex-direction: column;
// gap: 12px;
padding: 0px 12px 12px 12px;
.progressLabel {
font-size: 12px;
color: #666666;
font-family: PingFang SC;
font-weight: 400;
}
// 自定义进度条样式
:global(.ant-progress) {
.ant-progress-bg {
background: linear-gradient(90deg, #2E4CD4 0%, #4B69F1 100%);
}
.ant-progress-text {
color: #2E4CD4;
font-weight: 500;
}
}
}
}
} }
} }
} }
@ -311,7 +448,7 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 8px 15px 5px 15px; padding: 11px 15px 5px 15px;
.tableTitle { .tableTitle {
display: flex; display: flex;
@ -328,40 +465,54 @@
background-color: #2E4CD4; background-color: #2E4CD4;
} }
} }
}
.tableActions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 8px;
margin-top: 5px;
padding: 0px 15px;
.leftActions {
display: flex;
align-items: center;
}
.tableActions { .rightActions {
display: flex; display: flex;
gap: 8px; gap: 8px;
margin-top: 5px; align-items: center;
}
.actionButton { .actionButton {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
height: 28px; height: 28px;
border: 1px solid #DFE4F6; border: 1px solid #DFE4F6;
border-radius: 4px; border-radius: 4px;
color: #2E4CD4; color: #2E4CD4;
font-weight: 500; font-weight: 500;
font-size: 12px; font-size: 12px;
padding: 0px 8px; padding: 0px 8px;
background: transparent; background: transparent;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
&:hover { &:hover {
background-color: #f0f2ff; background-color: #f0f2ff;
border-color: #2E4CD4; border-color: #2E4CD4;
} }
&:active { &:active {
background-color: #e6ebff; background-color: #e6ebff;
} }
.buttonIcon { .buttonIcon {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
}
} }
} }
} }
@ -389,6 +540,7 @@
padding: 8px 12px; padding: 8px 12px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
text-align: center; text-align: center;
color: #666666;
} }
:global(.ant-table-tbody > tr:hover > td) { :global(.ant-table-tbody > tr:hover > td) {

@ -892,6 +892,8 @@
padding: 8px 12px; padding: 8px 12px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
text-align: center; text-align: center;
color: #666666;
// color: pink;
} }
:global(.ant-table-tbody > tr:hover > td) { :global(.ant-table-tbody > tr:hover > td) {

@ -576,6 +576,7 @@
padding: 8px 12px; padding: 8px 12px;
border-bottom: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0;
text-align: center; text-align: center;
color: #666666;
} }
:global(.ant-table-tbody > tr:hover > td) { :global(.ant-table-tbody > tr:hover > td) {

Loading…
Cancel
Save