feat():防汛实时监测开发

lsf-dev
李神峰 2025-06-12 17:59:36 +08:00
parent 2c6d12f71f
commit 12f3fa0878
12 changed files with 1048 additions and 10 deletions

View File

@ -148,7 +148,7 @@ const map = {
setView(id) {
let layerVisible = {};
const map = window.__mapref
if (id === 1 || id == 503) {
if ( id == 503) {
layerVisible = {
RealDrpLayer: true,
RealHDLayer: true,
@ -161,7 +161,21 @@ const map = {
Object.keys(DCPJ_TYPES).forEach(key => {
layerVisible['Dcpj_' + key + 'Layer'] = false;
});
} else if (id === 0) {
}if (id === 1 ) {
layerVisible = {
RealDrpLayer: true,
RealHDLayer: false,
RealSkLayer: false,
AdcdLayer: true,
PicStLayer: false,
RivlLayer: true,
WataLayer: false,
}
Object.keys(DCPJ_TYPES).forEach(key => {
layerVisible['Dcpj_' + key + 'Layer'] = false;
});
}
else if (id === 0) {
layerVisible = {
RealDrpLayer: false,
RealHDLayer: false,

View File

@ -32,8 +32,8 @@ export default function calcLayout(view, rightStack, hidePanels) {
} else if (view === 1) {
left = [
{ key: '天气' },
{ key: '河道实时水情', style: { height: '10rem', flexGrow: 1 } },
{ key: '水库监测', style: { height: '20rem', flexGrow: 1 } },
{ key: '雨情统计', style: { height: '29rem', flexGrow: 1 } },
{ key: '实时雨情', style: { height: '20rem', flexGrow: 1 } },
];
leftFullHeight = true;
} else if (view === 2) {
@ -253,8 +253,11 @@ export default function calcLayout(view, rightStack, hidePanels) {
rightFullHeight = true;
} else if (view === 1) {
right = [
{ key: '警报' },
{ key: '实时雨情', style: { height: '20rem', flexGrow: 1 } },
// { key: '警报' },
{ key: '水情统计', style: { height: '20rem', flexGrow: 1 } },
{ key: '河道实时水情', style: { height: '20rem', flexGrow: 1 } },
{ key: '水库监测', style: { height: '20rem', flexGrow: 1 } },
]
rightFullHeight = true;
} else if (view === 2) {

View File

@ -209,7 +209,7 @@ function DrpChart({ record }) {
useEffect(() => {
drpSearch(record.type, record.stcd, 'h', resultTm, record.countycode).then((data) => {
const newData = record.test ? demoData : data;
setData(newData || []);
setData(data);
});
}, [])

View File

@ -138,6 +138,8 @@ import Sbtj from './panels/Sbtj'
import Sbyj from './panels/Sbyj'
import Gsfhqx from './panels/Gsfhqx'
import JbqkRight from './panels/JbqkRight'
import RainSta from './panels/RainSta'
import DrpSta from './panels/DrpSta'
export default function PanelIndex({ name, style, ...params }) {
if (name === '天气') {
@ -345,6 +347,10 @@ export default function PanelIndex({ name, style, ...params }) {
return <Yawg style={style} />
} else if (name === "降雨分析") {
return <Drpfx style={style} />
} else if (name === "雨情统计") {
return <RainSta style={style} />
} else if (name === "水情统计") {
return <DrpSta style={style} />
} else if (name === "山洪预警") {
return <ShWarn style={style} />
} else if (name === "水库预警") {

View File

@ -11,8 +11,8 @@ const VIEWS = [
// { id: 0, title: '防洪形势', img: '/assets/menu/防洪形势.png' },
{ id: 8, title: '防洪形势', img: '/assets/menu/防洪形势.png' },
// { id: 9, title: '防洪形势', img: '/assets/menu/防洪形势.png' },
{ id: 1, title: '实时数据', img: '/assets/menu/实时数据.png' },
{ id: 2, title: '水利设施', img: '/assets/menu/水利设施.png' },
{ id: 1, title: '监测数据', img: '/assets/menu/实时数据.png' },
// { id: 2, title: '水利设施', img: '/assets/menu/水利设施.png' },
{ id: 5, title: '预报', img: '/assets/menu/降雨中心.png' },
{ id: 6, title: '预警', img: '/assets/menu/病险水库.png' },
{ id: 4, title: '预演', img: '/assets/menu/预警分析.png' },

View File

@ -207,7 +207,7 @@ function DrpSearch({ record }) {
drpSearch(record.type, record.stcd, 'h', searchTm.tm).then((data) => {
console.log(data,record);
const newData = record.test ? demoData : data;
setData(newData || []);
setData(data);
// setData(data);
})
}

View File

@ -0,0 +1,165 @@
import { Button, makeStyles } from '@material-ui/core';
import { Email } from '@material-ui/icons';
import React from 'react';
import { useDispatch } from 'react-redux';
import config from '../../../../config';
import { bxstr, drpRealGet, skRealGet } from '../../../../models/_/real';
import { strNumber } from '../../../../utils/tools';
import { InfoPopNames } from '../../InfoPops';
const useStyles = makeStyles({
root: {
padding: '1.5rem 0.75rem 0.75rem 0.75rem',
color: 'rgb(224, 246, 247)',
fontSize: '0.9rem',
lineHeight: '1.8rem',
},
titleDate: {
fontSize: '1.2rem',
margin: '0.2rem',
color: '#00deff',
},
number: {
color: '#ffd220',
fontSize: '1.2rem',
margin: '0.2rem',
},
sttype: {
color: '#92f0ff',
},
stname: {
fontWeight: 'bold',
fontSize: '1rem',
margin: '0.25rem',
cursor: 'pointer'
},
grid: {
display: 'flex',
justifyContent: 'space-around',
marginBottom: '1rem',
textAlign: 'center',
'& .value': {
fontSize: '1.8rem',
color: '#6fe9fd',
lineHeight: '2rem'
},
'& .key': {
fontSize: '0.8rem',
color: '#aaa',
},
},
action: {
textAlign: 'right',
color: '#fff',
}
})
export default function OverallContent({ data }) {
const classes = useStyles();
const dispatch = useDispatch();
const {
drpInfo,
skInfo,
tm1, tm2,
} = data || {};
const { h24, h1, h3, h6 } = drpInfo || {};
const _showRecord = (record, poptype) => {
if (record) {
const { lgtd, lttd } = record;
if (lgtd && lttd) {
dispatch.runtime.setFeaturePop({ type: poptype, properties: record, coordinates: [lgtd, lttd] });
dispatch.runtime.setCameraTarget({
center: [lgtd, lttd],
zoom: 15,
pitch: config.poiPitch,
});
}
}
}
const showRecord = (obj) => {
if (!obj) {
return;
}
const { type } = obj;
if (type === 'sk') {
skRealGet(obj.stcd).then((record) => {
_showRecord(record, InfoPopNames.RealSkPop)
})
} else {
drpRealGet(obj).then((record) => {
_showRecord(record, InfoPopNames.RealDrpPop)
});
}
}
const doBx = () => {
bxstr().then((data) => {
dispatch.runtime.setInfoDlg({
layerId: 'OverallSmtp',
properties: { txt: data }
})
});
}
return (
<div className={classes.root}>
<div className={classes.grid}>
<div>
<div className="value">{strNumber(h24?.drpStCount?.total, '-')}</div>
<div className="key">降雨测站</div>
</div>
<div>
<div className="value">{strNumber(skInfo?.aRz, '-')}</div>
<div className="key">超汛限水库</div>
</div>
<div>
<div className="value" style={{ fontSize: '1.5rem', cursor: 'pointer' }} onClick={() => showRecord(h24?.max)}>
{h24?.max?.stnm || '--'}
</div>
<div className="key">最大降雨测站</div>
</div>
</div>
<div>
<span className={classes.titleDate}>{tm1 || '-'}</span><span className={classes.titleDate}>{tm2 || '-'}</span>
24小时中共有<span className={classes.number}>{strNumber(h24?.drpStCount?.total, '-')}</span>
个降雨测站(<span className={classes.sttype}>山洪测站</span>
<span className={classes.number}>{strNumber(h24?.drpStCount?.sh, '-')}</span>
)其中最大降雨测站为<span onClick={() => showRecord(h24?.max)} className={classes.stname}>{h24?.max?.stnm || '-'}</span>
降雨量<span className={classes.number}>{strNumber(h24?.max?.value, '-')}</span>mm
{h24?.cntDrp10 > 0 && (<><span className={classes.sttype}>10mm以下</span><span className={classes.number}>{strNumber(h24?.cntDrp10, '-')}</span></>)}
{h24?.cntDrp25 > 0 && (<><span className={classes.sttype}>10mm至25mm</span><span className={classes.number}>{strNumber(h24?.cntDrp25, '-')}</span></>)}
{h24?.cntDrp50 > 0 && (<><span className={classes.sttype}>25mm至50mm</span><span className={classes.number}>{strNumber(h24?.cntDrp50, '-')}</span></>)}
{h24?.cntDrp100 > 0 && (<><span className={classes.sttype}>50mm至100mm</span><span className={classes.number}>{strNumber(h24?.cntDrp100, '-')}</span></>)}
{h24?.cntDrp250 > 0 && (<><span className={classes.sttype}>100mm至250mm</span><span className={classes.number}>{strNumber(h24?.cntDrp250, '-')}</span></>)}
{h24?.cntDrpg250 > 0 && (<><span className={classes.sttype}>大于250mm</span><span className={classes.number}>{strNumber(h24?.cntDrpg250, '-')}</span></>)}
{h1?.max?.value > 0 && (<><span className={classes.sttype}>前1小时</span><span onClick={() => showRecord(h1?.max)} className={classes.stname}>{h1?.max?.stnm}</span>({h1?.max?.value}mm)</>)}
{h3?.max?.value > 0 && (<><span className={classes.sttype}>前3小时</span><span onClick={() => showRecord(h3?.max)} className={classes.stname}>{h3?.max?.stnm}</span>({h3?.max?.value}mm)</>)}
{h6?.max?.value > 0 && (<><span className={classes.sttype}>前6小时</span><span onClick={() => showRecord(h6?.max)} className={classes.stname}>{h6?.max?.stnm}</span>({h6?.max?.value}mm)</>)}
{
!h1?.max?.value || !h3?.max?.value || !h6?.max?.value ? (
`${[!h1?.max?.value ? '1' : null, !h3?.max?.value ? '3' : null, !h6?.max?.value ? '6' : null].filter(Boolean).join(',')}小时无降雨。`
) : null
}
超汛限水位水库数为<span className={classes.number}>{strNumber(skInfo?.aRz, '-')}</span>
</div>
<div className={classes.action}>
<Button startIcon={<Email />} onClick={doBx} style={{ color: '#fff' }} size="small">报讯</Button>
</div>
</div>
)
}

View File

@ -0,0 +1,340 @@
import React, { useState,useEffect } from 'react';
import { OverallPromise } from '../../../../models/_/real';
import useRequest from '../../../../utils/useRequest';
import PanelBox from '../../components/PanelBox';
import OverallContent from './OverallContent';
import { makeStyles } from '@material-ui/core/styles';
import DpTableRow from '../../../../layouts/mui/DpTableRow';
import {
Box,
Typography,
Checkbox,
FormControlLabel,
ButtonGroup,
Button,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
IconButton,
Collapse
} from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import { useDispatch, useSelector } from 'react-redux';
import DpTableCell from '../../../../layouts/mui/DpTableCell';
import clsx from 'clsx';
import RemoveIcon from '@material-ui/icons/Remove';
import config from '../../../../config';
import { InfoPopNames } from '../../InfoPops';
const useStyles = makeStyles((theme) => ({
root: {
color: '#fff',
'& .MuiTypography-root': {
color: '#fff'
},
'& .MuiCheckbox-root': {
color: '#fff',
'&.Mui-checked': {
color: '#409eff'
}
},
'& .MuiButtonGroup-root': {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(3)
}
},
typeSection: {
marginBottom: theme.spacing(2)
},
timeButton: {
width:210,
color: '#fff',
borderColor: 'rgba(255,255,255,0.3)',
'&.MuiButton-contained': {
backgroundColor: '#409eff',
color: '#fff',
'&:hover': {
backgroundColor: '#409eff'
}
},
'&:hover': {
backgroundColor: 'rgba(255,255,255,0.1)'
}
},
table: {
'& .MuiTableCell-root': {
color: '#fff',
borderColor: 'rgba(255,255,255,0.1)'
}
},
expandButton: {
color: '#fff'
},
stationRow: {
'&:nth-of-type(odd)': {
backgroundColor: 'rgba(255,255,255,0.05)'
},
'&:hover': {
backgroundColor: 'rgba(255,255,255,0.1)'
}
},
warningRow: {
'&.pink': { backgroundColor: 'rgba(255,192,203,0.5)' },
'&.purple': { backgroundColor: 'rgba(147,112,219,0.5)' },
'&.blue': { backgroundColor: 'rgba(135,206,235,0.5)' },
'&.blue1': { backgroundColor: 'rgba(135,206,235,0.4)' },
'&.blue2': { backgroundColor: 'rgba(135,206,235,0.3)' },
'&.green': { backgroundColor: 'rgba(144,238,144,0.5)' }
},
expandedRow: {
'&.pink': { backgroundColor: 'rgba(255,192,203,0.1)' },
'&.purple': { backgroundColor: 'rgba(147,112,219,0.1)' },
'&.blue': { backgroundColor: 'rgba(135,206,235,0.1)' },
'&.green': { backgroundColor: 'rgba(144,238,144,0.1)' }
}
}));
export default function Overall({ style }) {
const dispatch = useDispatch();
const classes = useStyles();
const [types, setTypes] = useState({
mountain: true,
water: true,
weather: true,
reservoir: true
});
const [timeRange, setTimeRange] = useState('1h');
const [expanded, setExpanded] = useState({});
const handleTypeChange = (event) => {
setTypes({
...types,
[event.target.name]: event.target.checked
});
};
const stations = [
{ id: 'history', name: '历史极值站点', count: 0, color: 'pink' },
{ id: '100year', name: '100年一遇以上站点', count: 0, color: 'purple' },
{ id: '50year', name: '50年一遇以上站点', count: 0, color: 'blue' },
{ id: 'special', name: '特大暴雨站点', count: 0, color: 'blue1' },
{ id: 'heavy', name: '大暴雨站点', count: 0, color: 'blue2' },
{ id: 'storm', name: '暴雨站点', count: 1, color: 'green' }
];
const toggleExpand = (id) => {
setExpanded(prev => ({
...prev,
[id]: !prev[id]
}));
};
const drpData = [
{
"stcd": "61612910",
"stnm": "桃林河(阎河)",
"adcd": "421181000000000",
adnm: '阎家河镇桃林河村村民委员会',
zgrz: '55.67',
time: '2025-06-11 10:14至2025-06-12 10:14',
jjrz:'58.43',
"wscd": null,
"importancy": 0,
"lgtd": 115.087777777,
"lttd": 31.164444444,
"elev": null,
"hasRz": true,
"type": "sh",
"today": 21,
"h1": 15.5,
"h3": 21,
"h6": 21,
"h12": 21,
"h24": 21,
"h48": 21,
"tm": "2025-06-06T22:15:00.000Z",
"state": 1,
"warning": 0
},
{
"stcd": "61612150",
"stnm": "鹰山畈(黄土岗)",
"adcd": "421181000000000",
"wscd": null,
adnm: '黄士岗镇英山畈村村民委员会(雾港河村、鹰山畈村)',
zgrz: '77.00',
time: '2025-06-12 10:33',
jjrz:'78.98',
"importancy": 0,
"lgtd": 115.073611,
"lttd": 31.386667,
"elev": null,
"hasRz": true,
"type": "sh",
"today": 27,
"h1": 18.5,
"h3": 27,
"h6": 27,
"h12": 27,
"h24": 27,
"h48": 27,
"tm": "2025-06-06T22:00:00.000Z",
"state": 1,
"warning": 0
},
{
"stcd": "61613700",
"stnm": "四角门(宋铁二桥)",
"adcd": "421181000000000",
"wscd": null,
"importancy": 0,
"lgtd": 114.8291,
"lttd": 31.0754,
adnm: '铁门岗乡大庙岗村村民委员会(四角门村、大庙岗村、大店村、肖上湾村)',
zgrz: '27.57',
time: '2025-06-11 10:14至2025-06-12 10:14',
jjrz:'34.86',
"elev": null,
"hasRz": true,
"type": "sh",
"today": 3.5,
"h1": 2,
"h3": 3.5,
"h6": 3.5,
"h12": 3.5,
"h24": 3.5,
"h48": 3.5,
"tm": "2025-06-06T22:00:00.000Z",
"state": 1,
"warning": 0
},
{
"stcd": "61614460",
"stnm": "项生(宋埠)",
"adcd": "421181000000000",
"wscd": null,
"importancy": 0,
adnm: '宋埠镇项生村村民委员会',
zgrz: '21.93',
time: '2025-06-11 10:14至2025-06-12 10:14',
jjrz:'23.65',
"lgtd": 114.798056,
"lttd": 31.058611,
"elev": null,
"hasRz": true,
"type": "sh",
"today": 4.5,
"h1": 2,
"h3": 4.5,
"h6": 4.5,
"h12": 4.5,
"h24": 4.5,
"h48": 4.5,
"tm": "2025-06-06T22:00:00.000Z",
"state": 1,
"warning": 0
},
]
const skData = []
const flyTo = (record) => {
const { lgtd, lttd } = record;
if (lgtd && lttd) {
dispatch.runtime.setFeaturePop({ type: InfoPopNames.RealDrpPop, properties: record, coordinates: [lgtd, lttd] });
dispatch.runtime.setCameraTarget({
center: [lgtd, lttd + config.poiPositionOffsetY.hd],
zoom: config.poiPositionZoom.hd,
pitch: config.poiPitch,
});
}
}
const [type, setType] = useState('1h')
const [data, setData] = useState([])
useEffect(() => {
const newArr = timeRange == '3h' ? skData : drpData;
setData(newArr)
}, [timeRange])
return (
<PanelBox
style={style}
title="水情统计"
color="green"
extra={
<span className="button-group">
{
['h1', 'h3', 'h6', 'h12', 'h24'].map(key => (
<span key={key} className={clsx({ active: type === key })} onClick={() => setType(key)}>{key}</span>
))
}
</span>
}
>
<Box className={classes.root}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<ButtonGroup variant="outlined">
{[
{ value: '1h', label: '河道水情' },
{ value: '3h', label: '水库水情' },
].map((item) => (
<Button
key={item.value}
className={classes.timeButton}
onClick={() => {
if (item.value == '1h' || item.value == '3h') {
setTimeRange(item.value)
}
}}
variant={timeRange === item.value ? 'contained' : 'outlined'}
style={{ padding: '5px 10px' }}
>
{item.label}
</Button>
))}
</ButtonGroup>
</div>
</Box>
<TableContainer style={{ height: '70%' }}>
<Table size="small" stickyHeader>
<TableHead >
<DpTableRow>
<DpTableCell style={{ minWidth: '3rem' }} align='center'>序号</DpTableCell>
<DpTableCell style={{minWidth: '8rem' }} align='center'>站名</DpTableCell>
<DpTableCell style={{ minWidth: '8rem' }} align='center'>政区</DpTableCell>
<DpTableCell style={{ minWidth: '8rem' }} align='center'>最高水位(m)</DpTableCell>
<DpTableCell style={{ minWidth: '16rem' }} align='center'>发生时间</DpTableCell>
<DpTableCell style={{ minWidth: '8rem' }} align='center'>警戒水位(m)</DpTableCell>
{/* <DpTableCell style={{ width: '15%' }}>所属政区</DpTableCell> */}
</DpTableRow>
</TableHead>
<TableBody>
{
data.map((item,i) => (
<DpTableRow key={item.stcd} onClick={() => flyTo(item)}>
<DpTableCell align='center'>{i + 1}</DpTableCell>
<DpTableCell align='center'>{item.stnm}</DpTableCell>
<DpTableCell align='center'>
<div
className="table-ellipsis cursor-pointer"
title={item.adnm}
>{item.adnm}</div>
</DpTableCell>
<DpTableCell align='center'>{item.zgrz}</DpTableCell>
<DpTableCell align='center'>{item.time}</DpTableCell>
<DpTableCell align='center'>{item.jjrz}</DpTableCell>
</DpTableRow>
))
}
</TableBody>
</Table>
</TableContainer>
</PanelBox>
)
}

View File

@ -0,0 +1,38 @@
.dppanel-overall {
padding: 0.75rem;
color: rgb(224, 246, 247);
font-size: 0.8rem;
line-height: 1.8rem;
.title-date {
font-size: 1.2rem;
margin: 0.2rem;
color: #00deff;
}
.number {
color: #ffd220;
font-size: 1.2rem;
margin: 0.2rem;
}
.sttype {
color: #92f0ff;
}
.stname {
font-weight: bold;
font-size: 1rem;
margin: 0.25rem;
}
.sycm {
height: 5rem;
padding-top: 0.75rem;
ul{ margin-left:-.5rem;margin-right:-.5rem; padding: .16rem 0;}
li{ float: left; width: 33.33%; text-align: center; position: relative}
li:before{ position:absolute; content: ""; height:30%; width: 1px; background: rgba(255,255,255,.1); right: 0; top: 15%;}
li:last-child:before{ width: 0;}
li h2{ font-size:2rem; color: #6fe9fd; margin: 0; font-family: 'electronicFont';margin-bottom: 0.5rem;}
li span{ font-size:1rem; color: #fff; opacity: .5;}
}
}

View File

@ -0,0 +1,165 @@
import { Button, makeStyles } from '@material-ui/core';
import { Email } from '@material-ui/icons';
import React from 'react';
import { useDispatch } from 'react-redux';
import config from '../../../../config';
import { bxstr, drpRealGet, skRealGet } from '../../../../models/_/real';
import { strNumber } from '../../../../utils/tools';
import { InfoPopNames } from '../../InfoPops';
const useStyles = makeStyles({
root: {
padding: '1.5rem 0.75rem 0.75rem 0.75rem',
color: 'rgb(224, 246, 247)',
fontSize: '0.9rem',
lineHeight: '1.8rem',
},
titleDate: {
fontSize: '1.2rem',
margin: '0.2rem',
color: '#00deff',
},
number: {
color: '#ffd220',
fontSize: '1.2rem',
margin: '0.2rem',
},
sttype: {
color: '#92f0ff',
},
stname: {
fontWeight: 'bold',
fontSize: '1rem',
margin: '0.25rem',
cursor: 'pointer'
},
grid: {
display: 'flex',
justifyContent: 'space-around',
marginBottom: '1rem',
textAlign: 'center',
'& .value': {
fontSize: '1.8rem',
color: '#6fe9fd',
lineHeight: '2rem'
},
'& .key': {
fontSize: '0.8rem',
color: '#aaa',
},
},
action: {
textAlign: 'right',
color: '#fff',
}
})
export default function OverallContent({ data }) {
const classes = useStyles();
const dispatch = useDispatch();
const {
drpInfo,
skInfo,
tm1, tm2,
} = data || {};
const { h24, h1, h3, h6 } = drpInfo || {};
const _showRecord = (record, poptype) => {
if (record) {
const { lgtd, lttd } = record;
if (lgtd && lttd) {
dispatch.runtime.setFeaturePop({ type: poptype, properties: record, coordinates: [lgtd, lttd] });
dispatch.runtime.setCameraTarget({
center: [lgtd, lttd],
zoom: 15,
pitch: config.poiPitch,
});
}
}
}
const showRecord = (obj) => {
if (!obj) {
return;
}
const { type } = obj;
if (type === 'sk') {
skRealGet(obj.stcd).then((record) => {
_showRecord(record, InfoPopNames.RealSkPop)
})
} else {
drpRealGet(obj).then((record) => {
_showRecord(record, InfoPopNames.RealDrpPop)
});
}
}
const doBx = () => {
bxstr().then((data) => {
dispatch.runtime.setInfoDlg({
layerId: 'OverallSmtp',
properties: { txt: data }
})
});
}
return (
<div className={classes.root}>
<div className={classes.grid}>
<div>
<div className="value">{strNumber(h24?.drpStCount?.total, '-')}</div>
<div className="key">降雨测站</div>
</div>
<div>
<div className="value">{strNumber(skInfo?.aRz, '-')}</div>
<div className="key">超汛限水库</div>
</div>
<div>
<div className="value" style={{ fontSize: '1.5rem', cursor: 'pointer' }} onClick={() => showRecord(h24?.max)}>
{h24?.max?.stnm || '--'}
</div>
<div className="key">最大降雨测站</div>
</div>
</div>
<div>
<span className={classes.titleDate}>{tm1 || '-'}</span><span className={classes.titleDate}>{tm2 || '-'}</span>
24小时中共有<span className={classes.number}>{strNumber(h24?.drpStCount?.total, '-')}</span>
个降雨测站(<span className={classes.sttype}>山洪测站</span>
<span className={classes.number}>{strNumber(h24?.drpStCount?.sh, '-')}</span>
)其中最大降雨测站为<span onClick={() => showRecord(h24?.max)} className={classes.stname}>{h24?.max?.stnm || '-'}</span>
降雨量<span className={classes.number}>{strNumber(h24?.max?.value, '-')}</span>mm
{h24?.cntDrp10 > 0 && (<><span className={classes.sttype}>10mm以下</span><span className={classes.number}>{strNumber(h24?.cntDrp10, '-')}</span></>)}
{h24?.cntDrp25 > 0 && (<><span className={classes.sttype}>10mm至25mm</span><span className={classes.number}>{strNumber(h24?.cntDrp25, '-')}</span></>)}
{h24?.cntDrp50 > 0 && (<><span className={classes.sttype}>25mm至50mm</span><span className={classes.number}>{strNumber(h24?.cntDrp50, '-')}</span></>)}
{h24?.cntDrp100 > 0 && (<><span className={classes.sttype}>50mm至100mm</span><span className={classes.number}>{strNumber(h24?.cntDrp100, '-')}</span></>)}
{h24?.cntDrp250 > 0 && (<><span className={classes.sttype}>100mm至250mm</span><span className={classes.number}>{strNumber(h24?.cntDrp250, '-')}</span></>)}
{h24?.cntDrpg250 > 0 && (<><span className={classes.sttype}>大于250mm</span><span className={classes.number}>{strNumber(h24?.cntDrpg250, '-')}</span></>)}
{h1?.max?.value > 0 && (<><span className={classes.sttype}>前1小时</span><span onClick={() => showRecord(h1?.max)} className={classes.stname}>{h1?.max?.stnm}</span>({h1?.max?.value}mm)</>)}
{h3?.max?.value > 0 && (<><span className={classes.sttype}>前3小时</span><span onClick={() => showRecord(h3?.max)} className={classes.stname}>{h3?.max?.stnm}</span>({h3?.max?.value}mm)</>)}
{h6?.max?.value > 0 && (<><span className={classes.sttype}>前6小时</span><span onClick={() => showRecord(h6?.max)} className={classes.stname}>{h6?.max?.stnm}</span>({h6?.max?.value}mm)</>)}
{
!h1?.max?.value || !h3?.max?.value || !h6?.max?.value ? (
`${[!h1?.max?.value ? '1' : null, !h3?.max?.value ? '3' : null, !h6?.max?.value ? '6' : null].filter(Boolean).join(',')}小时无降雨。`
) : null
}
超汛限水位水库数为<span className={classes.number}>{strNumber(skInfo?.aRz, '-')}</span>
</div>
<div className={classes.action}>
<Button startIcon={<Email />} onClick={doBx} style={{ color: '#fff' }} size="small">报讯</Button>
</div>
</div>
)
}

View File

@ -0,0 +1,269 @@
import React, { useState } from 'react';
import { OverallPromise } from '../../../../models/_/real';
import useRequest from '../../../../utils/useRequest';
import PanelBox from '../../components/PanelBox';
import OverallContent from './OverallContent';
import { makeStyles } from '@material-ui/core/styles';
import { InfoPopNames } from '../../InfoPops';
import {
Box,
Typography,
Checkbox,
FormControlLabel,
ButtonGroup,
Button,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
IconButton,
Collapse
} from '@material-ui/core';
import AddIcon from '@material-ui/icons/Add';
import { useDispatch, useSelector } from 'react-redux';
import DpTableCell from '../../../../layouts/mui/DpTableCell';
import clsx from 'clsx';
import RemoveIcon from '@material-ui/icons/Remove';
import config from '../../../../config';
const useStyles = makeStyles((theme) => ({
root: {
color: '#fff',
'& .MuiTypography-root': {
color: '#fff'
},
'& .MuiCheckbox-root': {
color: '#fff',
'&.Mui-checked': {
color: '#409eff'
}
},
'& .MuiButtonGroup-root': {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(3)
}
},
typeSection: {
marginBottom: theme.spacing(2)
},
timeButton: {
width:210,
color: '#fff',
borderColor: 'rgba(255,255,255,0.3)',
'&.MuiButton-contained': {
backgroundColor: '#409eff',
color: '#fff',
'&:hover': {
backgroundColor: '#409eff'
}
},
'&:hover': {
backgroundColor: 'rgba(255,255,255,0.1)'
}
},
table: {
'& .MuiTableCell-root': {
color: '#fff',
borderColor: 'rgba(255,255,255,0.1)'
}
},
expandButton: {
color: '#fff'
},
stationRow: {
'&:nth-of-type(odd)': {
backgroundColor: 'rgba(255,255,255,0.05)'
},
'&:hover': {
backgroundColor: 'rgba(255,255,255,0.1)'
}
},
warningRow: {
'&.pink': { backgroundColor: 'rgba(255,192,203,0.5)' },
'&.purple': { backgroundColor: 'rgba(147,112,219,0.5)' },
'&.blue': { backgroundColor: 'rgba(135,206,235,0.5)' },
'&.blue1': { backgroundColor: 'rgba(135,206,235,0.4)' },
'&.blue2': { backgroundColor: 'rgba(135,206,235,0.3)' },
'&.green': { backgroundColor: 'rgba(144,238,144,0.5)' }
},
expandedRow: {
'&.pink': { backgroundColor: 'rgba(255,192,203,0.1)' },
'&.purple': { backgroundColor: 'rgba(147,112,219,0.1)' },
'&.blue': { backgroundColor: 'rgba(135,206,235,0.1)' },
'&.green': { backgroundColor: 'rgba(144,238,144,0.1)' }
}
}));
export default function Overall({ style }) {
const dispatch = useDispatch();
const classes = useStyles();
const [types, setTypes] = useState({
mountain: true,
water: true,
weather: true,
reservoir: true
});
const [timeRange, setTimeRange] = useState('1h');
const [expanded, setExpanded] = useState({});
const handleTypeChange = (event) => {
setTypes({
...types,
[event.target.name]: event.target.checked
});
};
const stations = [
{ id: 'history', name: '历史极值站点', count: 0, color: 'pink' },
{ id: '100year', name: '100年一遇以上站点', count: 0, color: 'purple' },
{ id: '50year', name: '50年一遇以上站点', count: 0, color: 'blue' },
{ id: 'special', name: '特大暴雨站点', count: 0, color: 'blue1' },
{ id: 'heavy', name: '大暴雨站点', count: 0, color: 'blue2' },
{ id: 'storm', name: '暴雨站点', count: 1, color: 'green' }
];
const toggleExpand = (id) => {
setExpanded(prev => ({
...prev,
[id]: !prev[id]
}));
};
const drpData = [
{
"stcd": "Q9111",
"stnm": "福田河",
"adcd": "421181000000000",
'test':1,
"wscd": null,
"importancy": 0,
"lgtd": 115.0944,
"lttd": 31.4747,
"elev": null,
"hasRz": true,
"type": "qx",
"today": 50.3,
"h1": 50.2,
"h3": 50.2,
"h6": 50.2,
"h12": 50.2,
"h24": 50.3,
"tm": "2025-06-06T22:00:00.000Z",
"state": 1,
"warning": 0
},
]
const flyTo = (record) => {
const { lgtd, lttd } = record;
if (lgtd && lttd) {
dispatch.runtime.setFeaturePop({ type: InfoPopNames.RealDrpPop, properties: record, coordinates: [lgtd, lttd] });
dispatch.runtime.setCameraTarget({
center: [lgtd, lttd + config.poiPositionOffsetY.hd],
zoom: config.poiPositionZoom.hd,
pitch: config.poiPitch,
});
}
}
const [type, setType] = useState('h24')
return (
<PanelBox
style={style}
title="雨情统计"
color="green"
extra={
<span className="button-group">
{
['h1', 'h3', 'h6', 'h12', 'h24'].map(key => (
<span key={key} className={clsx({ active: type === key })} onClick={() => setType(key)}>{key}</span>
))
}
</span>
}
>
<Box className={classes.root}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<ButtonGroup variant="outlined">
{[
{ value: '1h', label: '政区' },
{ value: '3h', label: '流域' },
].map((item) => (
<Button
key={item.value}
className={classes.timeButton}
onClick={() => {
if (item.value == '1h' || item.value == '3h') {
setTimeRange(item.value)
}
}}
variant={timeRange === item.value ? 'contained' : 'outlined'}
style={{ padding: '5px 10px' }}
>
{item.label}
</Button>
))}
</ButtonGroup>
</div>
<TableContainer >
<Table stickyHeader>
<TableHead >
<TableRow>
<DpTableCell style={{ width: '51%' }}>站名</DpTableCell>
<DpTableCell style={{ width: '30%' }}>累计雨量(mm)</DpTableCell>
{/* <DpTableCell style={{ width: '15%' }}>所属政区</DpTableCell> */}
<DpTableCell style={{ width: '20%' }}>{timeRange == '1h' ? '所属政区':'所属流域'}</DpTableCell>
</TableRow>
</TableHead>
<TableBody>
{stations.map((station) => (
<React.Fragment key={station.id}>
<TableRow
// className={classes.stationRow}
className={`${classes.warningRow} ${station.color}`}
>
<DpTableCell>
<Box display="flex" alignItems="center">
<IconButton
size="small"
className={classes.expandButton}
onClick={() => toggleExpand(station.id)}
>
{expanded[station.id] ? <RemoveIcon /> : <AddIcon />}
</IconButton>
{station.name}({station.count})
</Box>
</DpTableCell>
<DpTableCell></DpTableCell>
<DpTableCell></DpTableCell>
<DpTableCell></DpTableCell>
</TableRow>
<TableRow>
<DpTableCell colSpan={4} style={{ padding: 0 }}>
<Collapse in={expanded[station.id]} timeout="auto" unmountOnExit>
<Box className={`${classes.expandedRow} ${station.color}`}>
{/* 展开的详细内容可以在这里添加 */}{
station.id == 'storm' && drpData.map(item => (
<TableRow onClick={() =>flyTo(item)}>
<DpTableCell style={{ width: '53%' }}>{item.stnm}</DpTableCell>
<DpTableCell style={{ width: timeRange == '1h' ?'27%':"30%" }}>{item.today}</DpTableCell>
<DpTableCell style={{ width: timeRange == '1h' ?'20%':'17%' }}>{timeRange == '1h' ? '乘马岗镇':'浮桥河'}</DpTableCell>
</TableRow>
))
}
</Box>
</Collapse>
</DpTableCell>
</TableRow>
</React.Fragment>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
</PanelBox>
)
}

View File

@ -0,0 +1,38 @@
.dppanel-overall {
padding: 0.75rem;
color: rgb(224, 246, 247);
font-size: 0.8rem;
line-height: 1.8rem;
.title-date {
font-size: 1.2rem;
margin: 0.2rem;
color: #00deff;
}
.number {
color: #ffd220;
font-size: 1.2rem;
margin: 0.2rem;
}
.sttype {
color: #92f0ff;
}
.stname {
font-weight: bold;
font-size: 1rem;
margin: 0.25rem;
}
.sycm {
height: 5rem;
padding-top: 0.75rem;
ul{ margin-left:-.5rem;margin-right:-.5rem; padding: .16rem 0;}
li{ float: left; width: 33.33%; text-align: center; position: relative}
li:before{ position:absolute; content: ""; height:30%; width: 1px; background: rgba(255,255,255,.1); right: 0; top: 15%;}
li:last-child:before{ width: 0;}
li h2{ font-size:2rem; color: #6fe9fd; margin: 0; font-family: 'electronicFont';margin-bottom: 0.5rem;}
li span{ font-size:1rem; color: #fff; opacity: .5;}
}
}