feat(): 监测数据对接

test
李神峰 2024-12-20 17:39:29 +08:00
parent dc4c2b8d1b
commit 63b98c549c
10 changed files with 318 additions and 79 deletions

View File

@ -31,6 +31,12 @@ const apiurl = {
edit: service_ykz +'/warnRule/update', edit: service_ykz +'/warnRule/update',
delete:service_ykz +'/warnRule/del' delete:service_ykz +'/warnRule/del'
} }
},
jcsj: {
realData: service_ykz + '/stPptnRReal/data',
historyList: service_ykz + '/stPptnRReal/his/data',
historyPage:service_ykz + '/stPptnRReal/page/data',
export:service_ykz + '/stPptnRReal/export'
} }
}, },
sbwh: { sbwh: {
@ -100,6 +106,10 @@ const apiurl = {
czrz: { czrz: {
page: service_ykz + '/gatePoreOpLog/page', page: service_ykz + '/gatePoreOpLog/page',
export:service_ykz + '/gatePoreOpLog/export' export:service_ykz + '/gatePoreOpLog/export'
},
sbgzjl: {
page: service_ykz + '/deviceFailureRecord/page',
export:service_ykz + '/deviceFailureRecord/export'
} }
}, },
systemM: { systemM: {

View File

@ -15,6 +15,7 @@ import BasicSituation from "./Gcyx/InformationSearch/BasicSituation";
import RunSituation from "./Gcyx/InformationSearch/RunSituation"; import RunSituation from "./Gcyx/InformationSearch/RunSituation";
import StaticTable from "./Gcyx/InformationSearch/StaticTable"; import StaticTable from "./Gcyx/InformationSearch/StaticTable";
import OperateLog from "./Gcyx/InformationSearch/OperateLog"; import OperateLog from "./Gcyx/InformationSearch/OperateLog";
import Sbgzjl from "./Gcyx/WatchWarn/Sbgzjl";
import Jcsj from './WatchData/Jcsj'; import Jcsj from './WatchData/Jcsj';
import PoliceRecord from './WatchData/PoliceMangant/PoliceRecord' import PoliceRecord from './WatchData/PoliceMangant/PoliceRecord'
import PoliceRuleConfig from './WatchData/PoliceMangant/PoliceRuleConfig' import PoliceRuleConfig from './WatchData/PoliceMangant/PoliceRuleConfig'
@ -59,6 +60,7 @@ const AppRouters: React.FC = () => {
{ path: 'gcyx/xxcx/yxqk', element: <RunSituation /> }, { path: 'gcyx/xxcx/yxqk', element: <RunSituation /> },
{ path: 'gcyx/xxcx/tjbb', element: <StaticTable /> }, { path: 'gcyx/xxcx/tjbb', element: <StaticTable /> },
{ path: 'gcyx/xxcx/czrz', element: <OperateLog /> }, { path: 'gcyx/xxcx/czrz', element: <OperateLog /> },
{ path: 'gcyx/jsyj/sbgzjl', element: <Sbgzjl /> },
// 系统管理 // 系统管理
{ path: 'xtgl/yhxx', element: <UserInfo /> }, { path: 'xtgl/yhxx', element: <UserInfo /> },

View File

@ -0,0 +1,65 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import { Table, Card, Modal, Form, Input, Button, Row,Col, Timeline, message, Tabs,Image } from 'antd';
import ToolBar from './toolbar';
import apiurl from '../../../../service/apiurl';
import usePageTable from '../../../../components/crud/usePageTable2';
import { createCrudService } from '../../../../components/crud/_';
import { httppost5 } from '../../../../utils/request';
import { exportFile } from '../../../../utils/tools.js';
const Page = () => {
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '设备名称', key: 'deviceName', dataIndex: 'deviceName', width: 150, ellipsis: true },
{ title: '故障信息', key: 'failureInfo', dataIndex: 'failureInfo', width: 200, ellipsis: true },
{
title: '故障原因', key: 'failureReason', dataIndex: 'failureReason', width: 170,
},
{
title: '故障产生时间', key: 'failureCreateTime', dataIndex: 'failureCreateTime', width: 140,
},
{ title: '故障解除时间', key: 'failureReliefTime', dataIndex: 'failureReliefTime', width: 140},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.gcyx.sbgzjl.page).find_noCode);
const exportExcel = () => {
let params = {
...searchVal,
}
httppost5(apiurl.gcyx.sbgzjl.export, params).then(res => {
exportFile(`设备故障记录.xlsx`,res.data)
})
}
useEffect(() => {
const params = {
search: {
...searchVal,
}
};
search(params)
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{paddingBottom:"0"}}>
<div className='lf CrudAdcdTreeTableBox' style={{width:"100%",overflowY:"auto"}}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
exportFile1={exportExcel}
/>
</Card>
<div className="ant-card-body" style={{ padding: "20px 0 0 0" }}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
</div>
</div>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,61 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import NormalSelect from '../../../../components/Form/NormalSelect';
import moment from 'moment';
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
// const types = Array(10).fill(0).map((item,i) => ({
// label: `${i + 1}#闸孔`,
// value: i + 1
// }))
const [form] = Form.useForm();
const onFinish = (values) => {
let dateTimeRangeSo;
if (values.tm) {
dateTimeRangeSo = {
start: moment(values.tm[0]).format('YYYY-MM-DD HH:mm:ss'),
end: moment(values.tm[1]).format('YYYY-MM-DD HH:mm:ss')
}
}
delete values.tm
setSearchVal({...values, dateTimeRangeSo});
}
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="设备名称" name="deviceName">
{/* <NormalSelect allowClear style={{ width: '150px' }} options={types} /> */}
<Input allowClear style={{width:'150px'}}/>
</Form.Item>
<Form.Item label="操作时间" name="tm">
<RangePicker
allowClear
showTime
style={{ width: "330px" }}
format="YYYY-MM-DD HH:mm:ss"
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item>
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
<Form.Item>
<Button onClick={()=>exportFile1()}>导出</Button>
</Form.Item>
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -13,6 +13,7 @@ import { Select } from 'antd';
import { httpget2, httppost2 } from '../../utils/request'; import { httpget2, httppost2 } from '../../utils/request';
import apiurl from '../../service/apiurl'; import apiurl from '../../service/apiurl';
import HFivePlayer from '../../components/video1Plary'; import HFivePlayer from '../../components/video1Plary';
import moment from 'moment';
const MenuTitleCard = ({ key, title }) => { const MenuTitleCard = ({ key, title }) => {
return ( return (
<div className='menuItem_style' key={key} title={title}> <div className='menuItem_style' key={key} title={title}>
@ -48,37 +49,87 @@ export default function Home() {
] ]
const types1 = {
0: "闸后流量(m³/s)",
1: '闸前水位(m)',
2: '闸后水位(m)',
3: '雨量(mm)',
}
const runData = [ const runData = [
{ {
name: '闸后流量(m³/s)', name: '闸后流量(m³/s)',
value: 4300, value: '',
time: '2024-08-15 15:00:00' time: ''
}, },
{ {
name: '闸前水位(m)', name: '闸前水位(m)',
value: 9.82, value: '',
time: '2024-08-15 15:00:00' time: ''
}, },
{ {
name: '闸后流量(m)', name: '闸后流量(m)',
value: 8.87, value: '',
time: '2024-08-15 15:00:00' time: ''
}, },
{ {
name: '雨量(mm)', name: '雨量(mm)',
value: 10.5, value: '',
time: '2024-08-15 15:00:00' time: ''
} }
] ]
const [RealData, setRealData] = useState(runData)
// 实时数据
const getRealData = async () => {
try {
const res = await httppost2(apiurl.jcsj.jcsj.realData)
if (res.code == 200) {
const uptData = res.data.map(item => ({
...item,
name: types1[item.type],
value:item.val,
time:item.tm
}))
setRealData(uptData)
getHistoryData(uptData[0])
}
} catch (error) {
console.log(error);
}
}
const pxOptions = useMemo(() => { const [historyList, setHistoryList] = useState([])
// if (staData) {
// return options(staData) const pxOptions = useMemo(() => {
// } else { if (historyList) {
// return options({}) return options(historyList)
// } } else {
return options({}) return options([])
}, []) }
}, [historyList])
const getHistoryData = async (val) => {
const start = moment().subtract(7,'days').format('YYYY-MM-DD 00:00:00')
const end = moment().format('YYYY-MM-DD 23:59:59')
let params = {
pageSo: {
pageSize: 10,
pageNumber:1
},
type:val.type,
dateTimeRangeSo:{
start,
end
}
}
try {
const res = await httppost2(apiurl.jcsj.jcsj.historyList,params)
if (res.code == 200) {
setHistoryList(res.data)
}
} catch (error) {
console.log(error);
}
}
//安全监测数据 //安全监测数据
const [safeData, setSafeData] = useState(Array(5).fill(0).map((item, i) => ({ id: i, cd: "SY01", dm: '1#断面', kpa: 2749, time: '2024-08-15 15:00:00' }))) const [safeData, setSafeData] = useState(Array(5).fill(0).map((item, i) => ({ id: i, cd: "SY01", dm: '1#断面', kpa: 2749, time: '2024-08-15 15:00:00' })))
//操作日志 //操作日志
@ -134,6 +185,7 @@ export default function Home() {
resize: true resize: true
}) })
getVideoList() getVideoList()
getRealData()
}, []) }, [])
return ( return (
@ -164,8 +216,8 @@ export default function Home() {
<div className='runWatch'> <div className='runWatch'>
<div className='project-title'>运行监测数据</div> <div className='project-title'>运行监测数据</div>
<div className='project-content'> <div className='project-content'>
{runData.map((item, i) => ( {RealData.map((item, i) => (
<div className={clsx({ 'run_list': true, active: activeOne == i })} key={item.name} onClick={() => setActiveOne(i)}> <div className={clsx({ 'run_list': true, active: activeOne == i })} key={item.name} onClick={() => { setActiveOne(i); getHistoryData(item)}}>
<span style={{ width: 94 }}>{item.name}</span> <span style={{ width: 94 }}>{item.name}</span>
<span>{item.value}</span> <span>{item.value}</span>
<span>{item.time}</span> <span>{item.time}</span>

View File

@ -1,4 +1,6 @@
export default function options(data = {}) { export default function options(data = {}) {
const maxY = Math.ceil(Math.max(...data?.map(s => s.val)))
const minY = Math.floor(Math.min(...data?.map(s => s.val)))
return { return {
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
@ -11,7 +13,7 @@ export default function options(data = {}) {
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"], data: data.map(item => item.tm),
boundaryGap: false, boundaryGap: false,
axisLine: { axisLine: {
lineStyle: { lineStyle: {
@ -24,6 +26,8 @@ export default function options(data = {}) {
}, },
yAxis: { yAxis: {
type: "value", type: "value",
min: minY,
max:maxY,
splitLine: { splitLine: {
lineStyle: { lineStyle: {
color: "#d9d9d9", color: "#d9d9d9",
@ -42,9 +46,9 @@ export default function options(data = {}) {
}, },
series: [ series: [
{ {
data: [150, 230, 224, 218, 135, 147, 260], data: data.map(item => item.val),
type: "line", type: "line",
name: '闸前水位', name: data[0]?.typeName,
lineStyle: { lineStyle: {
color: '#5b8ff9' color: '#5b8ff9'
}, },

View File

@ -6,7 +6,7 @@ import ReactEcharts from 'echarts-for-react';
import options from './options' import options from './options'
import usePageTable from '../../../components/crud/usePageTable2'; import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_'; import { createCrudService } from '../../../components/crud/_';
import { httppost5 } from '../../../utils/request'; import { httppost2, httppost5 } from '../../../utils/request';
import { exportFile } from '../../../utils/tools.js'; import { exportFile } from '../../../utils/tools.js';
import './index.less' import './index.less'
@ -14,69 +14,102 @@ const RealCard = ({ item }) => {
return ( return (
<div className='card-container' key={item.label}> <div className='card-container' key={item.label}>
<div className='item-one'>{item.label}</div> <div className='item-one'>{item.label}</div>
<div className='item-two'><span style={{ fontSize: 20, fontWeight: 700 }}>{item.value}</span> (08-15 15:00:00)</div> <div className='item-two'><span style={{ fontSize: 20, fontWeight: 700 }}>{item.value}</span> ({item.tm})</div>
</div> </div>
) )
} }
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => { const Page = () => {
const types = { const types1 = {
0: "闸后流量", 0: "闸后流量(m³/s)",
1: '闸前水位', 1: '闸前水位(m)',
2: '闸后水位', 2: '闸后水位(m)',
3: '雨量', 3: '雨量(mm)',
} }
const [historyList, setHistoryList] = useState([])
const pxOptions = useMemo(() => { const pxOptions = useMemo(() => {
// if (staData) { if (historyList) {
// return options(staData) return options(historyList)
// } else { } else {
// return options({}) return options([])
// } }
return options({}) }, [historyList])
}, [])
const nameList = [ const nameList = [
{ {
label: "闸后流量(m³/s)", label: "闸后流量(m³/s)",
value: 300 value: ''
}, },
{ {
label: "闸前水位(m)", label: "闸前水位(m)",
value: 300 value: ''
}, },
{ {
label: "闸后水位(m)", label: "闸后水位(m)",
value: 300 value: ''
}, },
{ {
label: "雨量(mm)", label: "雨量(mm)",
value: 300 value: ''
} }
] ]
const [searchVal, setSearchVal] = useState(false) const [searchVal, setSearchVal] = useState(false)
const columns = [ const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" }, { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ {
title: '监测项目', key: 'name', dataIndex: 'name', width: 150, title: '监测项目', key: 'typeName', dataIndex: 'typeName', width: 150,
render: (v) => <span>{types[v]}</span>
}, },
{ title: '监测值', key: 'adress', dataIndex: 'adress', width: 150 }, { title: '监测值', key: 'val', dataIndex: 'val', width: 150 },
{ {
title: '监测时间', key: 'eventsDate', dataIndex: 'eventsDate', width: 140, title: '监测时间', key: 'tm', dataIndex: 'tm', width: 140,
}, },
]; ];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]); const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.sbwh.whfabz.page).find_noCode); const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.jcsj.jcsj.historyPage).find_noCode);
const [RealData, setRealData] = useState(nameList)
// 实时数据
const getRealData = async () => {
try {
const res = await httppost2(apiurl.jcsj.jcsj.realData)
if (res.code == 200) {
const uptData = res.data.map(item => ({
...item,
label: types1[item.type],
value:item.val
}))
setRealData(uptData)
}
} catch (error) {
console.log(error);
}
}
// 历史数据
const getHistoryData = async (val) => {
let params = {
pageSo: {
pageSize: 10,
pageNumber:1
},
...val.search,
}
try {
const res = await httppost2(apiurl.jcsj.jcsj.historyList,params)
if (res.code == 200) {
setHistoryList(res.data)
}
} catch (error) {
console.log(error);
}
}
const exportExcel = () => { const exportExcel = () => {
let params = { let params = {
...searchVal, ...searchVal,
} }
httppost5(apiurl.pxjh.export, params).then(res => { httppost5(apiurl.jcsj.jcsj.export, params).then(res => {
exportFile(`统计报表.xlsx`, res.data) exportFile(`监测数据.xlsx`, res.data)
}) })
} }
useEffect(() => { useEffect(() => {
@ -86,8 +119,14 @@ const Page = () => {
} }
}; };
search(params) search(params)
getHistoryData(params)
}, [searchVal]) }, [searchVal])
useEffect(() => {
getRealData()
}, [])
return ( return (
<> <>
<div className='content-root clearFloat xybm' style={{ paddingBottom: "0" }}> <div className='content-root clearFloat xybm' style={{ paddingBottom: "0" }}>
@ -98,7 +137,7 @@ const Page = () => {
<div className='font_style'>实时数据</div> <div className='font_style'>实时数据</div>
</div> </div>
<div className='real-item'> <div className='real-item'>
{nameList.map(item => ( {RealData.map(item => (
<RealCard item={item} /> <RealCard item={item} />
))} ))}
</div> </div>

View File

@ -1,4 +1,8 @@
export default function options(data = {}) {
export default function options(data = []) {
const maxY = Math.ceil(Math.max(...data?.map(s => s.val)))
const minY = Math.floor(Math.min(...data?.map(s => s.val)))
return { return {
tooltip: { tooltip: {
trigger: "axis", trigger: "axis",
@ -6,11 +10,12 @@ export default function options(data = {}) {
grid: { grid: {
top: 10, top: 10,
bottom:135, bottom:135,
right:30 right: 60,
left:80
}, },
xAxis: { xAxis: {
type: "category", type: "category",
data: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"], data: data.map(item => item.tm),
boundaryGap: false, boundaryGap: false,
axisLine: { axisLine: {
lineStyle: { lineStyle: {
@ -23,6 +28,8 @@ export default function options(data = {}) {
}, },
yAxis: { yAxis: {
type: "value", type: "value",
min: minY,
max:maxY,
splitLine: { splitLine: {
lineStyle: { lineStyle: {
color: "#d9d9d9", color: "#d9d9d9",
@ -41,9 +48,9 @@ export default function options(data = {}) {
}, },
series: [ series: [
{ {
data: [150, 230, 224, 218, 135, 147, 260], data: data.map(item => item.val),
type: "line", type: "line",
name: '闸前水位', name: data[0]?.typeName,
lineStyle: { lineStyle: {
color: '#5b8ff9' color: '#5b8ff9'
}, },

View File

@ -1,4 +1,4 @@
import React, { useEffect,useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd'; import { Form, Input, Button, DatePicker } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect'; import NormalSelect from '../../../components/Form/NormalSelect';
@ -24,38 +24,37 @@ const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
value: 3, value: 3,
}, },
] ]
const types1 = [
{
label: "报警中",
value: 0,
},
{
label: "已解除",
value: 1,
},
]
const [form] = Form.useForm(); const [form] = Form.useForm();
const onFinish = (values) => { const onFinish = (values) => {
let dateSo; let dateTimeRangeSo;
if (values.tm) { if (values.tm) {
dateSo = { dateTimeRangeSo = {
start: moment(values.tm[0]).format('YYYY-MM-DD HH:mm:ss'), start: moment(values.tm[0]).format('YYYY-MM-DD HH:mm:ss'),
end: moment(values.tm[1]).format('YYYY-MM-DD HH:mm:ss') end: moment(values.tm[1]).format('YYYY-MM-DD HH:mm:ss')
} }
} }
delete values.tm delete values.tm
setSearchVal({...values, dateSo}); setSearchVal({ ...values, dateTimeRangeSo });
} }
useEffect(() => {
const start = moment().subtract(7, 'days').format('YYYY-MM-DD 00:00:00')
const end = moment().format('YYYY-MM-DD 23:59:59')
form.setFieldsValue({
tm: [moment(start), moment(end)]
})
form.setFieldValue("type", 0)
setSearchVal({ type: 0, dateTimeRangeSo: { start, end } })
}, [])
return ( return (
<> <>
<div style={{display:'flex',justifyContent:'space-between'}}> <div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}> <Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="监测项目" name="type"> <Form.Item label="监测项目" name="type">
<NormalSelect allowClear style={{ width: '150px' }} options={types} /> <NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item> </Form.Item>
<Form.Item label="监测时间" name="tm"> <Form.Item label="监测时间" name="tm">
<RangePicker <RangePicker
@ -65,7 +64,7 @@ const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
/> />
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button type="primary" htmlType="submit">查询</Button> <Button type="primary" htmlType="submit">查询</Button>
</Form.Item> </Form.Item>
@ -73,7 +72,7 @@ const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
<Button onClick={() => form.resetFields()}>重置</Button> <Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Button onClick={()=>exportFile1()}>导出</Button> <Button onClick={() => exportFile1()}>导出</Button>
</Form.Item> </Form.Item>
</Form> </Form>
</div> </div>