feat(): 测站到报率开发

master
李神峰 2025-02-11 18:00:22 +08:00
parent 0a9a8176a0
commit 95b642324e
7 changed files with 12103 additions and 137 deletions

View File

@ -8,7 +8,7 @@ const shengUrl2 = 'service28080'
// const shengUrlPro = 'http://223.75.53.141:28080'
// const shengUrlPro = 'http://223.75.53.141:8000' //正式
const shengUrlPro = 'http://223.75.53.141:9001' //正式
const guishiPro = '/gunshiApp/ptjs'
const guishiPro = '/shzh/ptjstest'
// const shengUrlPro = 'http://223.75.53.141:9001'
@ -22,7 +22,8 @@ const jsapi = {
ptjs: {
czrz: shengUrlPro + '/prod-api/baseplat-system/operlog/hb/list',
czdbl: guishiPro + '/monitor/summary'
czdbl: guishiPro + '/monitor/summary',
treeList:shengUrlPro + "/prod-api/baseplat-basic/hb/village/getChild/"
},
service: {

View File

@ -273,7 +273,7 @@ const session = {
{
id:121, redirect: "/ptjs/czrz", parent_id: -1, name: "平台监视", type: 1, order: 1, children: [
{ id: 402, path: "/ptjs/czrz", parent_id: 500, name: "操作日志", type: 0, order: 1},
{ id: 403, path: "/ptjs/Czdbl", parent_id: 500, name: "测站到报率", type: 0, order: 1},
{ id: 403, path: "/ptjs/czdbl", parent_id: 500, name: "测站到报率", type: 0, order: 1},
]
},

View File

@ -51,13 +51,10 @@ module.exports = function (app) {
);
app.use(
'/gunshiApp/ptjs',
'/shzh/ptjstest',
createProxyMiddleware({
target: 'http://192.168.66.7:20019',
target: 'http://223.75.53.141:81',
changeOrigin: true,
pathRewrite: {
'^/gunshiApp/ptjs': '',
},
})
);
};

View File

@ -1,127 +1,439 @@
import React, { useEffect, useState, useMemo, useRef } from 'react';
import { Card, message, Table, Space, Button } from 'antd';
import { Card, message, Table, Space, Button, Spin, Tree } from 'antd';
import ToolBar from './toolbar.js';
import usePageTable from '../../../components/Crud/usePageTable.js'
import ToolBottom from './toolBottom.js';
import apiurl from '../../../models/apiurl'
import { createCrudService } from '../../../components/Crud/_';
import {xyt_httpget2} from "../../../utils/request"
import { xyt_httpget2 } from "../../../utils/request"
import { resJson } from './res.js';
import moment from 'moment';
export default function Czrz() {
const refModal = useRef();
const businessType = {
// 0: "其它",
1: "新增",
2: "修改",
3: "删除",
4: "授权",
5: "导出",
6: "导入",
7: "强退",
8: "生成代码",
9: "清空数据",
}
const operatorStatus = {
0: '正常',
1: '异常'
}
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 columns = [
{
title: '日志编号',
dataIndex: 'operId',
key: 'operId',
title: '序号',
dataIndex: 'inx',
key: 'inx',
width: 80,
align: "center",
render: (text, record, index) => {
return index ? <span>{index}</span> : ''
}
},
{
title: '行政区划',
dataIndex: 'adnm',
key: 'adnm',
width: 100,
align: "center",
},
{
title: '系统模块',
dataIndex: 'title',
key: 'title',
width: 120,
align: "center",
},
{
title: '操作类型',
dataIndex: 'businessType',
key: 'businessType',
title: '总在线率',
dataIndex: 'onlineRate',
key: 'onlineRate',
width: 100,
align: "center",
render: (text, record) => (
<span>
{businessType[text]}
{record.ratelen > 0 ? (record.ratesum * 100 / record.ratelen).toFixed(2) : '-'}%
</span>
)
},
{
title: '请求方式',
dataIndex: 'requestMethod',
key: 'requestMethod',
width: 100,
align: "center",
},
{
title: '操作人员',
dataIndex: 'operName',
key: 'operName',
width: 180,
align: "center",
},
{
title: '主机',
dataIndex: 'operIp',
key: 'operIp',
width: 180,
align: "center",
},
{
title: '操作地点',
dataIndex: 'operAddress',
key: 'operAddress',
width: 180,
align: "center",
},
{
title: '操作状态',
dataIndex: 'status',
key: 'status',
width: 100,
align: "center",
render: (text, record) => (
<span>
{operatorStatus[text]}
</span>
)
},
{
title: '操作日期',
dataIndex: 'operTime',
key: 'operTime',
width: 150,
align: "center",
},
{
title: '操作', key: 'action', dataIndex: 'action', width: 150, align: "center",
render: (v, r) => (
<Space size="middle">
<a onClick={() => command("view")(r)}>查看</a>
</Space>
)
},
]
const [searchVal, setSearchVal] = useState(false)
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const detailsColumns = [
{
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 { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.ptjs.czdbl).xyt_find_noCode);
const getData = async (params) => {
setLoading(true)
try {
const res = await xyt_httpget2(apiurl.ptjs.czdbl,params)
// debugger
const res = await xyt_httpget2(apiurl.ptjs.czdbl, params)
if (res.code == 200) {
proccess(res.data)
}
} catch (error) {
console.log(error);
}
}
const command = (type) => (row) => {
refModal.current.showView(row)
const [hbobj, setHbobj] = useState()
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) || adcd === '429021000000') {
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);
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) || adcd === '429021000000') {
list.push(obj);
}
}
if (list.length > 0) {
setLoading(false)
}
console.log("list", list);
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 onLoadData = async ({ key, children }) => {
if (key.substr(4) != '00000000000') {
return
}
try {
const res = await xyt_httpget2(apiurl.ptjs.treeList + key)
if (res.code == 200) {
setTreeList(origin =>
updateTreeData(origin, key, res.data.map(item => ({ ...item, isLeaf: true })))
)
}
} catch (error) {
console.log(error);
}
}
const onSelect = (keys,arr) => {
console.log(keys,arr);
setSelectedKeys(keys)
setAdcd(keys[0])
}
// 子表格数据
const [subTableData, setSubTableData] = useState([])
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 ((adreg.test(obj.adcd) && obj.adcd != selectedObj.adcd) ||
(selectedObj.adcd === '429021000000' && obj.adcd === '429021000000')) {
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 === '429021000000') && 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)
}
useEffect(() => {
if (searchVal) {
const params = {
@ -131,21 +443,79 @@ export default function Czrz() {
}
}, [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
}
})
const type = selectObj?.adcd == '420000000000' ? 'province':'city'
// const type = 'province';
console.log("adcd",subStrAdcd);
filterSondata(selectObj,type,adcdList,SearchBottom.operTime)
}
}, [adcd,SearchBottom,adcdList,hbobj])
return (
<div className='page'>
<div style={{width:'100%'}}>
<Card style={{ display: 'flex', flexDirection: 'column' }}>
<ToolBar
setToolVal={setSearchVal}
/>
<Table
columns={columns}
{...tableProps}
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
rowKey="inx"
/>
<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>
<div className='right'>
<Card style={{ display: 'flex', flexDirection: 'column' }}>
<ToolBar
setToolVal={setSearchVal}
/>
<div style={{ display: 'flex', justifyContent: 'center', marginTop: 20 }}>
{
!loading ?
<Table
columns={newColumns}
dataSource={tableList}
pagination={false}
scroll={{ x: width, y: "calc( 100vh - 600px )" }}
rowKey="inx"
/> : <Spin size="large" style={{ marginTop: '10rem' }} />}
</div>
<div className='bottom' style={{marginTop:20,width:'100%'}}>
<ToolBottom setToolVal={setSearchBottom} />
<div style={{ display: 'flex', marginTop: 20,width:'100%' }}>
{
newDetailsColumns &&
<Table
columns={newDetailsColumns}
dataSource={subTableData}
pagination={false}
scroll={{ x: 1200}}
rowKey="inx"
/>}
</div>
</div>
</Card>
</div>
</div>
)
}

