应急演练页面

main
wangyunfei 2 days ago
parent 6b70d5e55b
commit d31c140a11

@ -0,0 +1,14 @@
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2141_24898)">
<path d="M23.625 0H3.375C1.51875 0 0 1.51875 0 3.375V23.625C0 25.4813 1.51875 27 3.375 27H23.625C25.4813 27 27 25.4813 27 23.625V3.375C27 1.51875 25.4813 0 23.625 0ZM19.7437 14.85L10.8 20.0812C9.7875 20.5875 8.4375 19.9125 8.4375 18.7313V8.26875C8.4375 7.0875 9.7875 6.24375 10.8 6.91875L19.7437 12.15C20.7563 12.6562 20.7563 14.3438 19.7437 14.85Z" fill="url(#paint0_linear_2141_24898)"/>
</g>
<defs>
<linearGradient id="paint0_linear_2141_24898" x1="13.5" y1="0" x2="13.5" y2="27" gradientUnits="userSpaceOnUse">
<stop stop-color="#556FEB"/>
<stop offset="1" stop-color="#8DAAF7"/>
</linearGradient>
<clipPath id="clip0_2141_24898">
<rect width="27" height="27" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 841 B

@ -1,77 +1,372 @@
import React, { useState } from 'react';
import { Card, Row, Col, Statistic, Progress, Button, Space } from 'antd';
import styles from './EmergencyResource.less';
import ComplianceManagement from './components/ComplianceManagement'; //合规性管理
import OnlineMonitoring from './components/OnlineMonitoring'; //在线监测预警
import EnvironmentalPersonnelManagement from './components/EnvironmentalPersonnelManagement'; //环保人员管理
import EvaluationReport from './components/EvaluationReport'; //评估报告
import EquipmentManagement from './components/EquipmentManagement'; //环保设备设施管理
import PollutionSourceManagement from './components/PollutionSourceManagement'; //污染源管理
import React, { useState, useEffect, useRef } from 'react';
import { Button } from "antd";
import * as echarts from 'echarts';
import styles from './EmergencyDrill.less';
import { Import } from '../business_hiddentrouble/component/hiddenDangerInspection/hiddenDangerInspection';
import iconDrill1 from '../../assets/business_Emergency/iconDrill1.svg';
const EmergencyDrill = () => {
const [timeType, setTimeType] = useState('month');
const chartRef = useRef(null);
const chartInstanceRef = useRef(null);
const chartRef2 = useRef(null);
const chartInstanceRef2 = useRef(null);
useEffect(() => {
if (!chartRef.current) return;
const SafeMajorHazardList = () => {
const [activeModule, setActiveModule] = useState('organization');
// 初始化图表
if (!chartInstanceRef.current) {
chartInstanceRef.current = echarts.init(chartRef.current);
}
// 模拟数据
const data = [12, 18, 8, 15, 22, 10, 14, 20, 16, 11, 19, 25];
const option = {
grid: {
left: '3%',
right: '3%',
top: '10%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
axisLabel: {
color: '#666666',
fontSize: 12
},
axisLine: {
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
},
axisTick: {
show: false
},
splitLine: {
show: true,
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 30,
interval: 5,
axisLabel: {
color: '#666666',
fontSize: 12
},
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
}
},
series: [
{
data: data,
type: 'bar',
barWidth: 23,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#556FEB' },
{ offset: 1, color: '#8DAAF7' }
])
}
}
]
};
chartInstanceRef.current.setOption(option);
// 窗口大小变化时重新渲染
const handleResize = () => {
chartInstanceRef.current?.resize();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [timeType]);
// 组件卸载时销毁图表
useEffect(() => {
return () => {
chartInstanceRef.current?.dispose();
chartInstanceRef2.current?.dispose();
};
}, []);
const handleModuleClick = (module) => {
setActiveModule(module)
// 第二个图表 - 折线图
useEffect(() => {
if (!chartRef2.current) return;
// 初始化图表
if (!chartInstanceRef2.current) {
chartInstanceRef2.current = echarts.init(chartRef2.current);
}
// 模拟数据
const plannedData = [12, 15, 10, 18, 20, 16, 14, 22, 19, 17, 21, 23]; // 计划演练
const actualData = [10, 13, 9, 16, 18, 15, 12, 20, 17, 15, 19, 21]; // 实际完成
const renderModule = () => {
switch (activeModule) {
case 'organization':
return <ComplianceManagement />;
case 'equipment':
return <OnlineMonitoring />;
case 'firefighting':
return <EnvironmentalPersonnelManagement />;
case 'other':
return <EvaluationReport />;
case 'equipmentManagement':
return <EquipmentManagement />;
case 'pollutionSource':
return <PollutionSourceManagement />;
default:
return <ComplianceManagement />;
const option = {
grid: {
left: '3%',
right: '3%',
top: '15%',
bottom: '3%',
containLabel: true
},
legend: {
data: ['计划演练', '实际完成'],
top: '5%',
right: 'center',
textStyle: {
color: '#666666',
fontSize: 12
},
itemWidth: 14,
itemHeight: 8
},
xAxis: {
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
axisLabel: {
color: '#666666',
fontSize: 12
},
axisLine: {
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
},
axisTick: {
show: false
},
splitLine: {
show: true,
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 30,
interval: 5,
axisLabel: {
color: '#666666',
fontSize: 12
},
axisLine: {
show: false
},
axisTick: {
show: false
},
splitLine: {
lineStyle: {
color: '#E5E5E5',
type: 'dashed'
}
}
},
series: [
{
name: '计划演练',
type: 'line',
data: plannedData,
smooth: false,
lineStyle: {
color: '#3CC3DF',
width: 1
},
itemStyle: {
color: '#fff',
borderColor: '#3CC3DF',
borderWidth: 1
},
symbol: 'circle',
symbolSize: 6,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(60, 195, 223, 0.4)' },
{ offset: 1, color: 'rgba(60, 195, 223, 0.05)' }
]
}
}
},
{
name: '实际完成',
type: 'line',
data: actualData,
smooth: false,
lineStyle: {
color: '#8979FF',
width: 1
},
itemStyle: {
color: '#fff',
borderColor: '#8979FF',
borderWidth: 1
},
symbol: 'circle',
symbolSize: 6,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(137, 121, 255, 0.4)' },
{ offset: 1, color: 'rgba(137, 121, 255, 0.05)' }
]
}
}
}
]
};
chartInstanceRef2.current.setOption(option);
// 窗口大小变化时重新渲染
const handleResize = () => {
chartInstanceRef2.current?.resize();
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return (
<div className={styles.containerDrill}>
<div className={styles.block1}>
<div className={styles.block1_item1}>
<div className={styles.item1_row1}>
<div className={styles.row1_left}>
<div className={styles.colorBlock}></div>
<span className={styles.title}>预案演练</span>
</div>
<Button className={styles.startBtn}>
<span className={styles.btnIcon}></span>
<span>开始演练</span>
</Button>
</div>
<div className={styles.item1_row2}>
<div className={styles.row2_left}>
<div className={styles.row2_title}>化工事故应急预案</div>
<div className={styles.row2_version}>最新版本:V3.2</div>
</div>
<div className={styles.row2_right}>
<img src={iconDrill1} alt="drill icon" className={styles.drillIcon} />
</div>
</div>
<div className={styles.item1_row3}>
<div className={styles.row3_left}>
<div className={styles.row3_title}>化工事故应急预案</div>
<div className={styles.row3_version}>最新版本:V3.2</div>
</div>
<div className={styles.row3_right}>
<img src={iconDrill1} alt="drill icon" className={styles.drillIcon} />
</div>
</div>
return (
<div className={styles.container}>
<div className={styles.TopButton}>
<Button
className={`${styles.TopButtonItem} ${activeModule === "organization" ? styles.active : ""}`}
onClick={() => handleModuleClick("organization")}
>合规性管理
</Button>
<Button
className={`${styles.TopButtonItem} ${activeModule === "firefighting" ? styles.active : ""}`}
onClick={() => handleModuleClick("firefighting")}
>环保人员管理
</Button>
<Button
className={`${styles.TopButtonItem} ${activeModule === "other" ? styles.active : ""}`}
onClick={() => handleModuleClick("other")}
>排污许可管理
</Button>
<Button
className={`${styles.TopButtonItem} ${activeModule === "equipmentManagement" ? styles.active : ""}`}
onClick={() => handleModuleClick("equipmentManagement")}
>环保设备设施管理
</Button>
<Button
className={`${styles.TopButtonItem} ${activeModule === "pollutionSource" ? styles.active : ""}`}
onClick={() => handleModuleClick("pollutionSource")}
>污染源管理
</Button>
<div className={styles.item1_row4}>
<div className={styles.row4_left}>
<div className={styles.row4_title}>化工事故应急预案</div>
<div className={styles.row4_version}>最新版本:V3.2</div>
</div>
<div className={styles.row4_right}>
<img src={iconDrill1} alt="drill icon" className={styles.drillIcon} />
</div>
</div>
</div>
<div className={styles.block1_item2}>
<div className={styles.item2_row1}>
<div className={styles.row1_left}>
<div className={styles.colorBlock}></div>
<span className={styles.title}>演练数据统计</span>
</div>
<div className={styles.content}>
{renderModule()}
<div className={styles.timeBtnGroup}>
<Button
className={timeType === 'month' ? 'active' : ''}
onClick={() => setTimeType('month')}
>
</Button>
<Button
className={timeType === 'season' ? 'active' : ''}
onClick={() => setTimeType('season')}
>
</Button>
<Button
className={timeType === 'year' ? 'active' : ''}
onClick={() => setTimeType('year')}
>
</Button>
</div>
</div>
<div ref={chartRef} className={styles.chartContainer}></div>
</div>
<div className={styles.block1_item3}>
<div className={styles.item3_header}>
<div className={styles.colorBlock}></div>
<span className={styles.title}>演练完成情况</span>
</div>
<div ref={chartRef2} className={styles.chartContainer}></div>
</div>
);
</div>
<div className={styles.block2}>
{/* 第二块内容区域 */}
</div>
<div className={styles.block3}>
{/* 第三块内容区域 */}
</div>
</div>
);
};
export default SafeMajorHazardList;
export default EmergencyDrill;

@ -0,0 +1,305 @@
.containerDrill {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
gap: 15px;
padding: 5px;
box-sizing: border-box;
.block1 {
width: 100%;
height: 32%;
padding: 0;
margin: 0;
display: flex;
flex-direction: row;
gap: 15px;
.block1_item1 {
background-color: #fff;
width: 20%;
height: 100%;
display: flex;
flex-direction: column;
gap: 8px;
overflow: hidden;
.item1_row1 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 10px 0 10px;
.row1_left {
display: flex;
align-items: center;
gap: 8px;
.colorBlock {
width: 2px;
height: 16px;
background-color: #2E4CD4;
opacity: 1;
}
.title {
font-size: 14px;
font-weight: 500;
color: #333333;
}
}
.startBtn {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
background: linear-gradient(180deg, #556FEB 0%, #8DAAF7 100%);
color: #fff;
font-size: 14px;
font-weight: 400;
border: none;
border-radius: 4px;
cursor: pointer;
.btnIcon {
font-size: 12px;
}
}
}
.item1_row2 {
flex: 1;
background-color: #F6F7FF;
margin: 0 10px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
.row2_left {
display: flex;
flex-direction: column;
gap: 8px;
.row2_title {
font-size: 14px;
color: #333333;
}
.row2_version {
font-size: 12px;
color: #666666;
}
}
.row2_right {
display: flex;
align-items: center;
.drillIcon {
width: auto;
height: 30px;
}
}
}
.item1_row3 {
flex: 1;
background-color: #F6F7FF;
margin: 0 10px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
.row3_left {
display: flex;
flex-direction: column;
gap: 8px;
.row3_title {
font-size: 14px;
color: #333333;
}
.row3_version {
font-size: 12px;
color: #666666;
}
}
.row3_right {
display: flex;
align-items: center;
.drillIcon {
width: auto;
height: 30px;
}
}
}
.item1_row4 {
flex: 1;
background-color: #F6F7FF;
margin: 0 10px 8px 10px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
.row4_left {
display: flex;
flex-direction: column;
gap: 8px;
.row4_title {
font-size: 14px;
color: #333333;
}
.row4_version {
font-size: 12px;
color: #666666;
}
}
.row4_right {
display: flex;
align-items: center;
.drillIcon {
width: auto;
height: 30px;
}
}
}
}
.block1_item2 {
width: 40%;
height: 100%;
background-color: #fff;
display: flex;
flex-direction: column;
padding: 5px 10px 0 10px;
.item2_row1 {
display: flex;
justify-content: space-between;
align-items: center;
.row1_left {
display: flex;
align-items: center;
gap: 8px;
.colorBlock {
width: 3px;
height: 16px;
background-color: #2E4CD4;
opacity: 1;
}
.title {
font-size: 14px;
font-weight: 500;
color: #333333;
}
}
.timeBtnGroup {
display: flex;
gap: 0;
:global {
.ant-btn {
padding: 4px 10px;
font-size: 12px;
color: #333333;
border: 1px solid #E3E3E3;
height: 28px;
border-radius: 0;
margin-left: -1px;
&:first-child {
margin-left: 0;
border-radius: 4px 0 0 4px;
}
&:last-child {
border-radius: 0 4px 4px 0;
}
&:hover {
opacity: 0.8;
z-index: 1;
}
}
.ant-btn.active {
background: linear-gradient(180deg, #556FEB 0%, #8DAAF7 100%);
color: #fff;
border-color: #556FEB;
z-index: 2;
}
}
}
}
.chartContainer {
flex: 1;
width: 100%;
}
}
.block1_item3 {
flex: 1;
height: 100%;
background: #FFFFFF;
border-radius: 4px;
padding: 5px 10px 0 10px;
display: flex;
flex-direction: column;
.item3_header {
display: flex;
align-items: center;
margin-top: 5px;
.colorBlock {
width: 3px;
height: 16px;
background-color: #2E4CD4;
margin-right: 8px;
}
.title {
font-size: 14px;
font-weight: 500;
color: #333333;
}
}
.chartContainer {
flex: 1;
width: 100%;
}
}
}
.block2 {
width: 100%;
height: 25%;
background-color: pink;
}
.block3 {
width: 100%;
flex: 1;
background-color: pink;
}
}

@ -1,69 +0,0 @@
.container {
background-color: transparent;
width: 100%;
height: 89vh;
overflow: hidden;
display: flex;
flex-direction: column;
.TopButton {
background-color: white;
width: 100%;
padding: 8px 30px 5px 30px;
display: flex;
gap: 24px;
margin-left: 6px;
.TopButtonItem {
background-color: #FFFFFF !important;
color: #999999 !important;
font-family: 'PingFang SC', sans-serif !important;
font-weight: 500 !important;
font-size: 14px !important;
line-height: 100% !important;
border-radius: 8px !important;
padding: 4px 16px !important;
height: auto !important;
border: none !important;
box-shadow: none !important;
position: relative !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 5px !important;
transition: all 0.3s ease !important;
&:hover {
color: #999999 !important;
border: none !important;
}
&:focus {
color: #999999 !important;
border: none !important;
}
&.active {
background: linear-gradient(98.03deg, #00E49C 0.68%, #00D841 98.3%) !important;
box-shadow: 0px 2px 2px 0px #AEEDDE !important;
color: #FFFFFF !important;
&::after {
content: '';
width: 28px;
height: 5px;
background-color: #FFFFFF;
border-radius: 6px;
opacity: 1;
}
}
}
}
.content {
// ======== 内容区域样式 ========
flex: 1; // ======== 占据剩余空间 ========
overflow-y: auto; // ======== 允许垂直滚动 ========
padding: 0; // ======== 无内边距 ========
}
}

@ -1,513 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal, Select } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined, PlusOutlined, UploadOutlined, EditOutlined, DownloadOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './AtmospherePollutantLibrary.less';
import licence1 from '@/assets/business_envinformation/image1.svg';
import licence2 from '@/assets/business_envinformation/image2.svg';
import viewicon from '@/assets/business_envinformation/viewicon.svg';
import editicon from '@/assets/business_envinformation/editicon.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
import icon_add from '@/assets/business_envinformation/icon_add.svg';
const AtmospherePollutantLibrary = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 19,
});
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([
{
key: 1,
serialNumber: 1,
pollutantName: '对乙酰氨基酚栓',
category: 25,
mainFeatures: '在接受调查的19为华尔街分析师...',
monitoringPoint: 1.25,
emittingEnterprise: '每日协通(北京)咨询有限公司',
monthlyEmission: 4.6,
quarterlyEmission: 4.6,
yearlyEmission: 5.0,
},
{
key: 2,
serialNumber: 2,
pollutantName: '萘普生缓释胶囊(适洛特)',
category: 27,
mainFeatures: '热到融化的马路、无穷无尽的野火...',
monitoringPoint: 1.25,
emittingEnterprise: '赢王科技有限公司',
monthlyEmission: 1.1,
quarterlyEmission: 1.1,
yearlyEmission: 1.8,
},
{
key: 3,
serialNumber: 3,
pollutantName: '复方感冒灵片',
category: 44,
mainFeatures: '从病虫害探测、土壤墒情监测智能...',
monitoringPoint: 1.25,
emittingEnterprise: '北京福商商务服务有限公司',
monthlyEmission: 2.4,
quarterlyEmission: 2.4,
yearlyEmission: 5.0,
},
{
key: 4,
serialNumber: 4,
pollutantName: '红药片',
category: 21,
mainFeatures: '近日,有科普博主发帖称,某社交...',
monitoringPoint: 1.25,
emittingEnterprise: '实华国际租赁有限公司',
monthlyEmission: 3.6,
quarterlyEmission: 3.6,
yearlyEmission: 4.7,
},
{
key: 5,
serialNumber: 5,
pollutantName: '布洛芬混悬液(翔宇赛可)',
category: 56,
mainFeatures: '在七八十年代,这种面料做成的服...',
monitoringPoint: 1.25,
emittingEnterprise: '北京冠钧财经策划有限公司',
monthlyEmission: 3.0,
quarterlyEmission: 3.0,
yearlyEmission: 4.7,
},
{
key: 6,
serialNumber: 6,
pollutantName: '阿莫西林胶囊',
category: 32,
mainFeatures: '抗生素类药物,用于治疗细菌感染...',
monitoringPoint: 1.15,
emittingEnterprise: '华北制药集团有限责任公司',
monthlyEmission: 2.8,
quarterlyEmission: 2.8,
yearlyEmission: 3.5,
},
{
key: 7,
serialNumber: 7,
pollutantName: '头孢拉定胶囊',
category: 28,
mainFeatures: '头孢类抗生素,广谱抗菌药物...',
monitoringPoint: 1.30,
emittingEnterprise: '石药集团欧意药业有限公司',
monthlyEmission: 1.9,
quarterlyEmission: 1.9,
yearlyEmission: 2.3,
},
{
key: 8,
serialNumber: 8,
pollutantName: '复方甘草片',
category: 35,
mainFeatures: '镇咳祛痰药物,含有甘草提取物...',
monitoringPoint: 1.20,
emittingEnterprise: '太极集团重庆桐君阁药厂有限公司',
monthlyEmission: 3.2,
quarterlyEmission: 3.2,
yearlyEmission: 4.1,
},
{
key: 9,
serialNumber: 9,
pollutantName: '板蓝根颗粒',
category: 41,
mainFeatures: '清热解毒,凉血利咽的中成药...',
monitoringPoint: 1.10,
emittingEnterprise: '广州白云山和记黄埔中药有限公司',
monthlyEmission: 4.5,
quarterlyEmission: 4.5,
yearlyEmission: 5.8,
},
{
key: 10,
serialNumber: 10,
pollutantName: '维生素C片',
category: 22,
mainFeatures: '补充维生素C增强免疫力...',
monitoringPoint: 1.35,
emittingEnterprise: '华润三九医药股份有限公司',
monthlyEmission: 2.1,
quarterlyEmission: 2.1,
yearlyEmission: 2.7,
},
{
key: 11,
serialNumber: 11,
pollutantName: '感冒清热颗粒',
category: 38,
mainFeatures: '疏风散寒,解表清热的中成药...',
monitoringPoint: 1.25,
emittingEnterprise: '北京同仁堂股份有限公司',
monthlyEmission: 3.7,
quarterlyEmission: 3.7,
yearlyEmission: 4.9,
},
{
key: 12,
serialNumber: 12,
pollutantName: '双氯芬酸钠缓释片',
category: 29,
mainFeatures: '非甾体抗炎药,用于缓解疼痛...',
monitoringPoint: 1.18,
emittingEnterprise: '扬子江药业集团有限公司',
monthlyEmission: 1.6,
quarterlyEmission: 1.6,
yearlyEmission: 2.0,
},
{
key: 13,
serialNumber: 13,
pollutantName: '藿香正气水',
category: 43,
mainFeatures: '解表化湿,理气和中的中成药...',
monitoringPoint: 1.22,
emittingEnterprise: '云南白药集团股份有限公司',
monthlyEmission: 2.9,
quarterlyEmission: 2.9,
yearlyEmission: 3.8,
},
{
key: 14,
serialNumber: 14,
pollutantName: '蒙脱石散',
category: 26,
mainFeatures: '止泻药物,保护胃肠黏膜...',
monitoringPoint: 1.28,
emittingEnterprise: '博福-益普生制药有限公司',
monthlyEmission: 1.4,
quarterlyEmission: 1.4,
yearlyEmission: 1.9,
},
{
key: 15,
serialNumber: 15,
pollutantName: '复方丹参片',
category: 37,
mainFeatures: '活血化瘀,理气止痛的中成药...',
monitoringPoint: 1.16,
emittingEnterprise: '天津中新药业集团股份有限公司',
monthlyEmission: 3.3,
quarterlyEmission: 3.3,
yearlyEmission: 4.2,
},
{
key: 16,
serialNumber: 16,
pollutantName: '奥美拉唑肠溶胶囊',
category: 31,
mainFeatures: '质子泵抑制剂,治疗胃溃疡...',
monitoringPoint: 1.33,
emittingEnterprise: '阿斯利康制药有限公司',
monthlyEmission: 2.2,
quarterlyEmission: 2.2,
yearlyEmission: 2.8,
},
{
key: 17,
serialNumber: 17,
pollutantName: '六味地黄丸',
category: 45,
mainFeatures: '滋阴补肾的经典中成药...',
monitoringPoint: 1.12,
emittingEnterprise: '仲景宛西制药股份有限公司',
monthlyEmission: 4.1,
quarterlyEmission: 4.1,
yearlyEmission: 5.3,
},
{
key: 18,
serialNumber: 18,
pollutantName: '阿司匹林肠溶片',
category: 24,
mainFeatures: '解热镇痛抗炎药,预防血栓...',
monitoringPoint: 1.27,
emittingEnterprise: '拜耳医药保健有限公司',
monthlyEmission: 1.8,
quarterlyEmission: 1.8,
yearlyEmission: 2.4,
},
{
key: 19,
serialNumber: 19,
pollutantName: '复方黄连素片',
category: 39,
mainFeatures: '清热燥湿,行气止痛的中成药...',
monitoringPoint: 1.21,
emittingEnterprise: '哈药集团三精制药有限公司',
monthlyEmission: 2.6,
quarterlyEmission: 2.6,
yearlyEmission: 3.4,
},
]);
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const start = (current - 1) * pageSize;
const end = start + pageSize;
return dataSource.slice(start, end);
};
const columns = [
{
title: (
<input
type="checkbox"
checked={selectedRowKeys.length === getCurrentPageData().length && getCurrentPageData().length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
/>
),
key: 'selection',
width: 60,
align: 'center',
fixed: 'left',
render: (_, record) => (
<input
type="checkbox"
checked={selectedRowKeys.includes(record.key)}
onChange={(e) => {
if (e.target.checked) {
setSelectedRowKeys([...selectedRowKeys, record.key]);
} else {
setSelectedRowKeys(selectedRowKeys.filter(key => key !== record.key));
}
}}
/>
),
},
{
title: '序号',
dataIndex: 'serialNumber',
key: 'serialNumber',
width: 80,
align: 'center',
},
{
title: '特征污染物名称',
dataIndex: 'pollutantName',
key: 'pollutantName',
width: 200,
align: 'center',
},
{
title: '种类',
dataIndex: 'category',
key: 'category',
width: 100,
align: 'center',
},
{
title: '主要特征',
dataIndex: 'mainFeatures',
key: 'mainFeatures',
width: 300,
},
{
title: '环境监测点',
dataIndex: 'monitoringPoint',
key: 'monitoringPoint',
width: 120,
align: 'center',
},
{
title: '排放企业',
dataIndex: 'emittingEnterprise',
key: 'emittingEnterprise',
width: 200,
},
{
title: '本月排放量',
dataIndex: 'monthlyEmission',
key: 'monthlyEmission',
width: 120,
align: 'center',
},
{
title: '本季度排放量',
dataIndex: 'quarterlyEmission',
key: 'quarterlyEmission',
width: 130,
align: 'center',
},
{
title: '本年度排放量',
dataIndex: 'yearlyEmission',
key: 'yearlyEmission',
width: 130,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 140,
align: 'center',
fixed: 'right',
render: (_, record) => (
<Space size={18}>
{/* <img
src={editicon}
alt="编辑"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleEdit(record)}
/>
<img
src={downloadicon}
alt="下载"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDownload(record)}
/> */}
<img
src={deleteicon}
alt="删除"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDownload = (record) => {
console.log('下载:', record);
// TODO: 实现下载功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
const handleAdd = () => {
console.log('新增');
// TODO: 实现新增功能
};
const handleImport = () => {
console.log('导入');
// TODO: 实现导入功能
};
const handleQuery = () => {
console.log('查询');
// TODO: 实现查询功能
};
const handleTableChange = (pagination) => {
setPagination(pagination);
};
// 全选功能
const handleSelectAll = (checked) => {
if (checked) {
const allKeys = getCurrentPageData().map(item => item.key);
setSelectedRowKeys(allKeys);
} else {
setSelectedRowKeys([]);
}
};
// 批量操作
const handleBatchOperation = (operation) => {
console.log(`批量${operation}:`, selectedRowKeys);
// TODO: 实现批量操作功能
};
return (
<div className={styles.atmospherePollutantLibrary}>
{/* 页面头部 */}
<div className={styles.pageHeader}>
大气污染特征污染物名录库
</div>
{/* 第一块:操作按钮和筛选条件 */}
<div className={styles.searchSection}>
<div className={styles.leftButtons}>
<Button
type="primary"
onClick={handleAdd}
className={styles.addButton}
>
<img
src={icon_add}
alt="新增"
style={{ width: 16, height: 16, marginRight: 0 }}
/>
新增
</Button>
<Button
onClick={handleImport}
className={styles.importButton}
>
批量导出
</Button>
</div>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: {
...pagination,
total: dataSource.length,
showTotal: (total) => `${total}`,
showSizeChanger: false,
}
}}
onChange={handleTableChange}
// scroll={{ x: 3000}}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default AtmospherePollutantLibrary;

@ -1,218 +0,0 @@
.atmospherePollutantLibrary {
width: 100%;
height: 100%;
// padding: 20px;
// background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.pageHeader {
margin-bottom: 15px;
background: #fff;
padding: 15px 15px 15px 20px;
border-radius: 2px;
color: #333333;
font-size: 16px;
font-weight: 500;
}
.searchSection {
background: #fff;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
.leftButtons {
display: flex;
gap: 12px;
.addButton {
background-color: #00D48A;
color: #fff;
height: 28px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
&:hover {
background-color: #00D48A;
border-color: #00D48A;
}
}
.importButton {
display: flex;
align-items: center;
background-color: #fff;
border-color: #D7D7D7;
color: #333;
height: 28px;
border-radius: 4px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
}
// .rightControls {
// display: flex;
// align-items: center;
// gap: 12px;
// .filterLabel {
// color: #333;
// font-size: 14px;
// white-space: nowrap;
// }
// .queryButton {
// background-color: #52c41a;
// border-color: #52c41a;
// color: white;
// height: 28px;
// border-radius: 4px;
// display: flex;
// align-items: center;
// justify-content: center;
// &:hover {
// background-color: #73d13d;
// border-color: #73d13d;
// }
// }
// .selectInput {
// :global {
// .ant-select-selector {
// display: flex;
// align-items: center;
// height: 28px !important;
// }
// .ant-select-selection-item {
// display: flex;
// align-items: center;
// line-height: 1;
// }
// .ant-select-selection-placeholder {
// display: flex;
// align-items: center;
// line-height: 1;
// }
// }
// }
// }
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
padding: 0 25px 0;
background-color: #fff;
overflow: hidden; // 只设置垂直隐藏
min-width: 0; // 确保可以收缩
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead>tr>th {
background-color: #FAFAFA;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody>tr>td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody>tr:hover>td {
background-color: #f5f5f5;
}
// 固定列样式
.ant-table-thead>tr>th.ant-table-cell-fix-left,
.ant-table-tbody>tr>td.ant-table-cell-fix-left {
background-color: #FAFAFA;
z-index: 1;
}
.ant-table-thead>tr>th.ant-table-cell-fix-right,
.ant-table-tbody>tr>td.ant-table-cell-fix-right {
background-color: #FAFAFA;
z-index: 1;
}
// 固定列阴影效果
.ant-table-cell-fix-left {
// box-shadow: 0px 0 4px 0px #00000040;
}
.ant-table-cell-fix-right {
// box-shadow: 0px 0 4px 0px #00000040;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
// 页码距离上边距
.ant-pagination {
text-align: right;
margin-top: 70px !important;
}
}
}
}

@ -1,62 +0,0 @@
import React, { useState } from 'react';
import styles from './ComplianceManagement.less';
import PermitManagement from './secondary_menu/PermitManagement'; // 排污许可
import RegulationCompliance from './secondary_menu/RegulationCompliance'; // 法规符合性
import SupervisionInspection from './secondary_menu/SupervisionInspection'; // 监督检查
import InformationDisclosure from './secondary_menu/InformationDisclosure'; // 信息公开及绿色通道
const ComplianceManagement = () => {
const [activeMenu, setActiveMenu] = useState('permit');
const menuItems = [
{ key: 'permit', label: '排污许可' },
{ key: 'regulation', label: '法规符合性' },
{ key: 'inspection', label: '监督检查' },
{ key: 'disclosure', label: '信息公开及绿色通道' }
];
const handleMenuClick = (key) => {
setActiveMenu(key);
};
const renderContent = () => {
switch (activeMenu) {
case 'permit':
return <PermitManagement />;
case 'regulation':
return <RegulationCompliance />;
case 'inspection':
return <SupervisionInspection />;
case 'disclosure':
return <InformationDisclosure />;
default:
return <PermitManagement />;
}
};
return (
<div className={styles.container}>
{/* 左侧菜单 */}
<div className={styles.leftMenu}>
{menuItems.map(item => (
<div
key={item.key}
className={`${styles.menuItem} ${activeMenu === item.key ? styles.active : ''}`}
onClick={() => handleMenuClick(item.key)}
>
{activeMenu === item.key && <div className={styles.activeIndicator}></div>}
<span className={styles.menuText}>{item.label}</span>
</div>
))}
</div>
{/* 右侧内容区 */}
<div className={styles.rightContent}>
{renderContent()}
</div>
</div>
);
};
export default ComplianceManagement;

@ -1,85 +0,0 @@
.container {
width: 100%;
height: 100%;
display: flex;
gap: 10px;
padding-left: 5px;
// padding-right: 5px;
padding-top: 10px;
padding-bottom: 10px;
background-color: #f5f5f5;
// 左侧菜单
.leftMenu {
display: flex;
flex-direction: column;
// gap: 1px;
flex-shrink: 0;
background-color: #fff;
.menuItem {
width: 180px;
height: 50px;
background-color: #FFFFFF;
border-radius: 4px;
display: flex;
align-items: center;
position: relative;
cursor: pointer;
transition: all 0.3s ease;
padding-left: 20px;
.menuText {
font-size: 14px;
color: #999999;
font-weight: 400;
transition: color 0.3s ease;
}
// 激活状态的指示器(左侧长条)
.activeIndicator {
position: absolute;
left: 3px;
width: 17.34765625px;
height: 1.97802734375px;
border-radius: 6px;
background-color: #009D6F;
transform: rotate(-90deg);
}
// 激活状态样式
&.active {
background-color: #D4FFEC;
.menuText {
color: #009D6F;
}
}
// 鼠标悬停效果
&:hover:not(.active) {
background-color: #f9f9f9;
}
}
}
// 右侧内容区
.rightContent {
flex: 1;
// background-color: #FFFFFF;
border-radius: 4px;
// padding: 20px;
overflow: auto;
.contentPlaceholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: #666666;
}
}
}

@ -1,536 +0,0 @@
// 表单输入框样式
.formInput {
:global(.ant-input) {
color: #333333 !important;
font-size: 12px !important;
}
:global(.ant-select-selector) {
color: #333333 !important;
font-size: 12px !important;
}
:global(.ant-picker-input input) {
color: #333333 !important;
font-size: 12px !important;
}
}
.Rcontainer {
padding: 8px 6px 0px 6px;
height: 100%;
display: flex;
flex-direction: column;
gap: 10px;
// 第一个div - 高度20%
.RcontainerTop {
height: 18%;
// background-color: #fff;
border-radius: 4px;
display: flex;
flex-direction: column;
.sectionContent {
height: 100%;
display: flex;
flex-direction: column;
// padding: 15px;
.blocksContainer {
flex: 1;
display: flex;
gap: 10px;
height: 100%;
.blockItem {
flex: 1;
height: 100%;
display: flex;
// background: linear-gradient(170.5deg, #F5F7FF 6.87%, #FFFFFF 47.65%);
border-radius: 4px;
// border: 2px solid #FFFFFF;
// 块1 - 蓝色渐变 + SVG背景
&.block1 {
background:
url('@/assets/business_envinformation/background1.svg'),
linear-gradient(180deg, #DBEBFF 0%, #DBEBFF 12.5%, rgba(255, 255, 255, 0.700824) 56%, rgba(255, 255, 255, 0.01) 100%),
linear-gradient(0deg, #FFFFFF, #FFFFFF);
// linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2));
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 块2 - 黄色渐变
&.block2 {
background:
url('@/assets/business_envinformation/background2.svg'),
linear-gradient(180deg, #FFFEDB 0%, #F5FFDB 19.23%, #FFFFFF 55.77%, #FFFFFF 100%);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 块3 - 绿色渐变
&.block3 {
background:
url('@/assets/business_envinformation/background3.svg'),
linear-gradient(180deg, #8CFFCD 0%, #C0FFE4 12.5%, #FFFFFF 56%, #FFFFFF 100%);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 块4 - 青色渐变
&.block4 {
background:
url('@/assets/business_envinformation/background4.svg'),
linear-gradient(180deg, #C5FFFC 0%, #C0FFFC 12.5%, #FFFFFF 56%, #FFFFFF 100%);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 块5 - 红色渐变
&.block5 {
background:
url('@/assets/business_envinformation/background5.svg'),
linear-gradient(180deg, #FFD2D2 0%, #FFD9D9 12.5%, #FFFFFF 56%, #FFFFFF 100%);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
// 块6 - 紫色渐变
&.block6 {
background:
url('@/assets/business_envinformation/background6.svg'),
linear-gradient(180deg, #F2D7FF 0%, #F4DDFF 12.5%, #FFFFFF 56%, #FFFFFF 100%);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.blockLeft {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
padding: 15px;
padding-left: 20px;
gap: 8px;
.blockTitle {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #333333;
line-height: 1.2;
}
.blockNumber {
font-family: PingFang SC;
font-weight: 700;
font-size: 24px;
color: #333333;
line-height: 1.2;
// 特定数字颜色
&.number258 {
color: #0080FF;
}
&.number58 {
color: #EFB700;
}
&.number51 {
color: #00DA86;
}
&.number28 {
color: #00DA86;
}
&.number50 {
color: #FD0404;
}
&.number58Second {
color: #A318E4;
}
}
.blockTime {
font-family: PingFang SC;
font-weight: 400;
font-size: 10px;
color: #999999;
line-height: 1.2;
}
.blockChange {
font-family: PingFang SC;
font-weight: 400;
font-size: 12px;
color: #1269FF;
line-height: 1.2;
display: flex;
align-items: center;
gap: 4px;
.arrow {
font-size: 14px;
font-weight: bold;
}
.checkIcon {
font-size: 16px;
color: #1269FF;
}
}
}
.blockRight {
flex: 1;
height: 100%;
background-color: transparent;
border-radius: 0 4px 4px 0;
display: flex;
align-items: center;
justify-content: center;
.blockImage {
// width: 80%;
height: 65%;
// height: 80%;
object-fit: contain;
margin-right: -5px;
}
}
}
}
}
}
// 第三个div - 占满剩余位置
.RcontainerBottom {
flex: 1; // 占满剩余空间
display: flex;
flex-direction: column;
background-color: #fff;
padding: 15px;
.sectionContent {
height: 100%;
display: flex;
flex-direction: column;
gap: 15px;
// 第一行 - 表单控件
.formRow {
display: flex;
align-items: center;
gap: 15px;
flex-shrink: 0;
.addButton {
display: flex;
align-items: center;
gap: 4px;
height: 28px;
border: 1px solid #00D48A;
border-radius: 2px;
color: #fff;
font-weight: 400;
font-size: 12px;
padding: 0 10px;
background: #00D48A;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background-color: #00B875;
border-color: #00B875;
}
.buttonIcon {
font-size: 16px;
font-weight: bold;
}
}
.rightControls {
display: flex;
align-items: center;
gap: 15px;
margin-left: auto;
.filterLabel {
font-size: 13px;
color: #333333;
white-space: nowrap;
}
// Select组件样式
:global(.ant-select) {
font-size: 12px;
height: 28px !important;
}
:global(.ant-select .ant-select-selector) {
height: 28px !important;
font-size: 12px;
border-radius: 2px !important;
display: flex !important;
align-items: center !important;
padding: 0 11px !important;
}
:global(.ant-select .ant-select-selection-item) {
line-height: 1.5714285714285714;
font-size: 12px;
}
:global(.ant-select .ant-select-selection-placeholder) {
line-height: 1.5714285714285714;
font-size: 12px;
color: #00000040 !important;
}
.searchInput {
width: 150px;
height: 28px;
border: 1px solid #d9d9d9;
border-radius: 2px;
padding: 0 12px;
font-size: 12px;
&:focus {
border-color: #2E4CD4;
outline: none;
}
&::placeholder {
color: #00000040;
}
}
.queryButton, .resetButton {
height: 28px;
border: 1px solid #d9d9d9;
border-radius: 4px;
padding: 0 16px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
border-color: #2E4CD4;
color: #2E4CD4;
}
}
.queryButton {
background-color: #00D48A;
color: #fff;
border-color: #00D48A;
&:hover {
background-color: #00B875;
border-color: #00B875;
color: #fff;
}
}
.resetButton {
background-color: #fff;
color: #666;
&:hover {
background-color: #f5f5f5;
}
}
}
}
// 第二行 - 表格
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.ant-table {
flex: 1;
overflow: auto;
}
.ant-table-pagination {
flex-shrink: 0;
margin: 16px 0 0 0;
padding: 0;
}
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #fafafa;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
}
}
}
}
}
}
// 操作按钮图标样式
.eye-icon {
width: 20px;
height: 12.5px;
position: relative;
display: inline-block;
&::before {
content: '';
position: absolute;
width: 20px;
height: 12.5px;
border: 2px solid #86F278;
border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
top: 0;
left: 0;
transform: rotate(-180deg);
opacity: 1;
}
&::after {
content: '';
position: absolute;
width: 6px;
height: 6px;
background-color: #86F278;
border-radius: 50%;
top: 3.5px;
left: 7px;
transform: rotate(-180deg);
}
}
.edit-icon {
width: 16px;
height: 16px;
position: relative;
display: inline-block;
&::before {
content: '';
position: absolute;
width: 12px;
height: 2px;
background-color: #1890ff;
top: 3px;
left: 2px;
transform: rotate(45deg);
}
&::after {
content: '';
position: absolute;
width: 2px;
height: 12px;
background-color: #1890ff;
top: 2px;
left: 7px;
transform: rotate(45deg);
}
}
.delete-icon {
width: 16px;
height: 16px;
position: relative;
display: inline-block;
&::before {
content: '';
position: absolute;
width: 12px;
height: 2px;
background-color: #ff4d4f;
top: 7px;
left: 2px;
transform: rotate(45deg);
}
&::after {
content: '';
position: absolute;
width: 12px;
height: 2px;
background-color: #ff4d4f;
top: 7px;
left: 2px;
transform: rotate(-45deg);
}
}

@ -1,58 +0,0 @@
import React, { useState } from 'react';
import { Tabs } from 'antd';
import styles from './EquipmentManagement.less';
// 导入子页面组件
import WasteGasPollutionControl from './secondary_menu/WasteGasPollutionControl';
import WastewaterFacilityManagement from './secondary_menu/WastewaterFacilityManagement';
import ProtectionFacilityMaintenance from './secondary_menu/ProtectionFacilityMaintenance';
const EquipmentManagement = () => {
const [activeTab, setActiveTab] = useState('waste-gas-control');
// 标签页配置
const tabItems = [
{
key: 'waste-gas-control',
label: '废气污染防治信息',
children: <WasteGasPollutionControl />
},
{
key: 'wastewater-facility',
label: '废水设置运行管理',
children: <WastewaterFacilityManagement />
},
{
key: 'protection-facility',
label: '防护设施检维修管理',
children: <ProtectionFacilityMaintenance />
}
];
// 标签页切换处理
const handleTabChange = (key) => {
setActiveTab(key);
};
return (
<div className={styles.container}>
<Tabs
activeKey={activeTab}
onChange={handleTabChange}
items={tabItems}
className={styles.tabs}
style={{
'--ant-tabs-tab-color': '#AFAFAF',
'--ant-tabs-tab-active-color': '#009D6F',
'--ant-tabs-tab-active-bg': '#fff'
}}
tabBarStyle={{
'--ant-tabs-tab-active-color': '#009D6F'
}}
/>
</div>
);
};
export default EquipmentManagement;

@ -1,119 +0,0 @@
.container {
width: 100%;
height: 100%;
padding: 16px;
// background-color: #f5f5f5;
.tabs {
height: 100%;
background-color: transparent;
border-radius: 8px;
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
:global(.ant-tabs-nav) {
margin: 0;
padding: 0 0px;
background-color: transparent;
border-bottom: none;
}
:global(.ant-tabs-tab) {
padding: 16px 24px !important;
font-size: 14px !important;
font-weight: 400 !important;
color: #AFAFAF !important;
background: transparent !important;
border: none !important;
position: relative;
&:hover {
color: #AFAFAF !important;
background-color: transparent !important;
}
&.ant-tabs-tab-active {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
}
// 额外的全局样式覆盖,确保优先级足够高
:global(.ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// 更强的选择器优先级
:global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// 针对可能的嵌套结构
:global(.ant-tabs-nav .ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// // 覆盖 Ant Design 5.x 的高优先级样式
// :global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
// color: #009D6F !important;
// text-shadow: none !important;
// }
// 使用更高优先级的选择器
:global(.ant-tabs.ant-tabs-top .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 针对 CSS 模块的覆盖
:global(.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 最高优先级覆盖
:global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 覆盖Ant Design的默认下划线
:global(.ant-tabs-ink-bar) {
background: none !important;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%) rotate(180deg);
width: 38.36132812500014px;
height: 3.3613271713256965px;
background-color: #009D6F;
opacity: 1;
border-radius: 2px;
z-index: 1;
}
}
:global(.ant-tabs-content-holder) {
height: calc(100% - 60px);
// padding: 20px;
.ant-tabs-content {
height: 100%;
.ant-tabs-tabpane {
height: 100%;
}
}
}
}
}

@ -1,57 +0,0 @@
import React, { useState } from 'react';
import { Tabs } from 'antd';
import styles from './EvaluationReport.less';
// 导入子页面组件
import PermitStatistics from './secondary_menu/PermitStatistics';
import EnvironmentalTaskList from './secondary_menu/EnvironmentalTaskList';
import DischargePermitManagement from './secondary_menu/DischargePermitManagement';
const EvaluationReport = () => {
const [activeTab, setActiveTab] = useState('permit-statistics');
// 标签页配置
const tabItems = [
{
key: 'permit-statistics',
label: '许可证信息统计表',
children: <PermitStatistics />
},
{
key: 'environmental-task-list',
label: '环保管理任务清单',
children: <EnvironmentalTaskList />
},
{
key: 'discharge-permit-management',
label: '排污许可执行管理',
children: <DischargePermitManagement />
}
];
// 标签页切换处理
const handleTabChange = (key) => {
setActiveTab(key);
};
return (
<div className={styles.container}>
<Tabs
activeKey={activeTab}
onChange={handleTabChange}
items={tabItems}
className={styles.tabs}
style={{
'--ant-tabs-tab-color': '#AFAFAF',
'--ant-tabs-tab-active-color': '#009D6F',
'--ant-tabs-tab-active-bg': '#fff'
}}
tabBarStyle={{
'--ant-tabs-tab-active-color': '#009D6F'
}}
/>
</div>
);
};
export default EvaluationReport;

@ -1,119 +0,0 @@
.container {
width: 100%;
height: 100%;
padding: 16px;
// background-color: #f5f5f5;
.tabs {
height: 100%;
background-color: transparent;
border-radius: 8px;
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
:global(.ant-tabs-nav) {
margin: 0;
padding: 0 0px;
background-color: transparent;
border-bottom: none;
}
:global(.ant-tabs-tab) {
padding: 16px 24px !important;
font-size: 14px !important;
font-weight: 400 !important;
color: #AFAFAF !important;
background: transparent !important;
border: none !important;
position: relative;
&:hover {
color: #AFAFAF !important;
background-color: transparent !important;
}
&.ant-tabs-tab-active {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
}
// 额外的全局样式覆盖,确保优先级足够高
:global(.ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// 更强的选择器优先级
:global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// 针对可能的嵌套结构
:global(.ant-tabs-nav .ant-tabs-tab.ant-tabs-tab-active) {
color: #009D6F !important;
background-color: #fff !important;
border-bottom: none !important;
}
// // 覆盖 Ant Design 5.x 的高优先级样式
// :global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
// color: #009D6F !important;
// text-shadow: none !important;
// }
// 使用更高优先级的选择器
:global(.ant-tabs.ant-tabs-top .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 针对 CSS 模块的覆盖
:global(.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 最高优先级覆盖
:global(.ant-tabs .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn) {
color: #009D6F !important;
text-shadow: none !important;
}
// 覆盖Ant Design的默认下划线
:global(.ant-tabs-ink-bar) {
background: none !important;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%) rotate(180deg);
width: 38.36132812500014px;
height: 3.3613271713256965px;
background-color: #009D6F;
opacity: 1;
border-radius: 2px;
z-index: 1;
}
}
:global(.ant-tabs-content-holder) {
height: calc(100% - 60px);
// padding: 20px;
.ant-tabs-content {
height: 100%;
.ant-tabs-tabpane {
height: 100%;
}
}
}
}
}

@ -1,716 +0,0 @@
import React, { useEffect, useRef, useState } from 'react';
import { Card, Result, Select, Button } from 'antd';
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';
import alarm1 from '@/assets/safe_majorHazard/online_monitoring/alarm1.png';
import alarm2 from '@/assets/safe_majorHazard/online_monitoring/alarm2.png';
import alarm3 from '@/assets/safe_majorHazard/online_monitoring/alarm3.png';
import exportIcon from '@/assets/safe_majorHazard/online_monitoring/export.png';
import deleteIcon from '@/assets/safe_majorHazard/online_monitoring/delete.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) {
const chart = echarts.init(chartRef.current);
const option = {
color: ['#04A7F3', '#E7C42C', '#EC6941'],
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: ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00', '24:00'],
axisLabel: {
fontSize: 10
}
},
yAxis: {
type: 'value',
min: 0,
max: 500,
axisLabel: {
formatter: '{value}',
fontSize: 10
}
},
series: [
{
name: '液位',
type: 'line',
smooth: true,
lineStyle: {
width: 1.5,
color: '#04A7F3'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(4, 167, 243, 0.3)' },
{ offset: 1, color: 'rgba(4, 167, 243, 0)' }
]
}
},
symbol: 'none', // 不显示数据点
data: [120, 200, 150, 300, 250, 400, 350, 280, 320, 180, 220, 160, 140]
},
{
name: '温度',
type: 'line',
smooth: true,
lineStyle: {
width: 1.5,
color: '#E7C42C'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(231, 196, 44, 0.3)' },
{ offset: 1, color: 'rgba(231, 196, 44, 0)' }
]
}
},
symbol: 'none',
data: [80, 120, 100, 180, 160, 220, 200, 150, 170, 90, 110, 85, 75]
},
{
name: '压力',
type: 'line',
smooth: true,
lineStyle: {
width: 1.5,
color: '#EC6941'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{ offset: 0, color: 'rgba(236, 105, 65, 0)' },
{ offset: 1, color: 'rgba(236, 105, 65, 0.3)' }
]
}
},
symbol: 'none',
data: [200, 300, 250, 450, 400, 430, 480, 420, 480, 280, 320, 260, 240]
}
]
};
chart.setOption(option);
// 响应式调整 - 使用ResizeObserver监听容器尺寸变化
let resizeTimer = null;
const handleResize = () => {
// 防抖处理避免频繁调用resize
if (resizeTimer) {
clearTimeout(resizeTimer);
}
resizeTimer = setTimeout(() => {
chart.resize();
}, 100);
};
// 监听窗口大小变化
window.addEventListener('resize', handleResize);
// 监听容器尺寸变化(解决菜单栏伸缩时的自适应问题)
let resizeObserver = null;
if (window.ResizeObserver) {
resizeObserver = new ResizeObserver(() => {
// 使用setTimeout确保DOM更新完成后再调整图表
setTimeout(() => {
handleResize();
}, 0);
});
resizeObserver.observe(chartRef.current);
}
return () => {
window.removeEventListener('resize', handleResize);
if (resizeObserver) {
resizeObserver.disconnect();
}
if (resizeTimer) {
clearTimeout(resizeTimer);
}
chart.dispose();
};
}
}, []);
// 表格列定义
const columns = [
{
title: '编号',
dataIndex: 'id',
key: 'id',
width: 80,
render: (text, record, index) => {
const page = pagination.current || 1;
const pageSize = pagination.pageSize || 5;
const number = (page - 1) * pageSize + index + 1;
return `0${number}`.slice(-2);
}
},
{
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: '王五',
},
{
key: '6',
id: '006',
alarmTime: '2024-01-15 13:25:15',
sensorName: 'LNG管道',
alarmType: '流量异常',
alarmContent: '管道流量异常波动',
priority: '中',
status: '未处理',
processTime: '-',
processor: '-',
},
{
key: '7',
id: '007',
alarmTime: '2024-01-15 14:10:30',
sensorName: 'LNG储罐',
alarmType: '温度异常',
alarmContent: '储罐温度异常升高',
priority: '高',
status: '处理中',
processTime: '2024-01-15 14:15:00',
processor: '赵六',
},
{
key: '8',
id: '008',
alarmTime: '2024-01-15 15:45:20',
sensorName: 'LNG管道',
alarmType: '压力超限',
alarmContent: '管道压力超过安全阈值',
priority: '高',
status: '已处理',
processTime: '2024-01-15 16:00:00',
processor: '孙七',
},
{
key: '9',
id: '009',
alarmTime: '2024-01-15 16:30:45',
sensorName: 'LNG储罐',
alarmType: '液位超限',
alarmContent: '储罐液位超过警戒线',
priority: '中',
status: '未处理',
processTime: '-',
processor: '-',
},
{
key: '10',
id: '010',
alarmTime: '2024-01-15 17:15:10',
sensorName: 'LNG管道',
alarmType: '泄漏检测',
alarmContent: '检测到轻微气体泄漏',
priority: '低',
status: '已处理',
processTime: '2024-01-15 17:30:00',
processor: '周八',
},
{
key: '11',
id: '011',
alarmTime: '2024-01-15 18:20:35',
sensorName: 'LNG储罐',
alarmType: '设备故障',
alarmContent: '储罐阀门异常关闭',
priority: '高',
status: '处理中',
processTime: '2024-01-15 18:25:00',
processor: '吴九',
},
{
key: '12',
id: '012',
alarmTime: '2024-01-15 19:05:50',
sensorName: 'LNG管道',
alarmType: '温度异常',
alarmContent: '管道温度异常下降',
priority: '中',
status: '未处理',
processTime: '-',
processor: '-',
},
];
// 初始化数据
useEffect(() => {
setPagination(prev => ({ ...prev, total: mockData.length }));
}, []);
// 根据分页获取当前页数据
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const startIndex = (current - 1) * pageSize;
const endIndex = startIndex + pageSize;
return mockData.slice(startIndex, endIndex);
};
// 表格选择变化
const onSelectChange = (newSelectedRowKeys, newSelectedRows) => {
setSelectedRowKeys(newSelectedRowKeys);
setSelectedRows(newSelectedRows);
};
// 分页变化处理
const handleTableChange = (pagination) => {
setPagination(prev => ({
...prev,
current: pagination.current,
pageSize: pagination.pageSize,
}));
};
// 导出功能
const handleExport = () => {
console.log('导出数据');
// 这里可以添加导出逻辑
};
// 批量删除功能
const handleBatchDelete = () => {
if (selectedRowKeys.length === 0) {
console.log('没有选中任何行');
// 可以在这里添加提示用户选择行的逻辑
return;
}
console.log('批量删除', selectedRowKeys);
// 这里可以添加批量删除逻辑
};
return (
<div className={styles.Ocontainer}>
<div className={styles.OcontainerTop}>
<div className={styles.OcontainerTopLeft}>
<div className={styles.OcontainerTopLeftTop}>
<div className={styles.alarmO}>
<div className={styles.alarmOLeft}>
<img style={{ width: 58, height: 47 }} src={alarm0} alt='alarm0' />
</div>
<div className={styles.alarmORight}>
<div className={styles.alarmORightText1}>总报警</div>
<div className={styles.alarmORightText2}>1456</div>
<div className={styles.alarmORightText3}>
<div>
未处理 <text style={{ color: '#FF4D4F' }}>6</text>
</div>
<div>
处理中 <text style={{ color: '#2e4cd4' }}>10</text>
</div>
</div>
</div>
</div>
<div className={styles.alarmTw}>
<div className={styles.alarmTwLeft}>
<img style={{ width: 58, height: 47 }} src={alarm1} alt='alarm1' />
</div>
<div className={styles.alarmTwRight}>
<div className={styles.alarmTwRightText1}>一级报警</div>
<div className={styles.alarmTwRightText2}>357</div>
<div className={styles.alarmTwRightText3}>
<div>
未处理 <text style={{ color: '#FF4D4F' }}>6</text>
</div>
<div>
处理中 <text style={{ color: '#2e4cd4' }}>10</text>
</div>
</div>
</div>
</div>
<div className={styles.alarmTh}>
<div className={styles.alarmThLeft}>
<img style={{ width: 58, height: 47 }} src={alarm2} alt='alarm2' />
</div>
<div className={styles.alarmThRight}>
<div className={styles.alarmThRightText1}>二级报警</div>
<div className={styles.alarmThRightText2}>401</div>
<div className={styles.alarmThRightText3}>
<div>
未处理 <text style={{ color: '#FF4D4F' }}>6</text>
</div>
<div>
处理中 <text style={{ color: '#2e4cd4' }}>10</text>
</div>
</div>
</div>
</div>
<div className={styles.alarmF}>
<div className={styles.alarmFLeft}>
<img style={{ width: 58, height: 47 }} src={alarm3} alt='alarm3' />
</div>
<div className={styles.alarmFRight}>
<div className={styles.alarmFRightText1}>三级报警</div>
<div className={styles.alarmFRightText2}>556</div>
<div className={styles.alarmFRightText3}>
<div>
未处理 <text style={{ color: '#FF4D4F' }}>6</text>
</div>
<div>
处理中 <text style={{ color: '#2e4cd4' }}>10</text>
</div>
</div>
</div>
</div>
</div>
<div className={styles.OcontainerTopLeftBottom}>
<div className={styles.OcontainerTopLeftBottomTitle}>
<div className={styles.titleLeft}>
<div className={styles.titleIcon}></div>
<div>预警看板</div>
</div>
<div className={styles.titleRight}>
<div>检测对象</div>
<Select
style={{ width: 80 }}
defaultValue="储罐"
options={[
{ value: '储罐', label: '储罐' },
{ value: '管道', label: '管道' },
{ value: '设备', label: '设备' }
]}
/>
</div>
</div>
<div className={styles.OcontainerTopLeftBottomChart} ref={chartRef}>
</div>
</div>
</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"
onClick={handleExport}
style={{ marginRight: 8 }}
>
<img src={exportIcon} alt="导出" style={{ width: 16, height: 16, margin: '-2px 6px 0 0px'}} />
导出word 报告
</Button>
<Button
type="primary"
onClick={handleBatchDelete}
>
<img src={deleteIcon} alt="删除" style={{ width: 16, height: 16, margin: '-2px 6px 0 0px' }} />
批量删除
</Button>
</div>
</div>
{/* 表格 5行10列 带页码 每页5条数据 */}
<div className={styles.tableContainer}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: pagination
}}
loading={loading}
selectionType="checkbox"
onSelectRow={onSelectChange}
onChange={handleTableChange}
pagination={{
...pagination,
showSizeChanger: false,
showQuickJumper: true,
showTotal: (total, range) =>
`${total}`,
}}
scroll={{ x: 1200 }}
/>
</div>
</div>
</div>
);
};
export default OnlineMonitoring;

@ -1,919 +0,0 @@
.Ocontainer {
padding: 8px 6px 0px 6px;
height: 100%;
display: flex;
flex-direction: column;
.OcontainerTop {
display: flex;
height: 50%;
margin-bottom: 5px;
.OcontainerTopLeft {
width: 72%;
height: 100%;
// background-color: pink;
margin-right: 10px;
// display: flex;
.OcontainerTopLeftTop {
width: 100%;
height: 35%;
display: flex;
gap: 12px;
.alarmO {
flex: 1;
height: 100%;
background-color: #F4F7FF;
border: 1px solid #AED3FF;
border-bottom: 0px solid #AED3FF;
border-radius: 4px;
box-shadow: 0px 2px 31px 0px #5382FE33 inset;
display: flex;
.alarmOLeft {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.alarmORight {
flex: 1;
width: 35%;
height: 100%;
display: flex;
flex-direction: column;
margin-left: 2px;
gap: 18px;
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 100%;
letter-spacing: 0%;
color: #333333;
.alarmORightText1 {
margin-top: 15px;
}
.alarmORightText2 {
font-weight: 700;
font-size: 16px;
}
.alarmORightText3 {
display: flex;
gap: 22px;
}
}
}
.alarmTw {
flex: 1;
height: 100%;
background-color: #FFF5f4;
border: 1px solid #FFC5BC;
border-bottom: 0px solid #FFC5BC;
border-radius: 4px;
box-shadow: 0px 2px 31px 0px #FE5F4C33 inset;
display: flex;
.alarmTwLeft {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.alarmTwRight {
flex: 1;
width: 35%;
height: 100%;
display: flex;
flex-direction: column;
margin-left: 2px;
gap: 18px;
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 100%;
letter-spacing: 0%;
color: #333333;
.alarmTwRightText1 {
margin-top: 15px;
}
.alarmTwRightText2 {
font-weight: 700;
font-size: 16px;
}
.alarmTwRightText3 {
display: flex;
gap: 22px;
}
}
}
.alarmTh {
flex: 1;
height: 100%;
background-color: #FFF7F2;
border: 1px solid #FFD9B2;
border-bottom: 0px solid #FFD9B2;
border-radius: 4px;
box-shadow: 0px 2px 31px 0px #FD883C33 inset;
display: flex;
.alarmThLeft {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.alarmThRight {
flex: 1;
width: 35%;
height: 100%;
display: flex;
flex-direction: column;
margin-left: 2px;
gap: 18px;
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 100%;
letter-spacing: 0%;
color: #333333;
.alarmThRightText1 {
margin-top: 15px;
}
.alarmThRightText2 {
font-weight: 700;
font-size: 16px;
}
.alarmThRightText3 {
display: flex;
gap: 22px;
}
}
}
.alarmF {
flex: 1;
height: 100%;
background-color: #EFF9FF;
border: 1px solid #89E1FF;
border-bottom: 0px solid #89E1FF;
border-radius: 4px;
box-shadow: 0px 2px 31px 0px #22A4FD33 inset;
display: flex;
.alarmFLeft {
width: 35%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.alarmFRight {
flex: 1;
width: 35%;
height: 100%;
display: flex;
flex-direction: column;
margin-left: 2px;
gap: 18px;
font-family: PingFang SC;
font-weight: 400;
font-style: Regular;
font-size: 12px;
line-height: 100%;
letter-spacing: 0%;
color: #333333;
.alarmFRightText1 {
margin-top: 15px;
}
.alarmFRightText2 {
font-weight: 700;
font-size: 16px;
}
.alarmFRightText3 {
display: flex;
gap: 22px;
}
}
}
}
.OcontainerTopLeftBottom {
margin-top: 12px;
background-color: #fff;
width: 100%;
height: 60%;
.OcontainerTopLeftBottomTitle {
display: flex;
justify-content: space-between;
align-items: center;
// padding: 8px 15px;
padding: 8px 15px 0px 15px;
.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;
}
}
.titleRight {
display: flex;
align-items: center;
gap: 8px;
font-family: PingFang SC;
font-style: Medium;
font-size: 13px;
line-height: 100%;
letter-spacing: 0%;
.selectBox {
padding: 4px 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
background-color: #fff;
font-size: 12px;
color: #333;
outline: none;
&:focus {
border-color: #2E4CD4;
}
}
}
}
.OcontainerTopLeftBottomChart {
flex: 1;
width: 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: #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: 14px;
color: #333333;
.titleIcon {
width: 3px;
height: 16px;
background-color: #2E4CD4;
}
}
.tableActions {
display: flex;
gap: 8px;
// 自定义按钮样式
:global(.ant-btn) {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
&:hover {
background-color: #f5f5f5 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:focus {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:active {
background-color: #e6e6e6 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
// 主要按钮样式
&.ant-btn-primary {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
&:hover {
background-color: #f5f5f5 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:focus {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:active {
background-color: #e6e6e6 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
}
// 危险按钮样式
&.ant-btn-dangerous {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
&:hover {
background-color: #f5f5f5 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:focus {
background-color: #ffffff !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
&:active {
background-color: #e6e6e6 !important;
border-color: #DFE4F6 !important;
color: #333333 !important;
box-shadow: none !important;
}
}
// 禁用状态
&:disabled {
background-color: #f5f5f5 !important;
border-color: #d9d9d9 !important;
color: #bfbfbf !important;
box-shadow: none !important;
}
}
}
}
.tableContainer {
flex: 1;
overflow: hidden;
:global(.ant-table) {
font-size: 12px;
}
:global(.ant-table-thead > tr > th) {
background-color: #f5f5fa;
font-weight: 500;
font-size: 14px;
color: #333333;
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;
}
}
}
}

@ -1,656 +0,0 @@
import React, { useState, useEffect, useRef } from 'react';
import { Select, Button, Table, Input, Space, Tooltip, message } from 'antd';
import { SearchOutlined, PlusOutlined, FileTextOutlined, DeleteOutlined, EditOutlined, MoreOutlined, RobotOutlined } from '@ant-design/icons';
import ReactECharts from 'echarts-for-react';
import { history } from 'umi';
import StandardTable from '@/components/StandardTable';
import styles from './PollutionSourceManagement.less';
import icon_water from '@/assets/business_envinformation/icon_water.svg';
import icon_soil from '@/assets/business_envinformation/icon_soil.svg';
import icon_factory from '@/assets/business_envinformation/icon_atmosphere.svg';
const { Option } = Select;
const PollutionSourceManagement = () => {
const [loading, setLoading] = useState(false);
const [chartReady, setChartReady] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [tableData, setTableData] = useState({
list: [],
pagination: {
current: 1,
pageSize: 5,
total: 85
}
});
// 确保DOM准备好后再渲染图表
useEffect(() => {
const timer = setTimeout(() => {
setChartReady(true);
}, 100);
return () => clearTimeout(timer);
}, []);
// 污染物排放统计图表配置 - 闭合环图+进度饼图
const pollutantEmissionOption = {
tooltip: {
show: false
},
series: [
// 外层闭合环图
{
name: '外层环',
type: 'pie',
radius: ['58%', '80%'],
center: ['50%', '50%'],
data: [{ value: 100, name: '外层环' }],
itemStyle: {
color: '#F6F1E8',
shadowBlur: 4,
shadowColor: '#FFF5F0',
shadowOffsetY: 4,
borderRadius: 10,
borderColor: 'rgba(255, 227, 208, 0.6)', // 外边框颜色
borderWidth: 2
},
label: { show: false },
labelLine: { show: false },
silent: true
},
// 内层进度饼图
{
name: '进度饼图',
type: 'pie',
radius: ['61%', '77%'],
center: ['50%', '50%'],
data: [
{
value: 62,
name: '超标污染物数量',
itemStyle: {
color: {
type: 'linear',
x: 0, y: 0, x2: 1, y2: 1,
colorStops: [
{ offset: 0, color: '#FFF4B3' },
{ offset: 0.5, color: '#FF8351' },
{ offset: 1, color: '#FF7125' }
]
},
borderRadius: 10
}
},
{
value: 38,
name: '剩余',
itemStyle: { color: 'transparent' }
}
],
label: { show: false },
labelLine: { show: false },
silent: true
}
]
};
// 超标污染物种类统计图表配置 - 闭合环图+进度饼图
const pollutantTypeOption = {
tooltip: {
show: false
},
series: [
// 外层闭合环图
{
name: '外层环',
type: 'pie',
radius: ['58%', '80%'],
center: ['50%', '50%'],
data: [{ value: 100, name: '外层环' }],
itemStyle: {
color: '#F2F0FF',
shadowBlur: 4,
shadowColor: '#F2F0FF',
shadowOffsetY: 4,
borderRadius: 10,
borderColor: '#E4E1FB', // 外边框颜色
borderWidth: 2
},
label: { show: false },
labelLine: { show: false },
silent: true
},
// 内层进度饼图
{
name: '进度饼图',
type: 'pie',
radius: ['61%', '77%'],
center: ['50%', '50%'],
data: [
{
value: 25,
name: '超标污染物种类',
itemStyle: {
color: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: '#B3D6FF' },
{ offset: 0.476, color: '#9E7DFF' },
{ offset: 1, color: '#2549FF' }
]
},
borderRadius: 10
}
},
{
value: 75,
name: '剩余',
itemStyle: { color: 'transparent' }
}
],
label: { show: false },
labelLine: { show: false },
silent: true
}
]
};
// 超标排放统计图表配置
const exceedanceOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
const data = params[0];
const exceedanceData = [
{ name: '污染物1', status: '轻微超标', exceedance: '15%' },
{ name: '污染物2', status: '严重超标', exceedance: '66%' },
{ name: '污染物3', status: '轻微超标', exceedance: '8%' },
{ name: '污染物4', status: '正常', exceedance: '0%' },
{ name: '污染物5', status: '轻微超标', exceedance: '12%' }
];
const item = exceedanceData[data.dataIndex];
return `
<div style=" background: #fff; color: #000000; border-radius: 8px;">
<div style="font-weight: 600; display: inline-block; margin-right: 10px;">${data.name}</div>
<div style="color: #ff6b6b; display: inline-block; margin-bottom: 5px;">${item.status}</div>
<div style="color: #000000; margin-bottom: 5px;">超标 ${item.exceedance}</div>
<div style="color: #000000; font-size: 12px;">大气环境特征污染物</div>
</div>
`;
}
},
grid: {
left: '12%',
right: '5%',
top: '5%',
bottom: '12%'
},
xAxis: {
type: 'value',
max: 100,
min: 0,
interval: 10,
splitNumber: 10,
axisLine: {
show: true,
lineStyle: {
color: '#D7D6D6',
width: 1
}
},
axisTick: {
show: true,
lineStyle: {
color: '#D7D6D6'
}
},
axisLabel: {
color: '#666',
formatter: function (value) {
return value;
}
},
splitLine: {
show: true,
lineStyle: {
color: '#f0f0f0',
type: 'dashed'
}
}
},
yAxis: {
type: 'category',
data: ['污染物1', '污染物2', '污染物3', '污染物4', '污染物5'],
axisLine: {
show: true,
lineStyle: {
color: '#D7D6D6'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#666',
fontSize: 12
}
},
series: [{
type: 'bar',
data: [45, 66, 32, 28, 38],
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [{
offset: 0, color: '#FFEBD9'
}, {
offset: 1, color: '#FF0000'
}]
},
// borderRadius: [0, 4, 0, 0]
},
barWidth: '60%',
barCategoryGap: '20px'
}]
};
// 表格列定义
const columns = [
{
title: '生产工艺设备',
dataIndex: 'equipment',
key: 'equipment',
width: 120,
},
{
title: '原材料产品',
dataIndex: 'material',
key: 'material',
width: 150,
},
{
title: '污染物排放处理设施',
dataIndex: 'facility',
key: 'facility',
width: 180,
},
{
title: '污染物排放种类',
dataIndex: 'type',
key: 'type',
width: 150,
render: (text) => (
<Space>
{text}
{/* <SearchOutlined style={{ color: '#1890ff', cursor: 'pointer' }} /> */}
</Space>
),
},
{
title: '排放数量',
dataIndex: 'quantity',
key: 'quantity',
width: 100,
},
{
title: '数量单位',
dataIndex: 'unit',
key: 'unit',
width: 100,
},
{
title: '排放方式',
dataIndex: 'method',
key: 'method',
width: 100,
},
{
title: '趋向',
dataIndex: 'trend',
key: 'trend',
width: 200,
ellipsis: true,
},
{
title: '操作',
key: 'action',
width: 80,
render: (_, record) => (
<Space size="middle">
<Tooltip title="删除">
<DeleteOutlined
style={{ color: '#ff4d4f', cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Tooltip>
</Space>
),
},
];
// 模拟表格数据
const mockTableData = [
{
key: '1',
equipment: '比亚迪',
material: '丁硼乳膏(雅皓)',
facility: '净水设备234',
type: '种类1',
quantity: 47,
unit: 'm³',
method: '方式1',
trend: '近3年下达中央预算内投'
},
{
key: '2',
equipment: '荣威',
material: '东方活血膏(明仁)',
facility: '净水设备234',
type: '种类1',
quantity: 34,
unit: 'm³',
method: '方式1',
trend: '近3年下达中央预算内投'
},
{
key: '3',
equipment: '现代',
material: '骨友灵搽剂(太极)',
facility: '净水设备234',
type: '种类1',
quantity: 45,
unit: 'm³',
method: '方式1',
trend: '刘某及同伴三人前往该射'
},
{
key: '4',
equipment: '日产',
material: '对乙酰氨基酚栓',
facility: '净水设备234',
type: '种类1',
quantity: 55,
unit: 'm³',
method: '方式1',
trend: '一到假期,大量"xx暑假'
},
{
key: '5',
equipment: '北汽',
material: '对乙酰氨基酚片(必理通)',
facility: '净水设备234',
type: '种类1',
quantity: 22,
unit: 'm³',
method: '方式1',
trend: '近日,陕西延安培文实验'
},
{
key: '6',
equipment: '吉利',
material: '阿莫西林胶囊(联邦)',
facility: '污水处理设备001',
type: '种类2',
quantity: 38,
unit: 'kg',
method: '方式2',
trend: '环保部门加强监管力度,排放标准逐步提高'
},
{
key: '7',
equipment: '长城',
material: '布洛芬缓释胶囊(芬必得)',
facility: '废气处理设备002',
type: '种类3',
quantity: 29,
unit: 't',
method: '方式3',
trend: '企业积极响应绿色生产号召,投入环保设施'
},
{
key: '8',
equipment: '奇瑞',
material: '复方甘草片(太极)',
facility: '固废处理设备003',
type: '种类4',
quantity: 15,
unit: 'm³',
method: '方式4',
trend: '定期进行环境监测,确保排放达标'
}
];
useEffect(() => {
setTableData({
list: mockTableData,
pagination: {
current: 6,
pageSize: 5,
total: 85
}
});
}, []);
// 处理删除操作
const handleDelete = (record) => {
message.success(`删除 ${record.equipment} 成功`);
};
// 处理新增操作
const handleAdd = () => {
message.info('新增功能开发中');
};
// 处理生成报表操作
const handleGenerateReport = () => {
message.info('生成报表功能开发中');
};
// 处理表格变化
const handleTableChange = (pagination) => {
setTableData(prev => ({
...prev,
pagination: {
...prev.pagination,
current: pagination.current,
pageSize: pagination.pageSize
}
}));
};
// 处理大气环境点击
const handleAtmosphereCardClick = () => {
history.push('/topnavbar00/business/atmospherePollutantLibrary');
};
return (
<div className={styles.pollutionDashboard}>
{/* 顶部统计区域 */}
<div className={styles.statsSection}>
{/* 污染物排放统计 */}
<div className={styles.pollutantStatsCard}>
<div className={styles.cardTitle}>
<span>污染物排放统计</span>
<div className={styles.cardHeader}>
<Select defaultValue="今日" className={styles.timeFilter}>
<Option value="今日">今日</Option>
<Option value="本周">本周</Option>
<Option value="本月">本月</Option>
</Select>
<Select defaultValue="所有名录" className={styles.categoryFilter}>
<Option value="所有名录">所有名录</Option>
<Option value="大气环境">大气环境</Option>
<Option value="水环境">水环境</Option>
</Select>
</div>
</div>
<div className={styles.chartsContainer}>
<div className={styles.pieChartContainer}>
{/* <div className={styles.chartTitle}>超标污染物数量</div> */}
{chartReady && (
<ReactECharts
option={pollutantEmissionOption}
style={{ height: '100%', width: '100%' }}
opts={{ renderer: 'canvas' }}
/>
)}
<div className={styles.chartCenterContent}>
<div className={styles.chartValue}>62%</div>
<div className={styles.chartLabel}>超标污染物数量</div>
</div>
</div>
<div className={styles.pieChartContainer}>
{/* <div className={styles.chartTitle}>超标污染物种类</div> */}
{chartReady && (
<ReactECharts
option={pollutantTypeOption}
style={{ height: '100%', width: '100%' }}
opts={{ renderer: 'canvas' }}
/>
)}
<div className={styles.chartCenterContent}>
<div className={styles.chartValue}>25%</div>
<div className={styles.chartLabel}>超标污染物种类</div>
</div>
</div>
</div>
</div>
{/* 超标排放统计 */}
<div className={styles.exceedanceStatsCard}>
<div className={styles.cardHeader}>
<div className={styles.cardTitle}>超标排放统计</div>
<div className={styles.filterGroup}>
<Select defaultValue="今日" className={styles.exceedanceTimeFilter}>
<Option value="今日">今日</Option>
<Option value="本周">本周</Option>
<Option value="本月">本月</Option>
</Select>
<Select defaultValue="所有名录" className={styles.exceedanceCategoryFilter}>
<Option value="所有名录">所有名录</Option>
<Option value="大气环境">大气环境</Option>
<Option value="水环境">水环境</Option>
</Select>
</div>
</div>
<div className={styles.barChartContainer}>
{chartReady && (
<ReactECharts
option={exceedanceOption}
style={{ height: '200px', width: '100%' }}
opts={{ renderer: 'canvas' }}
/>
)}
</div>
</div>
{/* 环境分类卡片 */}
<div className={styles.environmentalCategories}>
<div className={styles.categoryCard1} onClick={handleAtmosphereCardClick}>
<div className={styles.airPollutionText}>AIR POLLUSION</div>
<div className={styles.categoryContent}>
<div className={styles.categoryInfo}>
<div className={styles.titleContainer}>
<div className={`${styles.categoryTitle} ${styles.atmosphereGradient}`}>大气环境</div>
<div className={`${styles.categoryTitle} ${styles.atmosphereMirror}`}>大气环境</div>
</div>
<div className={`${styles.categorySubtitle} ${styles.pollutantSubtitle}`}>特征污染物名录库</div>
</div>
<img className={styles.categoryIcon} src={icon_factory} alt="icon_factory" />
</div>
</div>
<div className={styles.categoryCard2}>
<div className={styles.waterPollutionText}>WATER POLLUSION</div>
<div className={styles.categoryContent}>
<div className={styles.categoryInfo}>
<div className={styles.titleContainer}>
<div className={`${styles.categoryTitle} ${styles.waterGradient}`}>水环境</div>
<div className={`${styles.categoryTitle} ${styles.waterMirror}`}>水环境</div>
</div>
<div className={`${styles.categorySubtitle} ${styles.pollutantSubtitle}`}>特征污染物名录库</div>
</div>
<img src={icon_water} alt="icon_water" className={styles.categoryIcon} />
</div>
</div>
<div className={styles.categoryCard3}>
<div className={styles.soilPollutionText}>SOILPOLLUSION</div>
<div className={styles.categoryContent}>
<div className={styles.categoryInfo}>
<div className={styles.titleContainer}>
<div className={`${styles.categoryTitle} ${styles.soilGradient}`}>土壤及地下水</div>
<div className={`${styles.categoryTitle} ${styles.soilMirror}`}>土壤及地下水</div>
</div>
<div className={`${styles.categorySubtitle} ${styles.pollutantSubtitle}`}>特征污染物名录库</div>
</div>
<img className={styles.categoryIcon} src={icon_soil} alt="icon_soil" />
</div>
</div>
</div>
</div>
{/* 污染源管理表格区域 */}
<div className={styles.tableCard}>
<div className={styles.cardTitle}>
<span>污染源管理</span>
<div className={styles.titleButtons}>
<Button
type="primary"
// icon={<PlusOutlined />}
onClick={handleAdd}
className={styles.titleAddButton}
>
新增
</Button>
<Button
// icon={<FileTextOutlined />}
onClick={handleGenerateReport}
className={styles.titleReportButton}
>
生成报表
</Button>
</div>
</div>
<StandardTable
columns={columns}
data={tableData}
onChange={handleTableChange}
rowKey="key"
size="small"
// scroll={{ x: 1200 }}
rowSelection={{
selectedRowKeys,
onChange: setSelectedRowKeys,
getCheckboxProps: (record) => ({
name: record.name,
}),
}}
pagination={{
showTotal: (total, range) => `${total}`,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['5', '10', '20', '50', '100'],
defaultPageSize: 5,
size: 'small',
}}
/>
</div>
</div >
);
};
export default PollutionSourceManagement;

@ -1,590 +0,0 @@
.pollutionDashboard {
width: 100%;
min-height: 75vh;
// background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
padding: 15px;
box-sizing: border-box;
// 顶部统计区域
.statsSection {
display: flex;
gap: 15px;
margin-bottom: 15px;
height: 35vh;
align-items: stretch;
// 污染物排放统计卡片
.pollutantStatsCard {
width: 37%;
height: 100%;
background: url('@/assets/business_envinformation/background7.svg'),
linear-gradient(180deg, #E2FFF5 0%, rgba(255, 255, 255, 0.6) 51.44%),
linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2));
background-repeat: no-repeat;
border-radius: 2px;
padding: 10px 20px;
display: flex;
flex-direction: column;
.cardTitle {
background: transparent;
color: #000000;
font-weight: 500;
font-size: 16px;
padding: 0;
margin: 0 0 15px 0;
border: none;
display: flex;
align-items: center;
justify-content: space-between;
}
}
// 超标排放统计卡片
.exceedanceStatsCard {
width: 40%;
height: 100%;
background: url('@/assets/business_envinformation/background8.svg'),
linear-gradient(180.21deg, rgba(255, 227, 227, 0.58) 0.18%, #FFFFFF 53.1%),
linear-gradient(0deg, rgba(255, 255, 255, 0.2), rgba(255, 255, 255, 0.2));
background-repeat: no-repeat;
border-radius: 2px;
padding: 10px 20px;
display: flex;
flex-direction: column;
.cardTitle {
background: transparent;
color: #000000;
font-weight: 500;
font-size: 16px;
padding: 0;
margin: 0 0 15px 0;
border: none;
display: flex;
align-items: center;
justify-content: space-between;
}
.filterGroup {
display: flex;
gap: 10px;
}
.exceedanceTimeFilter,
.exceedanceCategoryFilter {
width: 100px;
flex-shrink: 0;
:global(.ant-select-selector) {
border-radius: 2px;
border: 1px solid #FFC3C3;
background: #FFDEDEB2;
transition: all 0.3s ease;
}
}
}
// 卡片头部筛选器
.cardHeader {
display: flex;
justify-content: space-between;
align-items: center;
gap: 10px;
margin-bottom: 0;
.cardTitle {
background: transparent;
color: #000000;
font-weight: 500;
font-size: 16px;
padding: 0;
margin: 0;
border: none;
flex-shrink: 0;
}
.filterGroup {
display: flex;
gap: 10px;
}
.timeFilter,
.categoryFilter {
width: 100px;
flex-shrink: 0;
:global(.ant-select-selector) {
border-radius: 2px;
border: 1px solid #73E9C6;
background: #C0FFE9AB;
transition: all 0.3s ease;
}
}
}
// 图表容器
.chartsContainer {
display: flex;
gap: 20px;
justify-content: space-between;
background: transparent;
flex: 1;
.pieChartContainer {
flex: 1;
text-align: center;
position: relative;
background: transparent;
height: 100%;
min-height: 200px;
.chartTitle {
font-size: 14px;
color: #666;
margin-bottom: 10px;
font-weight: 500;
background: transparent;
}
.chartCenterContent {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
background: transparent;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.chartValue {
font-size: 18px;
font-weight: bold;
color: #FF2F2F;
background: transparent;
margin: 0;
line-height: 1;
}
.chartLabel {
font-size: 12px;
font-weight: 500;
color: #000000;
background: transparent;
margin: 0;
margin-top: 2px;
line-height: 1;
}
}
}
// 条形图容器
.barChartContainer {
flex: 1;
margin-top: 10px;
}
// 环境分类卡片区域
.environmentalCategories {
flex: 1; // 撑满剩余宽度
height: 100%;
display: flex;
flex-direction: column;
gap: 15px;
// background-color: pink;
.categoryCard1 {
flex: 1;
background: linear-gradient(90deg, rgba(27, 201, 181, 0.2) 0%, rgba(58, 255, 216, 0) 100%);
position: relative;
padding: 5px 15px;
.airPollutionText {
position: absolute;
top: 2px;
left: 12px;
background: linear-gradient(183.17deg, rgba(0, 255, 217, 0.1) 2.62%, rgba(0, 153, 131, 0.1) 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 600;
font-style: normal;
font-size: 22px;
line-height: 22px;
letter-spacing: 0%;
z-index: 1;
pointer-events: none;
}
}
.categoryCard2 {
flex: 1;
background: linear-gradient(90deg, rgba(36, 149, 255, 0.2) 0%, rgba(85, 164, 255, 0) 100%);
position: relative;
padding: 5px 15px;
.waterPollutionText {
position: absolute;
top: 2px;
left: 12px;
background: linear-gradient(183.17deg, rgba(0, 170, 255, 0.1) 2.62%, rgba(89, 186, 255, 0.1) 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 600;
font-style: normal;
font-size: 22px;
line-height: 22px;
letter-spacing: 0%;
z-index: 1;
pointer-events: none;
}
}
.categoryCard3 {
flex: 1;
background: linear-gradient(90deg, rgba(25, 60, 234, 0.2) 0%, rgba(139, 193, 255, 0) 100%);
position: relative;
cursor: pointer;
padding: 5px 15px;
.soilPollutionText {
position: absolute;
top: 2px;
left: 12px;
background: linear-gradient(183.17deg, rgba(0, 89, 255, 0.1) 2.62%, rgba(89, 117, 255, 0.1) 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 600;
font-style: normal;
font-size: 22px;
line-height: 22px;
letter-spacing: 0%;
z-index: 1;
pointer-events: none;
}
}
.categoryContent {
display: flex;
justify-content: space-between;
align-items: center;
.categoryInfo {
flex: 1;
.titleContainer {
display: flex;
flex-direction: column;
margin-bottom: 5px;
}
.categoryTitle {
font-size: 16px;
font-weight: 600;
color: #333;
margin-bottom: 0px;
&.atmosphereGradient {
background: linear-gradient(183.17deg, #0EE5C5 2.62%, #08C2C2 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 10px;
}
&.atmosphereMirror {
background: linear-gradient(183.17deg, rgba(168, 255, 242, 0) 2.62%, rgba(86, 237, 214, 0) 65.7%, #00D9B9 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 0px;
transform: scaleY(-1);
}
&.waterGradient {
background: linear-gradient(183.17deg, #40AFFF 2.62%, #00B3FF 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 10px;
}
&.waterMirror {
background: linear-gradient(183.17deg, rgba(64, 175, 255, 0) 2.62%, rgba(0, 179, 255, 0) 65.7%, #00B3FF 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 0px;
transform: scaleY(-1);
}
&.soilGradient {
background: linear-gradient(183.17deg, #6E90FF 2.62%, #3D90EF 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 10px;
}
&.soilMirror {
background: linear-gradient(183.17deg, rgba(110, 144, 255, 0) 2.62%, rgba(61, 144, 239, 0) 65.7%, #3D90EF 132.53%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-family: 'Alimama ShuHeiTi', sans-serif;
font-weight: 700;
font-size: 24px;
line-height: 22px;
letter-spacing: 0%;
margin-top: 0px;
transform: scaleY(-1);
}
}
.categorySubtitle {
font-size: 12px;
color: #666;
&.pollutantSubtitle {
color: rgba(51, 51, 51, 1);
font-family: 'Alibaba PuHuiTi', sans-serif;
font-weight: 500;
font-size: 14px;
line-height: 22px;
letter-spacing: 4%;
margin-top: -20px;
}
}
}
.categoryIcon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
margin-right: 5px;
// border-radius: 50%;
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.factoryIcon,
.waterIcon,
.soilIcon {
font-size: 20px;
filter: grayscale(0);
}
}
}
}
}
// 表格卡片
.tableCard {
background: #fff;
border-radius: 2px;
// box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
// border: 1px solid rgba(255, 255, 255, 0.2);
// backdrop-filter: blur(10px);
padding: 20px;
.cardTitle {
// background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
color: rgba(0, 0, 0, 1);
font-weight: 500;
font-size: 16px;
padding: 12px 16px;
margin: -20px -20px 10px -20px;
// border-radius: 12px 12px 0 0;
// border-bottom: 2px solid #e8f4fd;
display: flex;
justify-content: space-between;
align-items: center;
.titleButtons {
display: flex;
gap: 10px;
align-items: center;
.titleAddButton {
background: rgba(0, 212, 138, 1);
border: none;
border-radius: 4px;
color: #fff;
font-weight: 500;
transition: all 0.3s ease;
height: 32px;
padding: 4px 15px;
font-size: 14px;
&:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
}
.titleReportButton {
border-radius: 4px;
border: 1px solid #d9d9d9;
background: #fff;
color: #666;
transition: all 0.3s ease;
height: 32px;
padding: 4px 15px;
font-size: 14px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
transform: translateY(-1px);
}
}
}
}
}
// 自定义Tooltip样式
.customTooltip {
background: rgba(0, 0, 0, 0.8);
border-radius: 8px;
padding: 10px;
color: white;
font-size: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
.tooltipLabel {
font-weight: 600;
margin-bottom: 5px;
color: #fff;
}
.tooltipStatus {
color: #ff6b6b;
margin-bottom: 3px;
}
.tooltipExceedance {
color: #ffd93d;
margin-bottom: 3px;
}
.tooltipType {
color: #a8e6cf;
font-size: 11px;
}
}
// 响应式设计
@media (max-width: 1200px) {
.statsSection {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
.environmentalCategories {
grid-column: 1 / -1;
flex-direction: row;
gap: 15px;
.categoryCard {
flex: 1;
}
}
}
}
@media (max-width: 768px) {
padding: 10px;
.statsSection {
grid-template-columns: 1fr;
gap: 15px;
.environmentalCategories {
flex-direction: column;
}
}
}
// 表格样式优化
:global(.ant-table) {
// border-radius: 8px;
overflow: hidden;
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
font-size: 12px;
color: rgba(0, 0, 0, 0.85);
:global(.ant-table-thead > tr > th) {
// background: linear-gradient(90deg, #f8f9fa 0%, #e9ecef 100%);
// border-bottom: 2px solid #dee2e6;
font-weight: 400;
}
:global(.ant-table-tbody > tr) {
// transition: all 0.3s ease;
}
:global(.ant-table-tbody > tr > td) {
// border-bottom: 1px solid #f0f0f0;
}
}
// 分页器样式
// :global(.ant-pagination) {
// margin-top: 20px;
// text-align: center;
// :global(.ant-pagination-item) {
// border-radius: 6px;
// border: 1px solid #d9d9d9;
// transition: all 0.3s ease;
// &.ant-pagination-item-active {
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
// border-color: #667eea;
// color: white;
// }
// }
// :global(.ant-pagination-prev),
// :global(.ant-pagination-next) {
// border-radius: 6px;
// border: 1px solid #d9d9d9;
// transition: all 0.3s ease;
// }
// }
}

@ -1,345 +0,0 @@
import React, { useState } from 'react';
import { Button, Input, Select } from 'antd';
import { SearchOutlined, RedoOutlined, UploadOutlined, DownloadOutlined, DeleteOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './DischargePermitManagement.less';
// import attachment from '@/assets/business_envinformation/attachment.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
const DischargePermitManagement = () => {
const [activeTab, setActiveTab] = useState('actual');
// 实际排放数据
const actualEmissionData = [
{ key: 1, emissionType: '前林市', pollutant: '51669811', outletType: '信用风险管理与法律防', outletName: '北京那蓝国际贸易有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 2, emissionType: '拉萨市', pollutant: '34887875', outletType: '涉外警务', outletName: '中瀚石林企业咨询(上海)有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 3, emissionType: '长家界市', pollutant: '12345678', outletType: '环境设计', outletName: '上海环境科技有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 4, emissionType: '北京市', pollutant: '87654321', outletType: '污染治理', outletName: '北京环保科技有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 5, emissionType: '上海市', pollutant: '11223344', outletType: '排放监测', outletName: '上海监测技术有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 6, emissionType: '广州市', pollutant: '55667788', outletType: '工业废水', outletName: '广州环保科技股份有限公司', permittedEmission: '3年', annualTotal: '2025-09-10' },
{ key: 7, emissionType: '深圳市', pollutant: '99887766', outletType: '生活污水', outletName: '深圳水务集团有限公司', permittedEmission: '4年', annualTotal: '2025-07-20' },
{ key: 8, emissionType: '杭州市', pollutant: '33445566', outletType: '农业面源', outletName: '杭州农业科技有限公司', permittedEmission: '2年', annualTotal: '2025-10-05' },
{ key: 9, emissionType: '南京市', pollutant: '77889900', outletType: '工业废气', outletName: '南京工业集团股份有限公司', permittedEmission: '6年', annualTotal: '2025-06-15' },
{ key: 10, emissionType: '武汉市', pollutant: '11223355', outletType: '交通污染', outletName: '武汉交通发展有限公司', permittedEmission: '3年', annualTotal: '2025-11-20' },
{ key: 11, emissionType: '成都市', pollutant: '66778899', outletType: '建筑扬尘', outletName: '成都建筑工程有限公司', permittedEmission: '5年', annualTotal: '2025-05-30' },
{ key: 12, emissionType: '西安市', pollutant: '44556677', outletType: '餐饮油烟', outletName: '西安餐饮管理有限公司', permittedEmission: '4年', annualTotal: '2025-12-10' }
];
// 超标排放数据
const excessiveEmissionData = [
{ key: 1, emissionType: '俞林市', pollutant: '51669811', outletType: '信用风险管理与法律防', outletName: '北京那蓝国际贸易有限公司', permittedEmission: '5年', annualTotal: '2025-08-15' },
{ key: 2, emissionType: '拉萨市', pollutant: '34887875', outletType: '涉外警务', outletName: '中瀚石林企业咨询(上海)有限公司', permittedEmission: '5年', annualTotal: '2025-08-09' },
{ key: 3, emissionType: '长家界市', pollutant: '1716652546', outletType: '环境设计', outletName: '水木晨曦(北京)科技有限公司', permittedEmission: '5年', annualTotal: '2025-08-17' },
{ key: 4, emissionType: '潭市', pollutant: '384654762', outletType: '电子竞技运动与管理', outletName: '亚商桥(北京)咨询有限公司', permittedEmission: '5年', annualTotal: '2025-08-18' },
{ key: 5, emissionType: '次州市', pollutant: '34669295254', outletType: '精算学', outletName: '中讯通讯科技有限公司', permittedEmission: '5年', annualTotal: '2025-08-13' },
{ key: 6, emissionType: '驻马店市', pollutant: '4347052411', outletType: '数字媒体艺术', outletName: '嘉实瑞沃德(北京)商贸有限公司', permittedEmission: '5年', annualTotal: '2025-08-21' },
{ key: 7, emissionType: '三亚市', pollutant: '388946891', outletType: '技术侦察学', outletName: '中大国际文化有限公司', permittedEmission: '5年', annualTotal: '2025-08-17' },
{ key: 8, emissionType: '巢湖市', pollutant: '7190228566', outletType: '财政学', outletName: '嘉实瑞沃德(北京)商贸有限公司', permittedEmission: '5年', annualTotal: '2025-08-20' },
{ key: 9, emissionType: '东营市', pollutant: '6656363924', outletType: '保险学', outletName: '北京济丰国际医院管理有限公司', permittedEmission: '5年', annualTotal: '2025-08-27' },
{ key: 10, emissionType: '九龙', pollutant: '622145211', outletType: '英语', outletName: '北京庆奔科贸有限公司', permittedEmission: '5年', annualTotal: '2025-08-28' },
{ key: 11, emissionType: '深圳市', pollutant: '99887766', outletType: '生活污水', outletName: '深圳水务集团有限公司', permittedEmission: '4年', annualTotal: '2025-07-20' },
{ key: 12, emissionType: '杭州市', pollutant: '33445566', outletType: '农业面源', outletName: '杭州农业科技有限公司', permittedEmission: '2年', annualTotal: '2025-10-05' }
];
// 污染治理设备异常情况数据
const equipmentAbnormalData = [
{ key: 1, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 2, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 3, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 4, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 5, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 6, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 7, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 8, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 9, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 10, emissionType: '类型1', pollutant: '10:15:10—10:50:10', outletType: '管道', outletName: '老化', permittedEmission: '因子名称', annualTotal: '管口5m内' },
{ key: 11, emissionType: '类型2', pollutant: '11:20:15—11:45:30', outletType: '风机', outletName: '磨损', permittedEmission: '因子名称2', annualTotal: '风机10m内' },
{ key: 12, emissionType: '类型3', pollutant: '14:30:20—15:10:40', outletType: '泵站', outletName: '堵塞', permittedEmission: '因子名称3', annualTotal: '泵站15m内' }
];
// 实际排放和超标排放的表格列定义
const normalColumns = [
{
title: '序号',
dataIndex: 'key',
key: 'key',
width: 80,
align: 'center',
},
{
title: '排放物类型',
dataIndex: 'emissionType',
key: 'emissionType',
width: 100,
},
{
title: '污染物',
dataIndex: 'pollutant',
key: 'pollutant',
width: 100,
},
{
title: '排放口类型',
dataIndex: 'outletType',
key: 'outletType',
width: 160,
},
{
title: '排放口编号/排放口名称',
dataIndex: 'outletName',
key: 'outletName',
width: 220,
},
{
title: '许可排放量(吨)',
dataIndex: 'permittedEmission',
key: 'permittedEmission',
width: 120,
},
{
title: '年度合计',
dataIndex: 'annualTotal',
key: 'annualTotal',
width: 120,
},
{
title: '第一季度',
key: 'q1',
width: 80,
render: () => <a href="#" className={styles.attachmentLink}>附件</a>,
},
{
title: '二季度',
key: 'q2',
width: 80,
render: () => <a href="#" className={styles.attachmentLink}>附件</a>,
},
{
title: '三季度',
key: 'q3',
width: 80,
render: () => <a href="#" className={styles.attachmentLink}>附件</a>,
},
{
title: '四季度',
key: 'q4',
width: 80,
render: () => <a href="#" className={styles.attachmentLink}>附件</a>,
},
{
title: '操作',
key: 'action',
width: 100,
render: (_, record) => (
<div className={styles.actionButtons}>
<img
src={downloadicon}
alt="下载"
className={styles.downloadIcon}
title="下载"
/>
<img
src={deleteicon}
alt="删除"
className={styles.deleteIcon}
title="删除"
/>
</div>
),
},
];
// 污染治理设备异常情况的表格列定义
const equipmentColumns = [
{
title: '序号',
dataIndex: 'key',
key: 'key',
width: 80,
align: 'center',
},
{
title: '故障类型',
dataIndex: 'emissionType',
key: 'emissionType',
width: 100,
},
{
title: '超标时段(开始时段—结束时段)',
dataIndex: 'pollutant',
key: 'pollutant',
width: 200,
},
{
title: '故障设施',
dataIndex: 'outletType',
key: 'outletType',
width: 100,
},
{
title: '故障原因',
dataIndex: 'outletName',
key: 'outletName',
width: 100,
},
{
title: '排放因子',
dataIndex: 'permittedEmission',
key: 'permittedEmission',
width: 100,
},
{
title: '排放范围',
dataIndex: 'annualTotal',
key: 'annualTotal',
width: 120,
},
{
title: '排放因子浓度(mg/m³或dB(A))',
key: 'concentration',
width: 200,
render: () => '2025-08-15',
},
{
title: '应对',
key: 'response',
width: 80,
render: () => '—',
},
{
title: '操作',
key: 'action',
width: 120,
render: (_, record) => (
<div className={styles.actionButtons}>
<img
src={downloadicon}
alt="下载"
className={styles.downloadIcon}
title="下载"
/>
<img
src={deleteicon}
alt="删除"
className={styles.deleteIcon}
title="删除"
/>
</div>
),
},
];
// 获取当前标签页的数据
const getCurrentData = () => {
switch (activeTab) {
case 'actual':
return actualEmissionData;
case 'excessive':
return excessiveEmissionData;
case 'equipment':
return equipmentAbnormalData;
default:
return actualEmissionData;
}
};
// 获取当前标签页的列定义
const getCurrentColumns = () => {
switch (activeTab) {
case 'actual':
case 'excessive':
return normalColumns;
case 'equipment':
return equipmentColumns;
default:
return normalColumns;
}
};
// 分页配置
const pagination = {
current: 1,
pageSize: 10,
total: 12,
showTotal: (total) => `${total}`,
showSizeChanger: true,
showQuickJumper: true,
};
return (
<div className={styles.dischargePermitManagement}>
<div className={styles.tabContainer}>
<div className={styles.tabButtons}>
<Button
className={`${styles.tabButton} ${activeTab === 'actual' ? styles.active : ''}`}
onClick={() => setActiveTab('actual')}
>
实际排放
</Button>
<Button
className={`${styles.tabButton} ${activeTab === 'excessive' ? styles.active : ''}`}
onClick={() => setActiveTab('excessive')}
>
超标排放
</Button>
<Button
className={`${styles.tabButton} ${activeTab === 'equipment' ? styles.active : ''}`}
onClick={() => setActiveTab('equipment')}
>
污染治理设备异常情况
</Button>
</div>
<div className={styles.filterSection}>
<span className={styles.filterLabel}>筛选条件</span>
<Select
className={styles.filterSelect}
placeholder="请选择"
style={{ width: 120 }}
/>
<Input
className={styles.filterInput}
placeholder="请输入"
style={{ width: 200 }}
/>
<Button
type="primary"
// icon={<SearchOutlined />}
className={styles.queryBtn}
>
查询
</Button>
<Button
// icon={<RedoOutlined />}
className={styles.resetBtn}
>
重置
</Button>
<Button
// icon={<UploadOutlined />}
className={styles.uploadBtn}
>
上传
</Button>
</div>
</div>
<div className={styles.tableContent}>
<StandardTable
columns={getCurrentColumns()}
data={{
list: getCurrentData(),
pagination: pagination
}}
rowKey="key"
/>
</div>
</div>
);
};
export default DischargePermitManagement;

@ -1,160 +0,0 @@
.dischargePermitManagement {
width: 100%;
height: 100%;
background-color: #fff;
padding: 20px;
.tabContainer {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding: 0 ;
// border-bottom: 1px solid #e8e8e8;
.tabButtons {
display: flex;
gap: 0;
background-color: #F4F4F4;
border-radius: 4px;
padding: 4px 8px;
align-items: center;
.tabButton {
padding: 8px 20px;
border: none;
background-color: transparent;
color: #666;
font-size: 14px;
font-weight: 500;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s ease;
height: auto;
line-height: 1.4;
&:hover {
color: #1890ff;
background-color: rgba(24, 144, 255, 0.1);
}
&.active {
background-color: #03C598;
color: #fff;
}
}
}
.filterSection {
display: flex;
align-items: center;
gap: 12px;
border-radius: 4px;
.filterLabel {
font-size: 14px;
color: #333;
}
.filterSelect {
min-width: 120px;
}
.filterInput {
min-width: 200px;
border-radius: 4px;
}
.queryBtn {
background-color: #00D48A;
border-color: #00D48A;
border-radius: 4px;
&:hover {
background-color: #389e0d;
border-color: #389e0d;
}
}
.resetBtn, .uploadBtn {
background-color: #fff;
color: #666;
border-color: #d9d9d9;
border-radius: 4px;
&:hover {
border-color: #1890ff;
color: #1890ff;
}
}
}
}
.tableContent {
width: 100%;
// 覆盖表头样式
:global {
.ant-table-thead > tr > th {
font-weight: 400 !important;
font-size: 12px !important;
color: #333 !important;
text-align: center !important;
background-color: #FAFAFA !important;
}
.ant-table-tbody > tr > td {
font-size: 12px;
color: #333;
text-align: center;
}
.ant-table-wrapper {
width: 100%;
max-width: 100%;
}
}
.attachmentLink {
color: #1890ff;
text-decoration: none;
font-size: 12px;
&:hover {
text-decoration: underline;
}
}
.actionButtons {
display: flex;
gap: 20px;
justify-content: center;
align-items: center;
.downloadIcon, .deleteIcon {
width: 20px;
height: 20px;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
transform: scale(1.1);
opacity: 0.8;
}
}
.downloadIcon {
&:hover {
filter: brightness(1.2);
}
}
.deleteIcon {
&:hover {
filter: brightness(1.2) saturate(1.5);
}
}
}
}
}

@ -1,42 +0,0 @@
import React from 'react';
import styles from './EnvironmentalTaskList.less';
const EnvironmentalTaskList = () => {
return (
<div className={styles.environmentalTaskListContainer}>
<div className={styles.environmentalTaskListContent}>
<div className={styles.environmentalTaskListText}>
<h2>2) 环保管理任务清单</h2>
<p>依据排污许可证副本中的环保要求,提供生成环保管理要求任务清单;</p>
<p>环保任务清单包括:大气排放口信息,大气污染物有组织排放许可年限值,大气污染物无组织排放年限制企业大气排放总许可量;废水排放口废水污染物排放许可限制;固体废物排放信息自行贮存和自行利用/处置设施信息;工业噪声排放信息;</p>
<p>环境管理要求包括:自行检测及记录表环境管理台账记录</p>
</div>
</div>
<div className={styles.environmentalTaskListPagination}>
<div className={styles.paginationInfo}>
<span>共85条</span>
</div>
<div className={styles.paginationControls}>
<select className={styles.pageSizeSelect}>
<option value="5">5/page</option>
</select>
<div className={styles.pageNumbers}>
<button className={styles.pageButton}>&lt;</button>
<button className={styles.pageNumber}>1</button>
<span className={styles.pageEllipsis}>...</span>
<button className={styles.pageNumber}>4</button>
<button className={styles.pageNumber}>5</button>
<button className={`${styles.pageNumber} ${styles.active}`}>6</button>
<button className={styles.pageNumber}>7</button>
<button className={styles.pageNumber}>8</button>
<span className={styles.pageEllipsis}>...</span>
<button className={styles.pageNumber}>50</button>
<button className={styles.pageButton}>&gt;</button>
</div>
</div>
</div>
</div>
);
};
export default EnvironmentalTaskList;

@ -1,105 +0,0 @@
.environmentalTaskListContainer {
width: 100%;
height: 72vh;
display: flex;
flex-direction: column;
background-color: #fff;
position: relative;
}
.environmentalTaskListContent {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 0px 20px;
}
.environmentalTaskListText {
max-width: 800px;
text-align: left;
line-height: 1.6;
h2 {
font-size: 20px;
color: #333;
margin-bottom: 20px;
font-weight: 600;
}
p {
font-size: 16px;
color: #333;
margin-bottom: 15px;
text-indent: 2em;
}
}
.environmentalTaskListPagination {
position: absolute;
bottom: 20px;
right: 20px;
display: flex;
align-items: center;
gap: 20px;
background: #fff;
padding: 10px 20px;
border-radius: 4px;
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.paginationInfo {
font-size: 14px;
color: #666;
}
.paginationControls {
display: flex;
align-items: center;
gap: 10px;
}
.pageSizeSelect {
padding: 4px 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
font-size: 12px;
background: #fff;
}
.pageNumbers {
display: flex;
align-items: center;
gap: 4px;
}
.pageButton, .pageNumber {
padding: 4px 8px;
border: 1px solid #d9d9d9;
background: #fff;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
min-width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
border-color: #1890ff;
color: #1890ff;
}
}
.pageNumber.active {
background: #1890ff;
color: #fff;
border-color: #1890ff;
}
.pageEllipsis {
padding: 4px 8px;
font-size: 12px;
color: #666;
}

@ -1,13 +0,0 @@
import React from 'react';
import styles from './InformationDisclosure.less';
const InformationDisclosure = () => {
return (
<div className={styles.container}>
<div className={styles.content}>待开发</div>
</div>
);
};
export default InformationDisclosure;

@ -1,15 +0,0 @@
.container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
.content {
font-size: 24px;
color: #999999;
font-weight: 400;
}
}

@ -1,286 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './PermitManagement.less';
import licence1 from '@/assets/business_envinformation/licence1.svg';
import licence2 from '@/assets/business_envinformation/licence2.svg';
const PermitManagement = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [dataSource, setDataSource] = useState([
{
key: 1,
companyName: '北京某某环保有限公司',
permitNumber: 'PWX-BJ-2023-001',
issueOrg: '北京市生态环境局',
expireDate: '2025-12-31',
original: '已上传',
duplicate: '已上传',
},
{
key: 2,
companyName: '上海某某化工有限公司',
permitNumber: 'PWX-SH-2023-002',
issueOrg: '上海市生态环境局',
expireDate: '2025-10-15',
original: '已上传',
duplicate: '已上传',
},
{
key: 3,
companyName: '广州某某制造有限公司',
permitNumber: 'PWX-GZ-2023-003',
issueOrg: '广州市生态环境局',
expireDate: '2026-03-20',
original: '未上传',
duplicate: '已上传',
},
{
key: 4,
companyName: '深圳某某电子有限公司',
permitNumber: 'PWX-SZ-2023-004',
issueOrg: '深圳市生态环境局',
expireDate: '2025-08-10',
original: '已上传',
duplicate: '未上传',
},
{
key: 5,
companyName: '成都某某科技有限公司',
permitNumber: 'PWX-CD-2023-005',
issueOrg: '成都市生态环境局',
expireDate: '2026-01-25',
original: '已上传',
duplicate: '已上传',
},
{
key: 6,
companyName: '武汉某某工业有限公司',
permitNumber: 'PWX-WH-2023-006',
issueOrg: '武汉市生态环境局',
expireDate: '2025-11-30',
original: '已上传',
duplicate: '已上传',
},
{
key: 7,
companyName: '杭州某某环保有限公司',
permitNumber: 'PWX-HZ-2023-007',
issueOrg: '杭州市生态环境局',
expireDate: '2026-05-15',
original: '未上传',
duplicate: '已上传',
},
{
key: 8,
companyName: '南京某某化学有限公司',
permitNumber: 'PWX-NJ-2023-008',
issueOrg: '南京市生态环境局',
expireDate: '2025-09-20',
original: '已上传',
duplicate: '已上传',
},
{
key: 9,
companyName: '重庆某某重工有限公司',
permitNumber: 'PWX-CQ-2023-009',
issueOrg: '重庆市生态环境局',
expireDate: '2026-02-28',
original: '已上传',
duplicate: '未上传',
},
{
key: 10,
companyName: '天津某某制药有限公司',
permitNumber: 'PWX-TJ-2023-010',
issueOrg: '天津市生态环境局',
expireDate: '2025-07-10',
original: '已上传',
duplicate: '已上传',
},
{
key: 11,
companyName: '西安某某材料有限公司',
permitNumber: 'PWX-XA-2023-011',
issueOrg: '西安市生态环境局',
expireDate: '2026-04-05',
original: '未上传',
duplicate: '已上传',
},
{
key: 12,
companyName: '青岛某某机械有限公司',
permitNumber: 'PWX-QD-2023-012',
issueOrg: '青岛市生态环境局',
expireDate: '2025-12-15',
original: '已上传',
duplicate: '已上传',
},
]);
const columns = [
{
title: '序号',
dataIndex: 'key',
key: 'key',
width: 80,
align: 'center',
},
{
title: '企业名称',
dataIndex: 'companyName',
key: 'companyName',
width: 200,
},
{
title: '排污许可证号',
dataIndex: 'permitNumber',
key: 'permitNumber',
width: 180,
},
{
title: '颁发机构',
dataIndex: 'issueOrg',
key: 'issueOrg',
width: 180,
},
{
title: '到期时间',
dataIndex: 'expireDate',
key: 'expireDate',
width: 120,
sorter: (a, b) => new Date(a.expireDate) - new Date(b.expireDate),
showSorterTooltip: false,
},
{
title: '正本',
dataIndex: 'original',
key: 'original',
width: 100,
align: 'center',
render: () => <a style={{ color: '#0080FF' }} onClick={() => { setCurrentImage(licence1); setIsModalVisible(true); }}>附件</a>
},
{
title: '副本',
dataIndex: 'duplicate',
key: 'duplicate',
width: 100,
align: 'center',
render: () => <a style={{ color: '#0080FF' }} onClick={() => { setCurrentImage(licence2); setIsModalVisible(true); }}>附件</a>
},
{
title: '操作',
key: 'action',
width: 150,
align: 'center',
render: (_, record) => (
<Space size="middle">
<EyeOutlined
style={{ color: '#7ee370', fontSize: 16, cursor: 'pointer' }}
onClick={() => handleView(record)}
/>
<DeleteOutlined
style={{ color: '#ff7e72', fontSize: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
return (
<div className={styles.permitContainer}>
{/* 第一块:搜索表单 */}
<div className={styles.searchSection}>
<Form form={form} layout="inline" onFinish={handleSearch}>
<Form.Item label="企业名称" name="companyName">
<Input placeholder="请输入" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item label="许可证号" name="permitNumber">
<Input placeholder="请输入" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item label="到期时间" name="expireDate">
<DatePicker placeholder="请选择" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{ backgroundColor: '#00D48A', borderColor: '#00D48A', color: '#fff', borderRadius: '4px' }}
>
查询
</Button>
</Form.Item>
<Form.Item>
<Button onClick={handleReset} style={{ borderRadius: '4px' }}>
重置
</Button>
</Form.Item>
</Form>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: dataSource,
pagination: {
total: dataSource.length,
pageSize: 10,
currentPage: 1,
showTotal: (total) => `${total}`,
}
}}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default PermitManagement;

@ -1,137 +0,0 @@
.permitContainer {
width: 100%;
height: 100%;
// padding: 20px;
background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.searchSection {
// margin-bottom: 20px;
padding: 20px;
// background-color: #fafafa;
// border-radius: 2px;
:global {
.ant-form-inline {
display: flex;
.ant-form-item {
margin-right: 16px;
margin-bottom: 0;
}
.ant-form-item:nth-last-child(2) {
margin-left: auto;
}
.ant-form-item:last-child {
margin-right: 0;
}
}
.ant-form-item-label {
font-weight: 500;
label {
color: #666666;
font-size: 13px;
}
}
.ant-input::placeholder,
.ant-picker-input input::placeholder {
color: #00000040;
font-size: 13px;
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0 20px 0;
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table {
flex: 1;
overflow: auto;
margin: 0;
}
.ant-table-pagination {
flex-shrink: 0;
}
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #fafafa;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
margin-top: 70px !important;
}
}
}
}

@ -1,421 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal, Select } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined, PlusOutlined, UploadOutlined, EditOutlined, DownloadOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './PermitStatistics.less';
import licence1 from '@/assets/business_envinformation/image1.svg';
import licence2 from '@/assets/business_envinformation/image2.svg';
import viewicon from '@/assets/business_envinformation/viewicon.svg';
import editicon from '@/assets/business_envinformation/editicon.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
const PermitStatistics = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 14,
});
const [dataSource, setDataSource] = useState([
{
key: 1,
administrativeRegion: '榆林市',
permitNumber: '51669811',
industryCategory: '信用风险管理与法律防',
companyName: '北京那蓝国际贸易有限公司',
validityPeriod: '5年',
issueDate: '2025-08-15',
original: '附件',
duplicate: '附件',
},
{
key: 2,
administrativeRegion: '拉萨市',
permitNumber: '34887875',
industryCategory: '涉外警务',
companyName: '中潮石林企业咨询(上海)有限公司北京分公司',
validityPeriod: '5年',
issueDate: '2025-08-09',
original: '附件',
duplicate: '附件',
},
{
key: 3,
administrativeRegion: '长家界市',
permitNumber: '1716652546',
industryCategory: '环境设计',
companyName: '水木晨曦(北京)科技有限公司',
validityPeriod: '5年',
issueDate: '2025-08-17',
original: '附件',
duplicate: '附件',
},
{
key: 4,
administrativeRegion: '马潭市',
permitNumber: '384654762',
industryCategory: '电子竞技运动与管理',
companyName: '亚商桥(北京)咨询有限公司',
validityPeriod: '5年',
issueDate: '2025-08-17',
original: '附件',
duplicate: '附件',
},
{
key: 5,
administrativeRegion: '交州市',
permitNumber: '34669295254',
industryCategory: '精算学',
companyName: '中讯通讯科技有限公司',
validityPeriod: '5年',
issueDate: '2025-08-13',
original: '附件',
duplicate: '附件',
},
{
key: 6,
administrativeRegion: '驻马店市',
permitNumber: '4347052411',
industryCategory: '数字媒体艺术',
companyName: '嘉实瑞沃德(北京)商贸有限公司',
validityPeriod: '5年',
issueDate: '2025-08-21',
original: '附件',
duplicate: '附件',
},
{
key: 7,
administrativeRegion: '三亚市',
permitNumber: '388946691',
industryCategory: '技术侦察学',
companyName: '中大国际文化有限公司',
validityPeriod: '5年',
issueDate: '2025-08-17',
original: '附件',
duplicate: '附件',
},
{
key: 8,
administrativeRegion: '美湖市',
permitNumber: '7190228566',
industryCategory: '财政学',
companyName: '嘉实瑞沃德(北京)商贸有限公司',
validityPeriod: '5年',
issueDate: '2025-08-20',
original: '附件',
duplicate: '附件',
},
{
key: 9,
administrativeRegion: '东营市',
permitNumber: '6656363924',
industryCategory: '保险学',
companyName: '北京清丰国际医院管理有限公司',
validityPeriod: '5年',
issueDate: '2025-06-27',
original: '附件',
duplicate: '附件',
},
{
key: 10,
administrativeRegion: '九龙',
permitNumber: '622145211',
industryCategory: '英语',
companyName: '北京庆奔科贸有限公司',
validityPeriod: '5年',
issueDate: '2025-08-28',
original: '附件',
duplicate: '附件',
},
{
key: 11,
administrativeRegion: '深圳市',
permitNumber: '755123456',
industryCategory: '计算机科学与技术',
companyName: '深圳创新科技有限公司',
validityPeriod: '3年',
issueDate: '2025-09-01',
original: '附件',
duplicate: '附件',
},
{
key: 12,
administrativeRegion: '杭州市',
permitNumber: '571789012',
industryCategory: '电子商务',
companyName: '杭州数字贸易有限公司',
validityPeriod: '4年',
issueDate: '2025-09-05',
original: '附件',
duplicate: '附件',
},
{
key: 13,
administrativeRegion: '成都市',
permitNumber: '028345678',
industryCategory: '生物技术',
companyName: '成都生物科技股份有限公司',
validityPeriod: '5年',
issueDate: '2025-09-10',
original: '附件',
duplicate: '附件',
},
{
key: 14,
administrativeRegion: '武汉市',
permitNumber: '027456789',
industryCategory: '机械工程',
companyName: '武汉智能制造有限公司',
validityPeriod: '3年',
issueDate: '2025-09-15',
original: '附件',
duplicate: '附件',
},
]);
const columns = [
{
title: '序号',
dataIndex: 'key',
key: 'key',
width: 80,
align: 'center',
},
{
title: '行政区',
dataIndex: 'administrativeRegion',
key: 'administrativeRegion',
width: 120,
},
{
title: '许可证编号',
dataIndex: 'permitNumber',
key: 'permitNumber',
width: 130,
},
{
title: '行业类别',
dataIndex: 'industryCategory',
key: 'industryCategory',
width: 200,
},
{
title: '企业名称',
dataIndex: 'companyName',
key: 'companyName',
width: 230,
},
{
title: '有效期限',
dataIndex: 'validityPeriod',
key: 'validityPeriod',
width: 80,
align: 'center',
},
{
title: '发证日期',
dataIndex: 'issueDate',
key: 'issueDate',
width: 120,
align: 'center',
},
{
title: '正本',
dataIndex: 'original',
key: 'original',
width: 80,
align: 'center',
render: () => <a style={{ color: '#0080FF' }} onClick={() => { setCurrentImage(licence1); setIsModalVisible(true); }}>附件</a>
},
{
title: '副本',
dataIndex: 'duplicate',
key: 'duplicate',
width: 120,
align: 'center',
render: () => <a style={{ color: '#0080FF' }} onClick={() => { setCurrentImage(licence2); setIsModalVisible(true); }}>附件</a>
},
{
title: '操作',
key: 'action',
width: 140,
align: 'center',
render: (_, record) => (
<Space size={13}>
<img
src={viewicon}
alt="查看"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleView(record)}
/>
<img
src={editicon}
alt="编辑"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleEdit(record)}
/>
<img
src={downloadicon}
alt="下载"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDownload(record)}
/>
<img
src={deleteicon}
alt="删除"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDownload = (record) => {
console.log('下载:', record);
// TODO: 实现下载功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
const handleAdd = () => {
console.log('新增');
// TODO: 实现新增功能
};
const handleImport = () => {
console.log('导入');
// TODO: 实现导入功能
};
const handleQuery = () => {
console.log('查询');
// TODO: 实现查询功能
};
const handleTableChange = (pagination) => {
setPagination(pagination);
};
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const start = (current - 1) * pageSize;
const end = start + pageSize;
return dataSource.slice(start, end);
};
return (
<div className={styles.permitContainer}>
{/* 第一块:操作按钮和筛选条件 */}
<div className={styles.searchSection}>
<div className={styles.leftButtons}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
className={styles.addButton}
>
新增
</Button>
<Button
icon={<UploadOutlined />}
onClick={handleImport}
className={styles.importButton}
>
导入
</Button>
</div>
<div className={styles.rightControls}>
<span className={styles.filterLabel}>筛选条件</span>
<Select
placeholder="请选择"
style={{ width: 140, height: 28 }}
allowClear
className={styles.selectInput}
/>
<Input
placeholder="请输入"
style={{ width: 160, height: 28 }}
/>
<Button
onClick={handleQuery}
className={styles.queryButton}
>
查询
</Button>
<Button
onClick={handleReset}
className={styles.resetButton}
>
重置
</Button>
</div>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: {
...pagination,
total: dataSource.length,
showTotal: (total) => `${total}`,
showSizeChanger: false,
}
}}
onChange={handleTableChange}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default PermitStatistics;

@ -1,187 +0,0 @@
.permitContainer {
width: 100%;
height: 100%;
// padding: 20px;
background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.searchSection {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.leftButtons {
display: flex;
gap: 12px;
.addButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.importButton {
background-color: white;
border-color: #d9d9d9;
color: #333;
height: 32px;
border-radius: 4px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
}
.rightControls {
display: flex;
align-items: center;
gap: 12px;
.filterLabel {
color: #333;
font-size: 14px;
white-space: nowrap;
}
.queryButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 28px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.selectInput {
:global {
.ant-select-selector {
display: flex;
align-items: center;
height: 28px !important;
}
.ant-select-selection-item {
display: flex;
align-items: center;
line-height: 1;
}
.ant-select-selection-placeholder {
display: flex;
align-items: center;
line-height: 1;
}
}
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 0 20px 0;
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table {
flex: 1;
overflow: auto;
margin: 0;
}
.ant-table-pagination {
flex-shrink: 0;
}
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #fafafa;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
margin-top: 70px !important;
}
}
}
}

@ -1,578 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal, Select } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined, PlusOutlined, UploadOutlined, EditOutlined, DownloadOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './ProtectionFacilityMaintenance.less';
import licence1 from '@/assets/business_envinformation/image1.svg';
import licence2 from '@/assets/business_envinformation/image2.svg';
import viewicon from '@/assets/business_envinformation/viewicon.svg';
import editicon from '@/assets/business_envinformation/editicon.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
const ProtectionFacilityMaintenance = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 13,
});
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([
{
key: 1,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
facilityCode: '35.236.217.212',
startTime: '2025-08-23 06:18',
endTime: '2025-08-23 06:18',
pollutantType: '123',
concentration: '39',
unit: 'm³/d',
dischargeDestination: '大气',
eventReason: '从病虫害探测、土壤墒情监测智能...',
isReported: '已报告',
responseMeasures: '2025-08-23 06:18',
},
{
key: 2,
recordTime: '2025-09-02',
recorder: '王嘉骐',
reviewer: '赵子峰',
facilityName: '复方水杨酸甲酯乳膏(曼秀雷敦)',
facilityCode: '65.177.48.116',
startTime: '2025-09-07 17:48',
endTime: '2025-09-07 17:48',
pollutantType: '大气污染物',
concentration: '52',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '从病虫害探测、土壤墒情监测智能...',
isReported: '已报告',
responseMeasures: '2025-09-07 17:48',
},
{
key: 3,
recordTime: '2025-09-06',
recorder: '王嘉琪',
reviewer: '郑清予',
facilityName: '口炎清颗粒(大神)',
facilityCode: '111.161.135.125',
startTime: '2025-09-04 13:08',
endTime: '2025-09-04 13:08',
pollutantType: '污水',
concentration: '28',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '从病虫害探测、土壤墒情监测智能...',
isReported: '已报告',
responseMeasures: '2025-09-04 13:08',
},
{
key: 4,
recordTime: '2025-08-22',
recorder: '王佛瑶',
reviewer: '赵玉',
facilityName: '烧烫伤膏(茂祥)',
facilityCode: '162.208.135.147',
startTime: '2025-08-28 22:40',
endTime: '2025-08-28 22:40',
pollutantType: '污水',
concentration: '46',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '近期,高铁"熊孩子"事件频出,...',
isReported: '已报告',
responseMeasures: '2025-08-28 22:40',
},
{
key: 5,
recordTime: '2025-08-31',
recorder: '吴子萱',
reviewer: '钱品妍',
facilityName: '云南白药(云南白药)',
facilityCode: '138.6.246.181',
startTime: '2025-09-17 19:48',
endTime: '2025-09-17 19:48',
pollutantType: '污水',
concentration: '37',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '刘某及同伴三人前往该射击俱乐部...',
isReported: '已报告',
responseMeasures: '2025-09-17 19:48',
},
{
key: 6,
recordTime: '2025-08-29',
recorder: '何风景',
reviewer: '赵海洲',
facilityName: '麝香壮骨膏(修正)',
facilityCode: '134.80.173.128',
startTime: '2025-09-02 22:21',
endTime: '2025-09-02 22:21',
pollutantType: '污水',
concentration: '53',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '一位网友在社交平台发布的视频显...',
isReported: '未报告',
responseMeasures: '2025-09-02 22:21',
},
{
key: 7,
recordTime: '2025-08-28',
recorder: '李琳颖',
reviewer: '李建刚',
facilityName: '复方醋酸甲羟孕酮胶囊(妇复春)',
facilityCode: '218.169.25.43',
startTime: '2025-09-06 16:27',
endTime: '2025-09-06 16:27',
pollutantType: '污水',
concentration: '24',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '盛夏时节,四川绵竹市汉旺镇一株...',
isReported: '未报告',
responseMeasures: '2025-09-06 16:27',
},
{
key: 8,
recordTime: '2025-08-22',
recorder: '赵午光',
reviewer: '钱泽西',
facilityName: '桂龙药膏',
facilityCode: '54.218.80.84',
startTime: '2025-09-12 22:50',
endTime: '2025-09-12 22:50',
pollutantType: '污水',
concentration: '47',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '随着"热射病"这一高温疾病快速...',
isReported: '未报告',
responseMeasures: '2025-09-12 22:50',
},
{
key: 9,
recordTime: '2025-08-21',
recorder: '王凤娇',
reviewer: '李金泽',
facilityName: '和兴白花油(和兴白花油)',
facilityCode: '222.1.18.173',
startTime: '2025-09-10 04:28',
endTime: '2025-09-10 04:28',
pollutantType: '污水',
concentration: '33',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '夏粮丰,全年稳。国家粮食和物资...',
isReported: '未报告',
responseMeasures: '2025-09-10 04:28',
},
{
key: 10,
recordTime: '2025-09-09',
recorder: '赵涛',
reviewer: '何能',
facilityName: '茶苯海明含片(贻晗柠)',
facilityCode: '136.200.182.22',
startTime: '2025-08-30 07:15',
endTime: '2025-08-30 07:15',
pollutantType: '污水',
concentration: '34',
unit: 'm³/d',
dischargeDestination: '河流',
eventReason: '近日,一则"携程推出火车卧铺女...',
isReported: '未报告',
responseMeasures: '2025-08-30 07:15',
},
{
key: 11,
recordTime: '2025-09-15',
recorder: '李小明',
reviewer: '王建国',
facilityName: '阿莫西林胶囊(华北制药)',
facilityCode: '192.168.1.100',
startTime: '2025-09-15 14:30',
endTime: '2025-09-15 16:45',
pollutantType: '大气污染物',
concentration: '68',
unit: 'mg/m³',
dischargeDestination: '大气',
eventReason: '设备故障导致废气处理系统异常运行...',
isReported: '已报告',
responseMeasures: '2025-09-15 16:45',
},
{
key: 12,
recordTime: '2025-09-18',
recorder: '张美丽',
reviewer: '刘德华',
facilityName: '布洛芬缓释胶囊(中美史克)',
facilityCode: '10.0.0.25',
startTime: '2025-09-18 09:20',
endTime: '2025-09-18 11:30',
pollutantType: '污水',
concentration: '42',
unit: 'mg/L',
dischargeDestination: '污水处理厂',
eventReason: '管道泄漏导致废水直接排放...',
isReported: '未报告',
responseMeasures: '2025-09-18 11:30',
},
{
key: 13,
recordTime: '2025-09-20',
recorder: '陈志强',
reviewer: '周杰伦',
facilityName: '头孢拉定胶囊(石药集团)',
facilityCode: '172.16.0.88',
startTime: '2025-09-20 20:15',
endTime: '2025-09-20 22:00',
pollutantType: '噪声',
concentration: '85',
unit: 'dB',
dischargeDestination: '环境',
eventReason: '夜间施工未采取降噪措施...',
isReported: '已报告',
responseMeasures: '2025-09-20 22:00',
},
]);
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const start = (current - 1) * pageSize;
const end = start + pageSize;
return dataSource.slice(start, end);
};
const columns = [
{
title: (
<input
type="checkbox"
checked={selectedRowKeys.length === getCurrentPageData().length && getCurrentPageData().length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
/>
),
key: 'selection',
width: 60,
align: 'center',
fixed: 'left',
render: (_, record) => (
<input
type="checkbox"
checked={selectedRowKeys.includes(record.key)}
onChange={(e) => {
if (e.target.checked) {
setSelectedRowKeys([...selectedRowKeys, record.key]);
} else {
setSelectedRowKeys(selectedRowKeys.filter(key => key !== record.key));
}
}}
/>
),
},
{
title: '记录时间',
dataIndex: 'recordTime',
key: 'recordTime',
width: 120,
align: 'center',
},
{
title: '记录人',
dataIndex: 'recorder',
key: 'recorder',
width: 100,
align: 'center',
},
{
title: '审核人',
dataIndex: 'reviewer',
key: 'reviewer',
width: 100,
align: 'center',
},
{
title: '设施名称',
dataIndex: 'facilityName',
key: 'facilityName',
width: 200,
},
{
title: '编号',
dataIndex: 'facilityCode',
key: 'facilityCode',
width: 150,
align: 'center',
},
{
title: '异常情况起始时刻',
dataIndex: 'startTime',
key: 'startTime',
width: 160,
align: 'center',
},
{
title: '异常情况终止时刻',
dataIndex: 'endTime',
key: 'endTime',
width: 160,
align: 'center',
},
{
title: '污染物种类',
dataIndex: 'pollutantType',
key: 'pollutantType',
width: 120,
align: 'center',
},
{
title: '污染物排放浓度',
dataIndex: 'concentration',
key: 'concentration',
width: 140,
align: 'center',
},
{
title: '浓度单位',
dataIndex: 'unit',
key: 'unit',
width: 100,
align: 'center',
},
{
title: '排放去向',
dataIndex: 'dischargeDestination',
key: 'dischargeDestination',
width: 100,
align: 'center',
},
{
title: '事件原因',
dataIndex: 'eventReason',
key: 'eventReason',
width: 180,
},
{
title: '是否报告',
dataIndex: 'isReported',
key: 'isReported',
width: 100,
align: 'center',
render: (text) => (
<span style={{
color: text === '未报告' ? '#722ed1' : '#52c41a',
backgroundColor: text === '未报告' ? '#F9F0FF' : '#F6FFED',
border: text === '未报告' ? '1px solid #D3ADF7' : '1px solid #B7EB8F',
padding: '2px 8px',
borderRadius: '4px',
display: 'inline-block'
}}>
{text}
</span>
),
},
{
title: '应对措施',
dataIndex: 'responseMeasures',
key: 'responseMeasures',
width: 150,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 100,
align: 'center',
fixed: 'right',
render: (_, record) => (
<Space size={18}>
<img
src={editicon}
alt="编辑"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleEdit(record)}
/>
<img
src={downloadicon}
alt="下载"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDownload(record)}
/>
<img
src={deleteicon}
alt="删除"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDownload = (record) => {
console.log('下载:', record);
// TODO: 实现下载功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
const handleAdd = () => {
console.log('新增');
// TODO: 实现新增功能
};
const handleImport = () => {
console.log('导入');
// TODO: 实现导入功能
};
const handleQuery = () => {
console.log('查询');
// TODO: 实现查询功能
};
const handleTableChange = (pagination) => {
setPagination(pagination);
};
// 全选功能
const handleSelectAll = (checked) => {
if (checked) {
const allKeys = getCurrentPageData().map(item => item.key);
setSelectedRowKeys(allKeys);
} else {
setSelectedRowKeys([]);
}
};
// 批量操作
const handleBatchOperation = (operation) => {
console.log(`批量${operation}:`, selectedRowKeys);
// TODO: 实现批量操作功能
};
return (
<div className={styles.protectionFacilityContainer}>
{/* 第一块:操作按钮和筛选条件 */}
<div className={styles.searchSection}>
<div className={styles.leftButtons}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
className={styles.addButton}
>
新增
</Button>
<Button
onClick={handleImport}
className={styles.importButton}
>
上传
</Button>
<Button
onClick={() => handleBatchOperation('下载')}
className={styles.importButton}
disabled={selectedRowKeys.length === 0}
>
批量下载
</Button>
</div>
<div className={styles.rightControls}>
<span className={styles.filterLabel}>筛选条件</span>
<Select
placeholder="请选择"
style={{ width: 140, height: 28 }}
allowClear
className={styles.selectInput}
/>
<Input
placeholder="请输入"
style={{ width: 160, height: 28 }}
/>
<Button
onClick={handleQuery}
className={styles.queryButton}
>
查询
</Button>
<Button
onClick={handleReset}
className={styles.resetButton}
>
重置
</Button>
</div>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: {
...pagination,
total: dataSource.length,
showTotal: (total) => `${total}`,
showSizeChanger: false,
}
}}
onChange={handleTableChange}
scroll={{ x: 3000 }}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default ProtectionFacilityMaintenance;

@ -1,205 +0,0 @@
.protectionFacilityContainer {
width: 100%;
height: 100%;
// padding: 20px;
background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.searchSection {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.leftButtons {
display: flex;
gap: 12px;
.addButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.importButton {
background-color: white;
border-color: #d9d9d9;
color: #333;
height: 32px;
border-radius: 4px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
}
.rightControls {
display: flex;
align-items: center;
gap: 12px;
.filterLabel {
color: #333;
font-size: 14px;
white-space: nowrap;
}
.queryButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 28px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.selectInput {
:global {
.ant-select-selector {
display: flex;
align-items: center;
height: 28px !important;
}
.ant-select-selection-item {
display: flex;
align-items: center;
line-height: 1;
}
.ant-select-selection-placeholder {
display: flex;
align-items: center;
line-height: 1;
}
}
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
padding: 0 20px 0;
overflow: hidden; // 只设置垂直隐藏
min-width: 0; // 确保可以收缩
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #fafafa;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
// 固定列样式
.ant-table-thead > tr > th.ant-table-cell-fix-left,
.ant-table-tbody > tr > td.ant-table-cell-fix-left {
background-color: #fafafa;
z-index: 1;
}
.ant-table-thead > tr > th.ant-table-cell-fix-right,
.ant-table-tbody > tr > td.ant-table-cell-fix-right {
background-color: #fafafa;
z-index: 1;
}
// 固定列阴影效果
.ant-table-cell-fix-left {
// box-shadow: 0px 0 4px 0px #00000040;
}
.ant-table-cell-fix-right {
// box-shadow: 0px 0 4px 0px #00000040;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
margin-top: 25px !important;
}
}
}
}

@ -1,592 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Select, Drawer, Descriptions, Tag } from 'antd';
import styles from './RegulationCompliance.less';
import stipulation1 from '@/assets/business_envinformation/stipulation1.svg';
const RegulationCompliance = () => {
const [form] = Form.useForm();
const [drawerVisible, setDrawerVisible] = useState(false);
const [selectedRegulation, setSelectedRegulation] = useState(null);
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
// 显示抽屉详情
const showDrawer = (regulation) => {
setSelectedRegulation(regulation);
setDrawerVisible(true);
};
// 关闭抽屉
const onCloseDrawer = () => {
setDrawerVisible(false);
setSelectedRegulation(null);
};
// 模拟法规数据(实际应该从后端获取)
const mockRegulationDetail = {
name: '2025排污许可条例',
publishDate: '2025-08-24',
department: '环保部门名称',
content: '在此输入具体的法规内容...',
status: '有效',
category: '排污许可',
version: '1.0',
updateTime: '2025-08-24'
};
return (
<div className={styles.regulationContainer}>
{/* 第一块:搜索表单 */}
<div className={styles.searchSection}>
<Form form={form} layout="inline" onFinish={handleSearch}>
<Form.Item label="法规名称" name="regulationName">
<Input placeholder="请输入" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item label="发布部门" name="regulationNumber">
<Input placeholder="请输入" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item label="发布日期" name="publishDate">
<DatePicker placeholder="请选择" style={{ width: 160, borderRadius: '2px' }} />
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
style={{ backgroundColor: '#00D48A', borderColor: '#00D48A', color: '#fff', borderRadius: '4px' }}
>
查询
</Button>
</Form.Item>
<Form.Item>
<Button onClick={handleReset} style={{ borderRadius: '4px' }}>
重置
</Button>
</Form.Item>
</Form>
</div>
{/* 第二块:表格区域 */}
<div className={styles.tableSection}>
<div className={styles.blocksContainer}>
{/* 法规合规管理块1 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-24
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块2 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-25
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块3 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-26
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块4 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-27
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块5 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-28
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块6 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-29
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块7 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-30
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块8 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-08-31
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块9 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-09-01
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称9
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块10 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-09-02
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块11 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-09-03
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
{/* 法规合规管理块12 */}
<div className={styles.regulationBlock}>
{/* 第一行:法规名称 */}
<div className={styles.regulationTitle}>
<img src={stipulation1} alt="法规图标" style={{ width: '20px', height: '20px', marginRight: '4px' }} />
2025排污许可条例
</div>
{/* 第二行:发布时间和发布部门 */}
<div className={styles.regulationInfo}>
<div className={styles.publishDate}>
发布时间&nbsp;&nbsp;&nbsp;&nbsp;2025-09-04
</div>
<div className={styles.publishDepartment}>
发布部门&nbsp;&nbsp;&nbsp;&nbsp;环保部门名称
</div>
</div>
{/* 第三行:操作按钮 */}
<div className={styles.actionButtons}>
<div
className={styles.actionButton}
onClick={() => showDrawer(mockRegulationDetail)}
style={{ cursor: 'pointer' }}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z" fill="#D8D8D8"/>
</svg>
</div>
<div className={styles.actionButton}>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z" fill="#D8D8D8"/>
</svg>
</div>
</div>
</div>
</div>
</div>
{/* 静态分页组件 */}
<div className={styles.paginationContainer}>
<div className={styles.pagination}>
<span className={styles.totalItems}>共85条</span>
{/* <select className={styles.pageSizeSelect}>
<option value="10">10 / page</option>
</select> */}
<button className={styles.pageButton}>&lt;</button>
<button className={styles.pageButton}>1</button>
<span className={styles.ellipsis}>...</span>
<button className={styles.pageButton}>4</button>
<button className={styles.pageButton}>5</button>
<button className={`${styles.pageButton} ${styles.active}`}>6</button>
<button className={styles.pageButton}>7</button>
<button className={styles.pageButton}>8</button>
<span className={styles.ellipsis}>...</span>
<button className={styles.pageButton}>50</button>
<button className={styles.pageButton}>&gt;</button>
</div>
</div>
{/* 抽屉详情 */}
<Drawer
title="法规详情"
width={600}
placement="right"
onClose={onCloseDrawer}
visible={drawerVisible}
maskClosable={true}
>
{selectedRegulation && (
<Descriptions bordered column={1} size="middle">
<Descriptions.Item label="法规名称">
{selectedRegulation.name}
</Descriptions.Item>
<Descriptions.Item label="发布日期">
{selectedRegulation.publishDate}
</Descriptions.Item>
<Descriptions.Item label="发布部门">
{selectedRegulation.department}
</Descriptions.Item>
<Descriptions.Item label="法规状态">
<Tag color="green">{selectedRegulation.status}</Tag>
</Descriptions.Item>
<Descriptions.Item label="法规类别">
{selectedRegulation.category}
</Descriptions.Item>
<Descriptions.Item label="版本号">
{selectedRegulation.version}
</Descriptions.Item>
<Descriptions.Item label="更新时间">
{selectedRegulation.updateTime}
</Descriptions.Item>
<Descriptions.Item label="法规内容">
<div style={{ whiteSpace: 'pre-wrap', maxHeight: '300px', overflow: 'auto' }}>
{selectedRegulation.content}
</div>
</Descriptions.Item>
</Descriptions>
)}
</Drawer>
</div>
);
};
export default RegulationCompliance;

@ -1,204 +0,0 @@
.regulationContainer {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.searchSection {
padding: 20px;
background-color: #fff;
:global {
.ant-form-inline {
display: flex;
.ant-form-item {
margin-right: 16px;
margin-bottom: 0;
}
.ant-form-item:nth-last-child(2) {
margin-left: auto;
}
.ant-form-item:last-child {
margin-right: 0;
}
}
.ant-form-item-label {
font-weight: 500;
label {
color: #666666;
font-size: 13px;
}
}
.ant-input::placeholder,
.ant-picker-input input::placeholder {
color: #00000040;
font-size: 13px;
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
padding: 20px;
.blocksContainer {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 20px;
margin-bottom: 20px;
}
.regulationBlock {
background-color: #fff;
// border: 1px solid #EEEEEE;
border-radius: 2px;
// padding: 8px 16px;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 120px;
}
.regulationTitle {
font-size: 14px;
font-weight: 500;
color: #333333;
padding: 8px 16px;
border: 1px solid #EEEEEE;
border-bottom: none;
margin-bottom: 0;
display: flex;
align-items: center;
}
.regulationInfo {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 15px;
border: 1px solid #EEEEEE;
border-bottom: none;
margin-bottom: 0;
}
.publishDate {
font-size: 12px;
color: #666666;
font-weight: 400;
margin-bottom: 6px;
}
.publishDepartment {
font-size: 12px;
color: #666666;
font-weight: 400;
}
.actionButtons {
display: flex;
justify-content: center;
gap: 8px;
width: 100%;
// margin-bottom: 0;
border: 1px solid #EEEEEE;
border-bottom: none;
// padding-top: 4px;
}
.actionButton {
width: calc(50% - 4px);
height: 24px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 2px;
transition: background-color 0.2s;
&:hover {
background-color: #f5f5f5;
}
}
}
.paginationContainer {
position: fixed;
bottom: 10px;
right: 10px;
z-index: 1000;
}
.pagination {
display: flex;
align-items: center;
gap: 8px;
// background: #fff;
padding: 8px 30px;
border-radius: 4px;
// box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.totalItems {
font-size: 12px;
color: #666;
margin-right: 8px;
}
.pageSizeSelect {
font-size: 12px;
border: 1px solid #d9d9d9;
border-radius: 2px;
padding: 2px 6px;
margin-right: 8px;
background: #fff;
}
.pageButton {
width: 28px;
height: 28px;
border: 1px solid #d9d9d9;
background: #fff;
color: #333;
font-size: 12px;
border-radius: 2px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
&:hover {
border-color: #00D48A;
color: #00D48A;
}
&.active {
background: #00D48A;
border-color: #00D48A;
color: #fff;
}
}
.ellipsis {
font-size: 12px;
color: #999;
padding: 0 4px;
}
}

@ -1,13 +0,0 @@
import React from 'react';
import styles from './SupervisionInspection.less';
const SupervisionInspection = () => {
return (
<div className={styles.container}>
<div className={styles.content}>待开发</div>
</div>
);
};
export default SupervisionInspection;

@ -1,15 +0,0 @@
.container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #fff;
.content {
font-size: 24px;
color: #999999;
font-weight: 400;
}
}

@ -1,803 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal, Select } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined, PlusOutlined, UploadOutlined, EditOutlined, DownloadOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './WasteGasPollutionControl.less';
import licence1 from '@/assets/business_envinformation/image1.svg';
import licence2 from '@/assets/business_envinformation/image2.svg';
import viewicon from '@/assets/business_envinformation/viewicon.svg';
import editicon from '@/assets/business_envinformation/editicon.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
const WasteGasPollutionControl = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 12,
});
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([
{
key: 1,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 2,
recordTime: '2025-09-02',
recorder: '王嘉琪',
reviewer: '赵子能',
facilityName: '复方水杨酸甲酯乳膏(曼秀雷敦)',
code: '65.177.48.116',
equipmentModel: '3D8d4ffa-bD7e-AffF-ED68-839DAFe74c27',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '14:10',
endRunTime: '03:06',
isNormal: '异常',
pollutantFlueGasVolume: '2',
pollutantFactor: '烟尘2',
treatmentEfficiency: '93.81',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '59.12',
pressure: '95',
emissionTime: '100',
powerConsumption: '34',
byproductName: '二氧化碳',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-08-24 05:16',
reagentAdditionAmount: '2',
},
{
key: 3,
recordTime: '2025-09-06',
recorder: '王嘉琪',
reviewer: '郑清予',
facilityName: '口炎清颗粒(大神)',
code: '111.161.135.125',
equipmentModel: '19b89E82-ae94-6bF7-2355-8DBC2d6a6009',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '12:26',
endRunTime: '03:26',
isNormal: '异常',
pollutantFlueGasVolume: '2',
pollutantFactor: '烟尘',
treatmentEfficiency: '91.40',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '59.95',
pressure: '90',
emissionTime: '95',
powerConsumption: '55',
byproductName: '二氧化碳',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-08-30 18:34',
reagentAdditionAmount: '2',
},
{
key: 4,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 5,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 6,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 7,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 8,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 9,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 10,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 11,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 12,
recordTime: '2025-08-29',
recorder: '赵喜行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
equipmentModel: '6Ddb888D-3d7A-305E-3372-109F7154Ad3A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantFlueGasVolume: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
exhaustStackHeight: '2',
exhaustTemperature: '50.48',
pressure: '100',
emissionTime: '115',
powerConsumption: '39',
byproductName: '氮气',
byproductProduction: '2',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
]);
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const start = (current - 1) * pageSize;
const end = start + pageSize;
return dataSource.slice(start, end);
};
const columns = [
{
title: (
<input
type="checkbox"
checked={selectedRowKeys.length === getCurrentPageData().length && getCurrentPageData().length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
/>
),
key: 'selection',
width: 60,
align: 'center',
fixed: 'left',
render: (_, record) => (
<input
type="checkbox"
checked={selectedRowKeys.includes(record.key)}
onChange={(e) => {
if (e.target.checked) {
setSelectedRowKeys([...selectedRowKeys, record.key]);
} else {
setSelectedRowKeys(selectedRowKeys.filter(key => key !== record.key));
}
}}
/>
),
},
{
title: '记录时间',
dataIndex: 'recordTime',
key: 'recordTime',
width: 120,
align: 'center',
},
{
title: '记录人',
dataIndex: 'recorder',
key: 'recorder',
width: 100,
align: 'center',
},
{
title: '审核人',
dataIndex: 'reviewer',
key: 'reviewer',
width: 100,
align: 'center',
},
{
title: '设施名称',
dataIndex: 'facilityName',
key: 'facilityName',
width: 200,
},
{
title: '编码',
dataIndex: 'code',
key: 'code',
width: 150,
},
{
title: '设备型号',
dataIndex: 'equipmentModel',
key: 'equipmentModel',
width: 200,
},
{
title: '参数名称',
dataIndex: 'parameterName',
key: 'parameterName',
width: 120,
align: 'center',
},
{
title: '设计值',
dataIndex: 'designValue',
key: 'designValue',
width: 100,
align: 'center',
},
{
title: '单位',
dataIndex: 'unit',
key: 'unit',
width: 80,
align: 'center',
},
{
title: '开始运行时间',
dataIndex: 'startRunTime',
key: 'startRunTime',
width: 120,
align: 'center',
},
{
title: '结束运行时间',
dataIndex: 'endRunTime',
key: 'endRunTime',
width: 120,
align: 'center',
},
{
title: '是否正常',
dataIndex: 'isNormal',
key: 'isNormal',
width: 100,
align: 'center',
render: (text) => (
<span style={{
color: text === '异常' ? '#ff4d4f' : '#52c41a',
backgroundColor: text === '异常' ? '#FFF1F0' : '#F6FFED',
border: text === '异常' ? '1px solid #FFA39E' : '1px solid #B7EB8F',
padding: '2px 8px',
borderRadius: '4px',
display: 'inline-block'
}}>
{text}
</span>
),
},
{
title: '污染物烟气量(m³/h)',
dataIndex: 'pollutantFlueGasVolume',
key: 'pollutantFlueGasVolume',
width: 150,
align: 'center',
},
{
title: '污染因子',
dataIndex: 'pollutantFactor',
key: 'pollutantFactor',
width: 120,
align: 'center',
},
{
title: '治理效率(%)',
dataIndex: 'treatmentEfficiency',
key: 'treatmentEfficiency',
width: 120,
align: 'center',
},
{
title: '数据来源',
dataIndex: 'dataSource',
key: 'dataSource',
width: 120,
align: 'center',
},
{
title: '排气筒高度(m)',
dataIndex: 'exhaustStackHeight',
key: 'exhaustStackHeight',
width: 130,
align: 'center',
},
{
title: '排气温度(℃)',
dataIndex: 'exhaustTemperature',
key: 'exhaustTemperature',
width: 130,
align: 'center',
},
{
title: '压力(kpa)',
dataIndex: 'pressure',
key: 'pressure',
width: 100,
align: 'center',
},
{
title: '排放时间(h)',
dataIndex: 'emissionTime',
key: 'emissionTime',
width: 120,
align: 'center',
},
{
title: '耗电量(kWh)',
dataIndex: 'powerConsumption',
key: 'powerConsumption',
width: 120,
align: 'center',
},
{
title: '副产物名称',
dataIndex: 'byproductName',
key: 'byproductName',
width: 120,
align: 'center',
},
{
title: '副产物产生量(t)',
dataIndex: 'byproductProduction',
key: 'byproductProduction',
width: 140,
align: 'center',
},
{
title: '药剂名称',
dataIndex: 'reagentName',
key: 'reagentName',
width: 120,
align: 'center',
},
{
title: '药剂添加时间',
dataIndex: 'reagentAdditionTime',
key: 'reagentAdditionTime',
width: 150,
align: 'center',
},
{
title: '药剂添加量(t)',
dataIndex: 'reagentAdditionAmount',
key: 'reagentAdditionAmount',
width: 140,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 140,
align: 'center',
fixed: 'right',
render: (_, record) => (
<Space size={18}>
{/* <img
src={viewicon}
alt="查看"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleView(record)}
/> */}
<img
src={editicon}
alt="编辑"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleEdit(record)}
/>
<img
src={downloadicon}
alt="下载"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDownload(record)}
/>
<img
src={deleteicon}
alt="删除"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDownload = (record) => {
console.log('下载:', record);
// TODO: 实现下载功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
const handleAdd = () => {
console.log('新增');
// TODO: 实现新增功能
};
const handleImport = () => {
console.log('导入');
// TODO: 实现导入功能
};
const handleQuery = () => {
console.log('查询');
// TODO: 实现查询功能
};
const handleTableChange = (pagination) => {
setPagination(pagination);
};
// 全选功能
const handleSelectAll = (checked) => {
if (checked) {
const allKeys = getCurrentPageData().map(item => item.key);
setSelectedRowKeys(allKeys);
} else {
setSelectedRowKeys([]);
}
};
// 批量操作
const handleBatchOperation = (operation) => {
console.log(`批量${operation}:`, selectedRowKeys);
// TODO: 实现批量操作功能
};
return (
<div className={styles.wasteGasContainer}>
{/* 第一块:操作按钮和筛选条件 */}
<div className={styles.searchSection}>
<div className={styles.leftButtons}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
className={styles.addButton}
>
新增
</Button>
<Button
// icon={<UploadOutlined />}
onClick={handleImport}
className={styles.importButton}
>
上传
</Button>
<Button
// icon={<UploadOutlined />}
onClick={() => handleBatchOperation('下载')}
className={styles.importButton}
disabled={selectedRowKeys.length === 0}
>
批量下载
</Button>
{/* <Button
onClick={() => handleBatchOperation('删除')}
className={styles.importButton}
disabled={selectedRowKeys.length === 0}
>
批量删除
</Button> */}
</div>
<div className={styles.rightControls}>
<span className={styles.filterLabel}>筛选条件</span>
<Select
placeholder="请选择"
style={{ width: 140, height: 28 }}
allowClear
className={styles.selectInput}
/>
<Input
placeholder="请输入"
style={{ width: 160, height: 28 }}
/>
<Button
onClick={handleQuery}
className={styles.queryButton}
>
查询
</Button>
<Button
onClick={handleReset}
className={styles.resetButton}
>
重置
</Button>
</div>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: {
...pagination,
total: dataSource.length,
showTotal: (total) => `${total}`,
showSizeChanger: false,
}
}}
onChange={handleTableChange}
scroll={{ x: 3000 }}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default WasteGasPollutionControl;

@ -1,205 +0,0 @@
.wasteGasContainer {
width: 100%;
height: 100%;
// padding: 20px;
background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.searchSection {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.leftButtons {
display: flex;
gap: 12px;
.addButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.importButton {
background-color: white;
border-color: #d9d9d9;
color: #333;
height: 32px;
border-radius: 4px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
}
.rightControls {
display: flex;
align-items: center;
gap: 12px;
.filterLabel {
color: #333;
font-size: 14px;
white-space: nowrap;
}
.queryButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 28px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.selectInput {
:global {
.ant-select-selector {
display: flex;
align-items: center;
height: 28px !important;
}
.ant-select-selection-item {
display: flex;
align-items: center;
line-height: 1;
}
.ant-select-selection-placeholder {
display: flex;
align-items: center;
line-height: 1;
}
}
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
padding: 0 20px 0;
overflow: hidden; // 只设置垂直隐藏
min-width: 0; // 确保可以收缩
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #FAFAFA;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
// 固定列样式
.ant-table-thead > tr > th.ant-table-cell-fix-left,
.ant-table-tbody > tr > td.ant-table-cell-fix-left {
background-color: #FAFAFA;
z-index: 1;
}
.ant-table-thead > tr > th.ant-table-cell-fix-right,
.ant-table-tbody > tr > td.ant-table-cell-fix-right {
background-color: #FAFAFA;
z-index: 1;
}
// 固定列阴影效果
.ant-table-cell-fix-left {
// box-shadow: 0px 0 4px 0px #00000040;
}
.ant-table-cell-fix-right {
// box-shadow: 0px 0 4px 0px #00000040;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
margin-top: 25px !important;
}
}
}
}

@ -1,746 +0,0 @@
import React, { useState } from 'react';
import { Form, Input, Button, DatePicker, Space, Modal, Select } from 'antd';
import { SearchOutlined, RedoOutlined, CloseOutlined, EyeOutlined, DeleteOutlined, PlusOutlined, UploadOutlined, EditOutlined, DownloadOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './WastewaterFacilityManagement.less';
import licence1 from '@/assets/business_envinformation/image1.svg';
import licence2 from '@/assets/business_envinformation/image2.svg';
import viewicon from '@/assets/business_envinformation/viewicon.svg';
import editicon from '@/assets/business_envinformation/editicon.svg';
import downloadicon from '@/assets/business_envinformation/downloadicon.svg';
import deleteicon from '@/assets/business_envinformation/deleteicon.svg';
const WastewaterFacilityManagement = () => {
const [form] = Form.useForm();
const [isModalVisible, setIsModalVisible] = useState(false);
const [currentImage, setCurrentImage] = useState(null);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 12,
});
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [dataSource, setDataSource] = useState([
{
key: 1,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 2,
recordTime: '2025-09-02',
recorder: '王嘉祺',
reviewer: '赵子峰',
facilityName: '复方水杨酸甲酯乳膏(曼秀雷敦)',
code: '65.177.48.116',
facilityModel: '3D8d4ffa-bD7e-AffF-ED68-839DAFe74c27',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '14:10',
endRunTime: '03:06',
isNormal: '异常',
pollutantOutletFlow: '2',
pollutantFactor: '烟尘2',
treatmentEfficiency: '93.81',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '59.12',
treatmentMethod: '95',
powerConsumption: '34',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-08-24 05:16',
reagentAdditionAmount: '2',
},
{
key: 3,
recordTime: '2025-09-06',
recorder: '王嘉琪',
reviewer: '郑清予',
facilityName: '口炎清颗粒(大神)',
code: '111.161.135.125',
facilityModel: '19b89EB2-ae94-6bF7-2355-6DBC2d6a6009',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '12:26',
endRunTime: '03:26',
isNormal: '异常',
pollutantOutletFlow: '2',
pollutantFactor: '烟尘',
treatmentEfficiency: '91.40',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '59.95',
treatmentMethod: '90',
powerConsumption: '56',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-08-30 18:34',
reagentAdditionAmount: '2',
},
{
key: 4,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 5,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 6,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 7,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 8,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 9,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 10,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 11,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
{
key: 12,
recordTime: '2025-08-29',
recorder: '赵吾行',
reviewer: '郑叶飞',
facilityName: '塞隆风湿酒(同仁堂)',
code: '35.236.217.212',
facilityModel: '6Ddb888D-3d7A-3e5E-3372-109F7154A03A',
parameterName: '重量',
designValue: '2',
unit: 't',
startRunTime: '00:46',
endRunTime: '03:55',
isNormal: '正常',
pollutantOutletFlow: '1',
pollutantFactor: '烟尘',
treatmentEfficiency: '95.32',
dataSource: '实时采集',
dischargeDestination: '2',
sludgeProduction: '50.48',
treatmentMethod: '100',
powerConsumption: '39',
reagentName: '乳酸钠葡萄糖',
reagentAdditionTime: '2025-09-01 07:53',
reagentAdditionAmount: '2',
},
]);
const getCurrentPageData = () => {
const { current, pageSize } = pagination;
const start = (current - 1) * pageSize;
const end = start + pageSize;
return dataSource.slice(start, end);
};
const columns = [
{
title: (
<input
type="checkbox"
checked={selectedRowKeys.length === getCurrentPageData().length && getCurrentPageData().length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
/>
),
key: 'selection',
width: 60,
align: 'center',
fixed: 'left',
render: (_, record) => (
<input
type="checkbox"
checked={selectedRowKeys.includes(record.key)}
onChange={(e) => {
if (e.target.checked) {
setSelectedRowKeys([...selectedRowKeys, record.key]);
} else {
setSelectedRowKeys(selectedRowKeys.filter(key => key !== record.key));
}
}}
/>
),
},
{
title: '记录时间',
dataIndex: 'recordTime',
key: 'recordTime',
width: 120,
align: 'center',
},
{
title: '记录人',
dataIndex: 'recorder',
key: 'recorder',
width: 100,
align: 'center',
},
{
title: '审核人',
dataIndex: 'reviewer',
key: 'reviewer',
width: 100,
align: 'center',
},
{
title: '设施名称',
dataIndex: 'facilityName',
key: 'facilityName',
width: 200,
},
{
title: '编码',
dataIndex: 'code',
key: 'code',
width: 150,
},
{
title: '设施型号',
dataIndex: 'facilityModel',
key: 'facilityModel',
width: 200,
},
{
title: '参数名称',
dataIndex: 'parameterName',
key: 'parameterName',
width: 120,
align: 'center',
},
{
title: '设计值',
dataIndex: 'designValue',
key: 'designValue',
width: 100,
align: 'center',
},
{
title: '单位',
dataIndex: 'unit',
key: 'unit',
width: 80,
align: 'center',
},
{
title: '开始运行时间',
dataIndex: 'startRunTime',
key: 'startRunTime',
width: 120,
align: 'center',
},
{
title: '结束运行时间',
dataIndex: 'endRunTime',
key: 'endRunTime',
width: 120,
align: 'center',
},
{
title: '是否正常',
dataIndex: 'isNormal',
key: 'isNormal',
width: 100,
align: 'center',
render: (text) => (
<span style={{
color: text === '异常' ? '#ff4d4f' : '#52c41a',
backgroundColor: text === '异常' ? '#FFF1F0' : '#F6FFED',
border: text === '异常' ? '1px solid #FFA39E' : '1px solid #B7EB8F',
padding: '2px 8px',
borderRadius: '4px',
display: 'inline-block'
}}>
{text}
</span>
),
},
{
title: '污染物出口流量(m³/h)',
dataIndex: 'pollutantOutletFlow',
key: 'pollutantOutletFlow',
width: 150,
align: 'center',
},
{
title: '污染因子',
dataIndex: 'pollutantFactor',
key: 'pollutantFactor',
width: 120,
align: 'center',
},
{
title: '治理效率(%)',
dataIndex: 'treatmentEfficiency',
key: 'treatmentEfficiency',
width: 120,
align: 'center',
},
{
title: '数据来源',
dataIndex: 'dataSource',
key: 'dataSource',
width: 120,
align: 'center',
},
{
title: '排放去向',
dataIndex: 'dischargeDestination',
key: 'dischargeDestination',
width: 120,
align: 'center',
},
{
title: '污泥产生量(t)',
dataIndex: 'sludgeProduction',
key: 'sludgeProduction',
width: 130,
align: 'center',
},
{
title: '处理方式',
dataIndex: 'treatmentMethod',
key: 'treatmentMethod',
width: 120,
align: 'center',
},
{
title: '耗电量(kWh)',
dataIndex: 'powerConsumption',
key: 'powerConsumption',
width: 120,
align: 'center',
},
{
title: '药剂名称',
dataIndex: 'reagentName',
key: 'reagentName',
width: 120,
align: 'center',
},
{
title: '药剂添加时间',
dataIndex: 'reagentAdditionTime',
key: 'reagentAdditionTime',
width: 150,
align: 'center',
},
{
title: '药剂添加量(t)',
dataIndex: 'reagentAdditionAmount',
key: 'reagentAdditionAmount',
width: 140,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 140,
align: 'center',
fixed: 'right',
render: (_, record) => (
<Space size={18}>
{/* <img
src={viewicon}
alt="查看"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleView(record)}
/> */}
<img
src={editicon}
alt="编辑"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleEdit(record)}
/>
<img
src={downloadicon}
alt="下载"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDownload(record)}
/>
<img
src={deleteicon}
alt="删除"
style={{ width: 16, height: 16, cursor: 'pointer' }}
onClick={() => handleDelete(record)}
/>
</Space>
),
},
];
const handleSearch = (values) => {
console.log('搜索参数:', values);
// TODO: 实现搜索功能
};
const handleReset = () => {
form.resetFields();
// TODO: 重置搜索
};
const handleView = (record) => {
console.log('查看:', record);
// TODO: 实现查看功能
};
const handleEdit = (record) => {
console.log('编辑:', record);
// TODO: 实现编辑功能
};
const handleDownload = (record) => {
console.log('下载:', record);
// TODO: 实现下载功能
};
const handleDelete = (record) => {
console.log('删除:', record);
// TODO: 实现删除功能
};
const handleAdd = () => {
console.log('新增');
// TODO: 实现新增功能
};
const handleImport = () => {
console.log('导入');
// TODO: 实现导入功能
};
const handleQuery = () => {
console.log('查询');
// TODO: 实现查询功能
};
const handleTableChange = (pagination) => {
setPagination(pagination);
};
// 全选功能
const handleSelectAll = (checked) => {
if (checked) {
const allKeys = getCurrentPageData().map(item => item.key);
setSelectedRowKeys(allKeys);
} else {
setSelectedRowKeys([]);
}
};
// 批量操作
const handleBatchOperation = (operation) => {
console.log(`批量${operation}:`, selectedRowKeys);
// TODO: 实现批量操作功能
};
return (
<div className={styles.wastewaterFacilityContainer}>
{/* 第一块:操作按钮和筛选条件 */}
<div className={styles.searchSection}>
<div className={styles.leftButtons}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={handleAdd}
className={styles.addButton}
>
新增
</Button>
<Button
// icon={<UploadOutlined />}
onClick={handleImport}
className={styles.importButton}
>
上传
</Button>
<Button
// icon={<UploadOutlined />}
onClick={() => handleBatchOperation('下载')}
className={styles.importButton}
disabled={selectedRowKeys.length === 0}
>
批量下载
</Button>
{/* <Button
onClick={() => handleBatchOperation('删除')}
className={styles.importButton}
disabled={selectedRowKeys.length === 0}
>
批量删除
</Button> */}
</div>
<div className={styles.rightControls}>
<span className={styles.filterLabel}>筛选条件</span>
<Select
placeholder="请选择"
style={{ width: 140, height: 28 }}
allowClear
className={styles.selectInput}
/>
<Input
placeholder="请输入"
style={{ width: 160, height: 28 }}
/>
<Button
onClick={handleQuery}
className={styles.queryButton}
>
查询
</Button>
<Button
onClick={handleReset}
className={styles.resetButton}
>
重置
</Button>
</div>
</div>
{/* 第二块:表格 */}
<div className={styles.tableSection}>
<StandardTable
columns={columns}
data={{
list: getCurrentPageData(),
pagination: {
...pagination,
total: dataSource.length,
showTotal: (total) => `${total}`,
showSizeChanger: false,
}
}}
onChange={handleTableChange}
scroll={{ x: 3000 }}
/>
</div>
{/* 图片弹窗 */}
<Modal
open={isModalVisible}
onCancel={() => setIsModalVisible(false)}
footer={null}
closeIcon={<CloseOutlined style={{ color: '#fff', fontSize: 20 }} />}
width="auto"
centered
styles={{
mask: { backgroundColor: '#10101080' },
content: { padding: 0, background: 'transparent', boxShadow: 'none' }
}}
>
{currentImage && <img src={currentImage} alt="许可证" style={{ width: '100%', display: 'block' }} />}
</Modal>
</div>
);
};
export default WastewaterFacilityManagement;

@ -1,206 +0,0 @@
.wastewaterFacilityContainer {
width: 100%;
height: 100%;
// padding: 20px;
background-color: #fff;
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
.searchSection {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.leftButtons {
display: flex;
gap: 12px;
.addButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 32px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 4px;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.importButton {
background-color: white;
border-color: #d9d9d9;
color: #333;
height: 32px;
border-radius: 4px;
&:hover {
border-color: #40a9ff;
color: #40a9ff;
}
}
}
.rightControls {
display: flex;
align-items: center;
gap: 12px;
.filterLabel {
color: #333;
font-size: 14px;
white-space: nowrap;
}
.queryButton {
background-color: #52c41a;
border-color: #52c41a;
color: white;
height: 28px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
background-color: #73d13d;
border-color: #73d13d;
}
}
.selectInput {
:global {
.ant-select-selector {
display: flex;
align-items: center;
height: 28px !important;
}
.ant-select-selection-item {
display: flex;
align-items: center;
line-height: 1;
}
.ant-select-selection-placeholder {
display: flex;
align-items: center;
line-height: 1;
}
}
}
}
}
.tableSection {
flex: 1;
display: flex;
flex-direction: column;
padding: 0 20px 0;
overflow: hidden; // 只设置垂直隐藏
min-width: 0; // 确保可以收缩
:global {
.ant-spin-nested-loading {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-spin-container {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
.ant-table-wrapper {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0;
padding: 0;
}
}
}
.ant-table {
font-size: 12px;
.ant-table-thead > tr > th {
background-color: #fafafa;
font-weight: 400;
color: #000000D9;
border-right: none;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr > td {
border-right: none;
color: #000000D9;
font-weight: 400;
text-align: center;
white-space: nowrap; // 防止换行
overflow: hidden;
text-overflow: ellipsis;
}
.ant-table-tbody > tr:hover > td {
background-color: #f5f5f5;
}
// 固定列样式
.ant-table-thead > tr > th.ant-table-cell-fix-left,
.ant-table-tbody > tr > td.ant-table-cell-fix-left {
background-color: #fafafa;
z-index: 1;
}
.ant-table-thead > tr > th.ant-table-cell-fix-right,
.ant-table-tbody > tr > td.ant-table-cell-fix-right {
background-color: #fafafa;
z-index: 1;
}
// 固定列阴影效果
.ant-table-cell-fix-left {
// box-shadow: 0px 0 4px 0px #00000040;
}
.ant-table-cell-fix-right {
// box-shadow: 0px 0 4px 0px #00000040;
}
a {
color: #1890ff;
text-decoration: none;
&:hover {
color: #40a9ff;
}
}
}
.ant-pagination {
text-align: right;
margin-top: 25px !important;
}
}
}
}
Loading…
Cancel
Save