628 lines
15 KiB
JavaScript
628 lines
15 KiB
JavaScript
import React, { useEffect, useState, useMemo, useRef } from 'react';
|
|
import { Card, message, Table, Space, Button, Spin, Tree } from 'antd';
|
|
import ToolBar from './toolbar.js';
|
|
import ToolBottom from './toolBottom.js';
|
|
import apiurl from '../../../models/apiurl'
|
|
import { xyt_httpget2, httpPostFile,httpGetFile } from "../../../utils/request";
|
|
import { exportFile } from '../../../utils/tools'
|
|
import { resJson } from './res.js';
|
|
import ReactEcharts from 'echarts-for-react';
|
|
import qsOption from './qsOption.js'
|
|
import dblOption from './dblOption.js'
|
|
import moment from 'moment';
|
|
export default function Czrz() {
|
|
const [newColumns, setNewColumns] = useState([])
|
|
const [tableList, setTableList] = useState([])
|
|
const [adcd, setAdcd] = useState('420000000000000')
|
|
const [treeList, setTreeList] = useState([])
|
|
const [selectedKeys, setSelectedKeys] = useState(['420000000000000'])
|
|
const [loading, setLoading] = useState(false)
|
|
const [SearchBottom, setSearchBottom] = useState(false)
|
|
const [adcdList, setAdcdList] = useState([])
|
|
const [dayArr, setDayArr] = useState([])
|
|
const [hbobj, setHbobj] = useState()
|
|
const [selectedObject, setSelectObject] = useState()
|
|
const [subTableData, setSubTableData] = useState([])
|
|
const qsoptions = useMemo(() => {
|
|
if (dayArr.length > 0 && selectedObject) {
|
|
return qsOption(dayArr, selectedObject, hbobj, adcdList)
|
|
} else {
|
|
return {}
|
|
}
|
|
}, [dayArr, selectedObject, hbobj, adcdList])
|
|
|
|
const dblOptions = useMemo(() => {
|
|
if (subTableData.length > 0 && SearchBottom) {
|
|
return dblOption(subTableData, SearchBottom.operTime)
|
|
} else {
|
|
return {}
|
|
}
|
|
}, [subTableData, SearchBottom])
|
|
const columns = [
|
|
{
|
|
title: '序号',
|
|
dataIndex: 'inx',
|
|
key: 'inx',
|
|
width: 80,
|
|
align: "center",
|
|
render: (text, record, index) => {
|
|
return index ? <span>{index}</span> : ''
|
|
}
|
|
},
|
|
{
|
|
title: '行政区划',
|
|
dataIndex: 'adnm',
|
|
key: 'adnm',
|
|
width: 120,
|
|
align: "center",
|
|
},
|
|
{
|
|
title: '总在线率',
|
|
dataIndex: 'onlineRate',
|
|
key: 'onlineRate',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record.ratelen > 0 ? (record.ratesum * 100 / record.ratelen).toFixed(2) : '-'}%
|
|
</span>
|
|
)
|
|
},
|
|
]
|
|
const detailsColumns = [
|
|
{
|
|
title: '序号',
|
|
dataIndex: 'inx',
|
|
key: 'inx',
|
|
width: 80,
|
|
align: "center",
|
|
render: (text, record, index) => {
|
|
return <span>{index + 1}</span>
|
|
}
|
|
},
|
|
{
|
|
title: '行政区划',
|
|
dataIndex: 'adnm',
|
|
key: 'adnm',
|
|
width: 100,
|
|
align: "center",
|
|
},
|
|
{
|
|
title: '雨量站',
|
|
children: [
|
|
{
|
|
title: '在线',
|
|
dataIndex: 'ontpcntpp',
|
|
key: 'ontpcntpp',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.ontpcnt?.pp}
|
|
</span>
|
|
)
|
|
},
|
|
{
|
|
title: '离线',
|
|
dataIndex: 'offtpcntpp',
|
|
key: 'offtpcntpp',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.offtpcnt?.pp}
|
|
</span>
|
|
)
|
|
},
|
|
]
|
|
},
|
|
{
|
|
title: '水位站',
|
|
children: [
|
|
{
|
|
title: '在线',
|
|
dataIndex: 'ontpcntzz',
|
|
key: 'ontpcntzz',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.ontpcnt?.zz}
|
|
</span>
|
|
)
|
|
},
|
|
{
|
|
title: '离线',
|
|
dataIndex: 'offtpcntzz',
|
|
key: 'offtpcntzz',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.offtpcnt?.zz}
|
|
</span>
|
|
)
|
|
},
|
|
]
|
|
},
|
|
{
|
|
title: '图像站',
|
|
children: [
|
|
{
|
|
title: '在线',
|
|
dataIndex: 'ontpcntwf',
|
|
key: 'ontpcntwf',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.ontpcnt?.wf}
|
|
</span>
|
|
)
|
|
},
|
|
{
|
|
title: '离线',
|
|
dataIndex: 'offtpcntwf',
|
|
key: 'offtpcntwf',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{record[SearchBottom?.operTime]?.offtpcnt?.wf}
|
|
</span>
|
|
)
|
|
},
|
|
]
|
|
},
|
|
{
|
|
title: '在线率',
|
|
dataIndex: 'onlineR',
|
|
key: 'onlineR',
|
|
width: 100,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{(record[SearchBottom?.operTime]?.rate * 100).toFixed(2)}%
|
|
</span>
|
|
)
|
|
},
|
|
{
|
|
title: '总在线率',
|
|
dataIndex: 'totalOnlineR',
|
|
key: 'totalOnlineR',
|
|
width: 150,
|
|
align: "center",
|
|
render: (text, record) => {
|
|
return <span>
|
|
{record.ratelen > 0 ? (record.ratesum * 100 / record.ratelen).toFixed(2) : '-'}%
|
|
</span>
|
|
|
|
}
|
|
|
|
},
|
|
]
|
|
const newDetailsColumns = useMemo(() => {
|
|
if (SearchBottom) {
|
|
const tmObj = {
|
|
title: SearchBottom?.operTime,
|
|
dataIndex: SearchBottom?.operTime,
|
|
key: SearchBottom?.operTime,
|
|
width: 100,
|
|
align: "center",
|
|
render: (v, r, i) => <span>{i + 1}</span>
|
|
}
|
|
return [tmObj, ...detailsColumns]
|
|
}
|
|
}, [SearchBottom])
|
|
const [searchVal, setSearchVal] = useState(false)
|
|
const width = useMemo(() => newColumns.reduce((total, cur) => total + (cur.width), 0), [newColumns]);
|
|
|
|
const getData = async (params) => {
|
|
setLoading(true)
|
|
try {
|
|
const res = await xyt_httpget2(apiurl.ptjs.czdbl, params)
|
|
if (res.code == 200) {
|
|
res.data['429000000000'] = { ...res.data["429021000000"], adcd: '429000000000' }
|
|
proccess(res.data)
|
|
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
const proccess = (results) => {
|
|
const dayarr = [];
|
|
const adlist = [];
|
|
let hbobj = {
|
|
adcd: '420000000000',
|
|
adnm: '湖北省',
|
|
ratesum: 0,
|
|
ratelen: 0
|
|
};
|
|
|
|
for (let adcd in results) {
|
|
let adobj = results[adcd];
|
|
|
|
adobj.adcd = adcd;
|
|
adobj.ratesum = 0;
|
|
adobj.ratelen = 0;
|
|
|
|
adlist.push(adobj);
|
|
|
|
if (/00000000$/.test(adcd)) {
|
|
for (let k in adobj) {
|
|
if (!/^[0-9]{4}/.test(k)) {
|
|
continue;
|
|
}
|
|
|
|
if (!(k in hbobj)) {
|
|
hbobj[k] = {
|
|
offtpcnt: {
|
|
pp: 0,
|
|
zz: 0,
|
|
wf: 0
|
|
},
|
|
ontpcnt: {
|
|
pp: 0,
|
|
zz: 0,
|
|
wf: 0
|
|
}
|
|
}
|
|
}
|
|
|
|
for (let onoff in adobj[k]) {
|
|
for (let sttp in adobj[k][onoff]) {
|
|
hbobj[k][onoff][sttp] += adobj[k][onoff][sttp];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dayarr.length == 0) {
|
|
for (let day in adobj) {
|
|
if (!/^[0-9]{4}/.test(day)) {
|
|
continue;
|
|
}
|
|
|
|
adobj.ratesum += adobj[day].rate;
|
|
adobj.ratelen += 1;
|
|
dayarr.push(day);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (let day in hbobj) {
|
|
if (!/^[0-9]{4}/.test(day)) {
|
|
continue;
|
|
}
|
|
|
|
let ciobj = hbobj[day];
|
|
|
|
let alloff = ciobj.offtpcnt.pp + ciobj.offtpcnt.zz + ciobj.offtpcnt.wf;
|
|
let allon = ciobj.ontpcnt.pp + ciobj.ontpcnt.zz + ciobj.ontpcnt.wf;
|
|
let rate = allon / (allon + alloff);
|
|
|
|
hbobj[day].rate = rate;
|
|
hbobj.ratesum += rate;
|
|
hbobj.ratelen += 1;
|
|
}
|
|
const newhbobj = hbobj;
|
|
adlist.sort(function (o1, o2) {
|
|
if (o1.adcd > o2.adcd) {
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
});
|
|
|
|
dayarr.sort(function (o1, o2) {
|
|
if (moment(o1).isBefore(moment(o2))) {
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
});
|
|
console.log("dayarr", dayarr);
|
|
setDayArr(dayarr)
|
|
const dayarrColumns = dayarr.map(it => ({
|
|
title: it,
|
|
dataIndex: it,
|
|
key: it,
|
|
width: 120,
|
|
align: "center",
|
|
render: (text, record) => (
|
|
<span>
|
|
{(record[it]?.rate * 100).toFixed(2)}%
|
|
</span>
|
|
)
|
|
}))
|
|
setNewColumns([...columns, ...dayarrColumns])
|
|
console.log("hbobj", newhbobj);
|
|
setHbobj(newhbobj);
|
|
setAdcdList(adlist);
|
|
filterdata(adlist, newhbobj)
|
|
}
|
|
|
|
const filterdata = (adlist, newhbobj) => {
|
|
let reg = /00000000$/;
|
|
const list = [];
|
|
|
|
for (let i = 0; i < adlist.length; i++) {
|
|
let obj = adlist[i];
|
|
let adcd = obj.adcd;
|
|
|
|
obj.ratesum = 0;
|
|
obj.ratelen = 0;
|
|
|
|
for (let day in obj) {
|
|
if (!/^[0-9]{4}/.test(day)) {
|
|
continue;
|
|
}
|
|
|
|
obj.ratesum += obj[day].rate;
|
|
obj.ratelen += 1;
|
|
}
|
|
if (reg.test(adcd)) {
|
|
list.push(obj);
|
|
}
|
|
}
|
|
if (list.length > 0) {
|
|
setLoading(false)
|
|
}
|
|
console.log("list", list);
|
|
console.log("newhbobj", newhbobj);
|
|
setTableList([newhbobj, ...list]);
|
|
}
|
|
|
|
const treeData = async (adcd) => {
|
|
const hbobj = {
|
|
adcd: "420000000000000",
|
|
adnm: "湖北省",
|
|
children: [],
|
|
}
|
|
try {
|
|
const res = await xyt_httpget2(apiurl.ptjs.treeList + adcd)
|
|
if (res.code == 200) {
|
|
hbobj.children = res.data;
|
|
setTreeList([hbobj]);
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
|
|
const updateTreeData = (list, key, children) => {
|
|
return list.map((node) => {
|
|
if (node.adcd === key) {
|
|
return {
|
|
...node,
|
|
children,
|
|
};
|
|
|
|
}
|
|
if (node.children) {
|
|
return {
|
|
...node,
|
|
children: updateTreeData(node.children, key, children),
|
|
};
|
|
}
|
|
return node;
|
|
})
|
|
}
|
|
|
|
// 山洪数据映射
|
|
const dataUpdate = (data) => {
|
|
return data.map(item => {
|
|
if (item.adcd == '420391000000000') {
|
|
item.adcd = '420381450000000';
|
|
item.adnm = '武当山';
|
|
}
|
|
if (item.adcd == '421303000000000') {
|
|
item.adcd = '421302000000000';
|
|
}
|
|
return item
|
|
})
|
|
}
|
|
const onLoadData = async ({ key, children }) => {
|
|
if (key.substr(4) != '00000000000') {
|
|
return
|
|
}
|
|
try {
|
|
const res = await xyt_httpget2(apiurl.ptjs.treeList + key)
|
|
if (res.code == 200) {
|
|
const filterData =res.data.filter(item => item.adcd != '420891000000000')
|
|
const results = dataUpdate(filterData)
|
|
setTreeList(origin =>
|
|
updateTreeData(origin, key, results.map(item => ({ ...item, isLeaf: true })))
|
|
)
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
const onSelect = (keys, arr) => {
|
|
console.log(keys, arr);
|
|
setSelectedKeys(keys)
|
|
setAdcd(keys[0])
|
|
}
|
|
|
|
// 子表格数据
|
|
const filterSondata = (selectedObj, type, adlist, selday) => {
|
|
const sellist = [];
|
|
if (selectedObj && type != 'province') {
|
|
let adreg = new RegExp('^' + selectedObj.adcd.substring(0, 4));
|
|
for (let si = 0; si < adlist.length; si++) {
|
|
let obj = adlist[si];
|
|
if (selectedObj.isBl) {
|
|
if ((adreg.test(obj.adcd) && obj.adcd == selectedObj.adcd)) {
|
|
sellist.push(obj);
|
|
}
|
|
} else if ((adreg.test(obj.adcd) && obj.adcd != selectedObj.adcd)) {
|
|
sellist.push(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selectedObj && type == 'province') {
|
|
let adreg = /00000000$/;
|
|
|
|
for (let si = 0; si < adlist.length; si++) {
|
|
let obj = adlist[si];
|
|
|
|
if ((adreg.test(obj.adcd)) && obj.adcd != selectedObj.adcd) {
|
|
sellist.push(obj);
|
|
}
|
|
}
|
|
}
|
|
sellist.sort(function (o1, o2) {
|
|
if (o1[selday]?.rate > o2[selday]?.rate) {
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
});
|
|
console.log("sellist", sellist);
|
|
|
|
setSubTableData(sellist)
|
|
}
|
|
// 下载测站离线表
|
|
const download = () => {
|
|
httpGetFile(apiurl.ptjs.export + '?' + `tm=${SearchBottom.operTime}`).then((res) => {
|
|
if (res) {
|
|
exportFile('测站离线表.xlsx', res.data)
|
|
}
|
|
})
|
|
}
|
|
useEffect(() => {
|
|
if (searchVal) {
|
|
const params = {
|
|
...searchVal
|
|
};
|
|
getData(params)
|
|
}
|
|
}, [searchVal])
|
|
|
|
useEffect(() => {
|
|
treeData("420000000000000")
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (adcd && SearchBottom && adcdList.length > 0 && hbobj) {
|
|
const subStrAdcd = adcd.substr(0, 12);
|
|
const selectObj = subStrAdcd == '420000000000' ? hbobj :
|
|
adcdList.find(item => {
|
|
if (item.adcd == subStrAdcd) {
|
|
return item
|
|
}
|
|
})
|
|
if (!selectObj) return
|
|
selectObj.isBl = selectObj?.adcd.substring(4) != '00000000' ? true : false
|
|
const type = selectObj?.adcd == '420000000000' ? 'province' : 'city'
|
|
// const type = 'province';
|
|
console.log("adcd", subStrAdcd);
|
|
setSelectObject(selectObj)
|
|
filterSondata(selectObj, type, adcdList, SearchBottom.operTime)
|
|
}
|
|
}, [adcd, SearchBottom, adcdList, hbobj])
|
|
|
|
|
|
return (
|
|
<div className='page'>
|
|
<div className='left'>
|
|
<Card>
|
|
{
|
|
treeList.length > 0 ?
|
|
<Tree
|
|
treeData={treeList}
|
|
fieldNames={{ title: 'adnm', key: "adcd" }}
|
|
loadData={onLoadData}
|
|
defaultExpandedKeys={["420000000000000"]}
|
|
selectedKeys={selectedKeys}
|
|
onSelect={onSelect}
|
|
/> :
|
|
<Spin size='large' style={{ margin: '7rem' }} />
|
|
}
|
|
|
|
</Card>
|
|
</div>
|
|
<div className='right' style={{ overflow: "auto" }}>
|
|
|
|
<Card style={{ display: 'flex', flexDirection: 'column' }}>
|
|
<div className='flex' style={{ alignItems: 'center', marginRight: 10, marginBottom: 20 }}>
|
|
<img src={require('../../../assets/images/panelTitle.png')} style={{ marginRight: 5 }}></img>
|
|
<span style={{ fontSize: 16, fontWeight: 'bold' }}>测站到报率</span>
|
|
</div>
|
|
<ToolBar
|
|
setToolVal={setSearchVal}
|
|
/>
|
|
<div style={{ display: 'flex', columnGap: 20, position: 'relative' }}>
|
|
{!loading &&
|
|
<>
|
|
<div style={{ position: 'absolute', left: '22%', fontSize: 16, fontWeight: 700 }}>到报率变化趋势</div>
|
|
<div style={{ position: 'absolute', right: '22%', fontSize: 16, fontWeight: 700 }}>日到报率详情</div></>
|
|
}
|
|
<div style={{ marginTop: 20, width: '50%' }}>
|
|
{
|
|
!loading ?
|
|
<>
|
|
<div style={{ width: '100%', height: 440 }}>
|
|
<ReactEcharts option={qsoptions} style={{ width: "100%", height: '100%' }} notMerge={true} />
|
|
</div>
|
|
<Table
|
|
columns={newColumns}
|
|
dataSource={tableList}
|
|
pagination={false}
|
|
scroll={{ x: width, y: "calc( 100vh - 500px )" }}
|
|
rowKey="inx"
|
|
/>
|
|
</>
|
|
: null}
|
|
</div>
|
|
<div className='bottom' style={{ marginTop: 20, width: '50%', position: "relative" }}>
|
|
{!loading &&
|
|
<>
|
|
<div style={{ position: 'absolute', right: 40, top: 20, zIndex: 10 }}>
|
|
<ToolBottom setToolVal={setSearchBottom} searchVal={searchVal} />
|
|
</div>
|
|
</>}
|
|
<div style={{ marginTop: 0, width: '100%' }}>
|
|
{
|
|
!loading ?
|
|
<>
|
|
<div style={{ width: '100%', height: 440 }}>
|
|
<ReactEcharts option={dblOptions} style={{ width: "100%", height: '100%' }} notMerge={true} />
|
|
</div>
|
|
<div style={{ position: "relative", width: '100%' }}>
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
right: 10,
|
|
top: -23,
|
|
cursor: 'pointer',
|
|
color: '#1677ff',
|
|
zIndex: 10
|
|
}}
|
|
onClick={download}>
|
|
下载测站离线表</div>
|
|
<Table
|
|
columns={detailsColumns}
|
|
dataSource={subTableData}
|
|
pagination={false}
|
|
scroll={{ x: 1200, y: "calc( 100vh - 600px )" }}
|
|
rowKey="inx"
|
|
/>
|
|
</div>
|
|
</> :
|
|
<Spin size="large" style={{ marginTop: '10rem' }} />
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|