11573
src/views/Ptjs/Czdbl/res.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
import dayjs from 'dayjs';
const ToolBottom = ({ setToolVal }) => {
const [form] = Form.useForm();
const onFinish = (values) => {
if (values.operTime) {
values.operTime = values.operTime ? dayjs(values.operTime).format('YYYY-MM-DD') : "";
}
setToolVal(values);
}
useEffect(() => {
const defaultValue = dayjs()
form.setFieldsValue({ operTime: defaultValue })
setToolVal({operTime:defaultValue.format('YYYY-MM-DD')})
}, []);
return (
<div className='pageToolBar'>
<Form form={form} onFinish={onFinish} size='Default' layout="inline">
<Form.Item label="监测日期" name="operTime">
<DatePicker
format='YYYY-MM-DD'
style={{ width: 150 }}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" size='Default'>查询</Button>
</Form.Item>
<Form.Item>
<Button size='Default' onClick={()=>form.resetFields()}>重置</Button>
</Form.Item>
</Form>
</div>
);
}
export default ToolBottom;

View File

@ -5,23 +5,7 @@ import dayjs from 'dayjs';
const { RangePicker } = DatePicker;
const ToolBar = ({ setToolVal }) => {
const types = [
// { label: '其它', value: 0 },
{ label: '新增', value: 1 },
{ label: '修改', value: 2 },
{ label: '删除', value: 3 },
{ label: '授权', value: 4 },
{ label: '导出', value: 5 },
{ label: '导入', value: 6 },
{ label: '强退', value: 7 },
{ label: '生成代码', value: 8 },
{ label: '清空数据', value: 9 },
];
const Stypes = [
{ label: '正常', value: 0 },
{ label: '异常', value: 1 },
];
const [form] = Form.useForm();
const onFinish = (values) => {
@ -35,8 +19,8 @@ const ToolBar = ({ setToolVal }) => {
useEffect(() => {
const defaultValue = [
dayjs().subtract(10, 'days'),
dayjs().subtract(1, 'days')
dayjs().subtract(7, 'days'),
dayjs()
]
form.setFieldsValue({ operTime: defaultValue })
setToolVal({stm:defaultValue[0].format('YYYY-MM-DD'), etm:defaultValue[1].format('YYYY-MM-DD')})