diff --git a/src/assets/business_envmonitoring/alarm_icon.svg b/src/assets/business_envmonitoring/alarm_icon.svg
new file mode 100644
index 0000000..b54568a
--- /dev/null
+++ b/src/assets/business_envmonitoring/alarm_icon.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/business_envmonitoring/jhrk_icon.svg b/src/assets/business_envmonitoring/jhrk_icon.svg
new file mode 100644
index 0000000..c6f79dd
--- /dev/null
+++ b/src/assets/business_envmonitoring/jhrk_icon.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/assets/business_envmonitoring/ledger_icon.svg b/src/assets/business_envmonitoring/ledger_icon.svg
new file mode 100644
index 0000000..851179b
--- /dev/null
+++ b/src/assets/business_envmonitoring/ledger_icon.svg
@@ -0,0 +1,32 @@
+
diff --git a/src/assets/business_envmonitoring/ljcz_icon.svg b/src/assets/business_envmonitoring/ljcz_icon.svg
new file mode 100644
index 0000000..ac2c800
--- /dev/null
+++ b/src/assets/business_envmonitoring/ljcz_icon.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/assets/business_envmonitoring/normal_icon.svg b/src/assets/business_envmonitoring/normal_icon.svg
new file mode 100644
index 0000000..ffeee14
--- /dev/null
+++ b/src/assets/business_envmonitoring/normal_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/business_envmonitoring/pczt_bg.svg b/src/assets/business_envmonitoring/pczt_bg.svg
new file mode 100644
index 0000000..d50c11f
--- /dev/null
+++ b/src/assets/business_envmonitoring/pczt_bg.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/assets/business_envmonitoring/rzs_icon.svg b/src/assets/business_envmonitoring/rzs_icon.svg
new file mode 100644
index 0000000..6618dd8
--- /dev/null
+++ b/src/assets/business_envmonitoring/rzs_icon.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/business_envmonitoring/warning_icon.svg b/src/assets/business_envmonitoring/warning_icon.svg
new file mode 100644
index 0000000..652ae94
--- /dev/null
+++ b/src/assets/business_envmonitoring/warning_icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/business_envmonitoring/ysz_icon.svg b/src/assets/business_envmonitoring/ysz_icon.svg
new file mode 100644
index 0000000..1ce70ae
--- /dev/null
+++ b/src/assets/business_envmonitoring/ysz_icon.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/assets/business_envmonitoring/zcl_icon.svg b/src/assets/business_envmonitoring/zcl_icon.svg
new file mode 100644
index 0000000..ab13d36
--- /dev/null
+++ b/src/assets/business_envmonitoring/zcl_icon.svg
@@ -0,0 +1,20 @@
+
diff --git a/src/pages/business_envmonitoring/components/WasteMonitoring.js b/src/pages/business_envmonitoring/components/WasteMonitoring.js
index f53ce40..7853e1e 100644
--- a/src/pages/business_envmonitoring/components/WasteMonitoring.js
+++ b/src/pages/business_envmonitoring/components/WasteMonitoring.js
@@ -1,10 +1,55 @@
-import React from 'react';
+import React, { useState } from 'react';
import styles from './WasteMonitoring.less';
+import ProductWaste from './secondary_menu/ProductWaste'; // 产废管理
+import GeneralSolidWaste from './secondary_menu/GeneralSolidWaste'; // 一般固废
+// import HazardouSolidWaste from './secondary_menu/HazardouSolidWaste'; // 危固废
const WasteMonitoring = () => {
+ const [activeMenu, setActiveMenu] = useState('product');
+
+ const menuItems = [
+ { key: 'product', label: '产废管理' },
+ { key: 'general', label: '一般固废' },
+ { key: 'hazardou', label: '危固废' },
+ ];
+
+ const handleMenuClick = (key) => {
+ setActiveMenu(key);
+ };
+
+ const renderContent = () => {
+ switch (activeMenu) {
+ case 'product':
+ return ;
+ case 'general':
+ return ;
+ case 'hazardou':
+ return ;
+ default:
+ return ;
+ }
+ };
+
return (
- 开发中
+ {/* 左侧菜单 */}
+
+ {menuItems.map(item => (
+
handleMenuClick(item.key)}
+ >
+ {activeMenu === item.key &&
}
+
{item.label}
+
+ ))}
+
+
+ {/* 右侧内容区 */}
+
+ {renderContent()}
+
);
};
diff --git a/src/pages/business_envmonitoring/components/WasteMonitoring.less b/src/pages/business_envmonitoring/components/WasteMonitoring.less
index 6d0fee9..48579ef 100644
--- a/src/pages/business_envmonitoring/components/WasteMonitoring.less
+++ b/src/pages/business_envmonitoring/components/WasteMonitoring.less
@@ -2,40 +2,84 @@
width: 100%;
height: 100%;
display: flex;
- justify-content: center;
- align-items: center;
- background-color: #fff;
- border-radius: 4px;
- padding: 20px;
+ gap: 10px;
+ padding-left: 5px;
+ // padding-right: 5px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ background-color: #f5f5f5;
- .developingBox {
+ // 左侧菜单
+ .leftMenu {
display: flex;
flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 60px 80px;
- background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
- border-radius: 12px;
- box-shadow: 0 10px 30px rgba(240, 147, 251, 0.3);
-
- .developingText {
- font-size: 32px;
- font-weight: 600;
- color: #ffffff;
- letter-spacing: 4px;
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
- animation: pulse 2s ease-in-out infinite;
+ // gap: 1px;
+ flex-shrink: 0;
+ background-color: #fff;
+
+ .menuItem {
+ width: 100px;
+ 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;
+ }
}
}
-}
-@keyframes pulse {
- 0%, 100% {
- opacity: 1;
- transform: scale(1);
- }
- 50% {
- opacity: 0.8;
- transform: scale(1.05);
+ // 右侧内容区
+ .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;
+ }
}
}
+
diff --git a/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.js b/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.js
new file mode 100644
index 0000000..d4b096c
--- /dev/null
+++ b/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.js
@@ -0,0 +1,368 @@
+import React, { useRef, useEffect, useState } from 'react';
+import { Card, Row, Col, Select, Progress, Button, Tag } from 'antd';
+import ReactECharts from 'echarts-for-react';
+import { CheckCircleOutlined } from '@ant-design/icons';
+import './ProductWaste.less';
+import ledgerIcon from '@/assets/business_envmonitoring/ledger_icon.svg';
+import alarmIcon from '@/assets/business_envmonitoring/alarm_icon.svg';
+import warningIcon from '@/assets/business_envmonitoring/warning_icon.svg';
+import normalIcon from '@/assets/business_envmonitoring/normal_icon.svg';
+const ProductWaste = () => {
+ const leftRef = useRef(null);
+ const [leftHeight, setLeftHeight] = useState('auto');
+ useEffect(() => {
+ function updateHeight() {
+ if (leftRef.current) {
+ setLeftHeight(leftRef.current.offsetHeight);
+ }
+ }
+ updateHeight();
+ window.addEventListener('resize', updateHeight);
+ return () => window.removeEventListener('resize', updateHeight);
+ }, []);
+ const yearOptions = [
+ { label: '2024', value: '2024' },
+ { label: '2023', value: '2023' },
+ ];
+
+ const timeTypeOptions = [
+ { label: '月', value: 'month' },
+ { label: '季度', value: 'quarter' },
+ { label: '年', value: 'year' },
+ ];
+
+ const monthOptions = [
+ { label: '本月', value: 'month' },
+ { label: '本季度', value: 'quarter' },
+ { label: '本年', value: 'year' },
+ ];
+
+ // 折线图 option
+ const lineOption = {
+ tooltip: { trigger: 'axis' },
+ legend: {
+ data: ['产废量', '贮存量', '处置量'],
+ top: 0,
+ itemWidth: 18, // 图标宽度
+ itemHeight: 8 // 图标高度
+ },
+ grid: { left: 40, right: 20, top: 30, bottom: 20 },
+ xAxis: {
+ type: 'category',
+ data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+ axisLine: {
+ lineStyle: {
+ color: '#D5E2FF'
+ }
+ },
+ axisTick: {
+ show: false
+ },
+ axisLabel: {
+ color: '#333'
+ }
+ },
+ yAxis: {
+ type: 'value',
+ name: '(吨)',
+ splitLine: {
+ show: true,
+ lineStyle: {
+ type: 'dashed',
+ color: '#D5E2FF'
+ }
+ }
+ },
+ series: [
+ { name: '产废量', type: 'line', smooth: false, data: [20, 25, 18, 22, 30, 15, 28, 19, 24, 21, 27, 23], lineStyle: { color: '#FF8800', width: 1 }, itemStyle: { color: '#FF8800' } },
+ { name: '贮存量', type: 'line', smooth: false, data: [30, 28, 32, 25, 20, 27, 22, 29, 26, 31, 24, 28], lineStyle: { color: '#FFC403', width: 1 }, itemStyle: { color: '#FFC403' } },
+ { name: '处置量', type: 'line', smooth: false, data: [15, 10, 12, 18, 20, 13, 17, 14, 16, 11, 19, 12], lineStyle: { color: '#00AAFA', width: 1 }, itemStyle: { color: '#00AAFA' } },
+ ],
+ };
+
+ // 南丁格尔玫瑰图 option(数值大的扇叶半径更大)
+ const pieOption = {
+ color: ['#32AEED', '#4FD884', '#6D59FF', '#FF685D', '#D25BDD', '#FFB800'],
+ legend: {
+ orient: 'vertical',
+ right: '10%',
+ top: 'center',
+ itemWidth: 13,
+ itemHeight: 4,
+ textStyle: {
+ fontSize: 12,
+ color: '#333'
+ }
+ },
+ series: [{
+ name: '固废种类构成',
+ type: 'pie',
+ // radius: ['20%', '70%'],
+ center: ['30%', '45%'],
+ // roseType: 'radius', // 南丁格尔玫瑰图,扇区半径根据数值大小变化
+ avoidLabelOverlap: false,
+ label: {
+ show: true,
+ position: 'inside',
+ formatter: '{d}%', // 显示占比百分数
+ fontSize: 12,
+ color: '#ffffff',
+ fontWeight: 'bold'
+ },
+ emphasis: {
+ label: {
+ show: true,
+ fontSize: '14',
+ fontWeight: 'bold'
+ }
+ },
+ labelLine: {
+ show: true,
+ length: 10,
+ length2: 5,
+ lineStyle: {
+ color: '#999',
+ width: 1
+ }
+ },
+ data: [
+ { value: 45, name: '危险废物' },
+ { value: 10, name: '一般固废' },
+ { value: 13, name: '建筑垃圾' },
+ { value: 15, name: '医疗废物' },
+ { value: 8, name: '电子废物' },
+ { value: 9, name: '其他' }
+ ]
+ }]
+ };
+
+ // 危固废占比
+ const dangerPercent = 88;
+
+ // 固废点情况
+ const pointStatus = [
+ { type: '超期库存点', value: 8, color: '#FF6B6B', btn: '详情' },
+ { type: '预警库存点', value: 12, color: '#FFD666', btn: '详情' },
+ { type: '正常库存点', value: 8, color: '#52C41A', btn: '详情' },
+ ];
+
+ // 单位产废排名 option
+ const rankData = [
+ { name: 'xxx单位', value: 50.21 },
+ { name: 'xxx单位', value: 50.00 },
+ { name: 'xxx单位', value: 48.52 },
+ { name: 'xxx单位', value: 45.03 },
+ { name: 'xxx单位', value: 30.25 },
+ { name: 'xxx单位', value: 30.00 },
+ { name: 'xxx单位', value: 20.02 },
+ { name: 'xxx单位', value: 30.25 },
+ ];
+
+ const maxValue = Math.max(...rankData.map(item => item.value));
+
+ // 各类别固废量 option
+ const categoryBarOption = {
+ grid: { left: 40, right: 20, top: 10, bottom: 20 },
+ xAxis: {
+ type: 'category',
+ data: ['xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类', 'xxx类'],
+ axisTick: { show: false },
+ axisLine: { show: false }
+ },
+ yAxis: {
+ type: 'value',
+ splitLine: {
+ show: true,
+ lineStyle: {
+ type: 'dashed',
+ color: '#E9EBF1',
+ width: 1
+ }
+ }
+ },
+ series: [{
+ type: 'bar',
+ data: [20, 25, 18, 22, 30, 15, 28, 19, 24, 21, 27, 23],
+ barWidth: 10,
+ itemStyle: {
+ color: '#9F92FF',
+ barBorderRadius: [10, 10, 0, 0] // 顶部圆弧,底部直角
+ }
+ }]
+ };
+
+ // 台账信息管理按钮
+ const ledgerBtns = [
+ '产废单位及产废信息',
+ '危固废单位及产废信息',
+ '贮废点及贮废信息',
+ '固废种类信息',
+ '固废利用处置明细',
+ '固废运输单位',
+ ];
+ return (
+
+
+ {/* 左侧容器 */}
+
+
+ {/* 顶部折线图+右侧单位产废排名 */}
+
+
+
+
+
+
+
+
+ {/* 左侧危固废占比+中间饼图+右侧固废点情况 */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 贮废点情况
+
+ {/* 超限库存点 */}
+
+
+
+
+
+
超限库存点
+
8
+
+
+
+ {/* 预警库存点 */}
+
+
+
+
+
+
预警库存点
+
12
+
+
+
+ {/* 正常库存点 */}
+
+
+
+
+
+
正常库存点
+
8
+
+
+
+
+
+
+
+
+ {/* 右侧容器 */}
+
+
+
+ 单位产废排名
+
+
+
+ {rankData.map((item, idx) => (
+
+
+ {item.name}
+ {item.value}吨
+
+
+
+ ))}
+
+
+
+
+
+
+ {/* 下方左侧各类别固废量+右侧台账信息管理 */}
+
+
+
+
+
+
+
+
+ 台账信息管理
+
+ {ledgerBtns.map((btn, idx) => (
+
+
+
+
+
{btn}
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export default ProductWaste;
\ No newline at end of file
diff --git a/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.less b/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.less
new file mode 100644
index 0000000..557d32c
--- /dev/null
+++ b/src/pages/business_envmonitoring/components/secondary_menu/ProductWaste.less
@@ -0,0 +1,246 @@
+.productWasteDashboard {
+ background: #F6F8FB;
+}
+
+.pw-card {
+ background: #fff;
+ border-radius: 0px;
+ box-shadow: 0 2px 8px #f0f1f2;
+}
+
+.pw-card-top,
+.pw-card-middle,
+.pw-card-bottom {
+ height: 100%;
+}
+
+.pw-card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 8px;
+}
+
+.pw-title {
+ font-weight: 600;
+ font-size: 14px;
+ border-left: 4px solid #009D6F;
+ padding-left: 8px;
+ color: #333333
+}
+
+.pw-select-group {
+ display: flex;
+ align-items: center;
+}
+
+.pw-label {
+ margin-right: 8px;
+ font-size: 14px;
+ color: #333;
+}
+
+.pw-select {
+ width: 80px;
+}
+
+.pw-echarts-line,
+.pw-echarts-bar,
+.pw-echarts-pie {
+ width: 100%;
+}
+
+.pw-progress-circle-wrap {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 120px;
+ margin-top: 20px;
+}
+
+.pw-point-status-wrap {
+ margin-top: 16px;
+}
+
+.pw-point-status-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 12px;
+}
+
+.pw-point-status-tag {
+ font-weight: 600;
+ font-size: 14px;
+ width: 100px;
+ text-align: center;
+}
+
+.pw-point-status-value {
+ font-weight: 600;
+ font-size: 16px;
+ margin: 0 12px;
+}
+
+.pw-ledger-btns-wrap {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ margin-top: 16px;
+}
+
+.pw-ledger-btn {
+ background: #E6FFFB;
+ color: #52C41A;
+ border: none;
+ box-shadow: 0 2px 8px #e6fffb;
+ margin-bottom: 8px;
+}
+
+.pw-row-middle,
+.pw-row-bottom {
+ margin-top: 0 !important;
+}
+
+.pw-point-status-new-wrap {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ margin-top: 8px;
+}
+
+.pw-point-status-new {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ border-radius: 4px;
+ padding: 8px;
+ box-sizing: border-box;
+ background: #fff;
+ border: 1px solid #FFDFDF;
+ min-height: 48px;
+ transition: box-shadow 0.2s;
+}
+
+.pw-point-status-left {
+ display: flex;
+ align-items: center;
+ gap: 3px;
+}
+
+.pw-point-status-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+}
+
+.pw-point-status-type {
+ font-size: 12px;
+ font-weight: 500;
+ margin-right: 4px;
+}
+
+.pw-point-status-value {
+ font-size: 12px;
+ font-weight: bold;
+ margin-left: 2px;
+}
+
+.pw-point-status-btn {
+ min-width: 56px;
+ font-size: 12px !important;
+ font-weight: 500;
+ border-radius: 4px;
+ padding: 0 12px;
+ height: 32px;
+}
+
+.pw-point-status-over {
+ background: #FFF4F4;
+ border: 1px solid #FFDFDF;
+
+ .pw-point-status-btn {
+ color: #FF3B3B;
+ border-color: #FF6060;
+ background: #FFF4F4;
+ }
+}
+
+.pw-point-status-warning {
+ background: #FFF5EB;
+ border: 1px solid #FFDEBD;
+
+ .pw-point-status-btn {
+ color: #FF963B;
+ border-color: #FFAA60;
+ background: #FFF5EB;
+ }
+}
+
+.pw-point-status-normal {
+ background: #F3FFF5;
+ border: 1px solid #96FAA7;
+
+ .pw-point-status-btn {
+ color: #09D02B;
+ border-color: #20DD40;
+ background: #F3FFF5;
+ }
+}
+
+.ant-card-body {
+ padding: 16px !important;
+}
+
+.pw-ledger-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-row-gap: 30px;
+ grid-column-gap: 6px;
+ margin-top: 25px;
+}
+
+.pw-ledger-item {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ background: none;
+ box-shadow: none;
+}
+
+.pw-ledger-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 5px;
+}
+
+.pw-ledger-text {
+ font-size: 12px;
+ color: #333;
+ text-align: center;
+ font-weight: 500;
+ line-height: 1.2;
+ word-break: break-all;
+}
+
+.pw-rank-list {
+ margin-top: 8px;
+}
+.pw-rank-item {
+// margin-bottom: 8px;
+}
+.pw-rank-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 13px;
+ margin-bottom: 2px;
+}
+.pw-rank-name {
+ color: #333;
+}
+.pw-rank-value {
+ color: #888;
+}
\ No newline at end of file