feat(): ai洪水预报修改
parent
9b5187625b
commit
0ac52e4e9e
|
|
@ -29,7 +29,8 @@ module.exports = function (app) {
|
|||
app.use(
|
||||
'/gunshiApp/dcpj',
|
||||
createProxyMiddleware({
|
||||
target: 'http://local.gunshiiot.com:18083',
|
||||
// target: 'http://local.gunshiiot.com:18083',
|
||||
target: 'http://192.168.66.30:24107',
|
||||
changeOrigin: true,
|
||||
})
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import React from 'react'
|
||||
|
||||
export default function RenderForm() {
|
||||
return (
|
||||
<div>RenderForm</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -48,18 +48,34 @@ export default function TestLine() {
|
|||
align: 'center',
|
||||
fixed:'left'
|
||||
},
|
||||
{
|
||||
title: '预测降雨量(mm)',
|
||||
dataIndex: 'predictRainfall',
|
||||
key: 'predictRainfall',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
// render: (text, record,index) => (
|
||||
// <InputNumber
|
||||
// defaultValue={text}
|
||||
// min={0}
|
||||
// precision={1}
|
||||
// onChange={(value) => handlePredictRainfallChange(value, index)}
|
||||
// style={{ width: '100%' }}
|
||||
// />
|
||||
// )
|
||||
},
|
||||
{
|
||||
title: '实测雨量(mm)',
|
||||
dataIndex: 'rain',
|
||||
key: 'rain',
|
||||
width: 100,
|
||||
dataIndex: 'rains',
|
||||
key: 'rains',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
render: (v) => <span>{ handleEmptyValue(v)}</span>
|
||||
},
|
||||
{
|
||||
title: '实测水位(m)',
|
||||
dataIndex: 'water',
|
||||
key: 'water',
|
||||
dataIndex: 'waters',
|
||||
key: 'waters',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
render: (v) => <span>{ handleEmptyValue(v)}</span>
|
||||
|
|
@ -78,12 +94,90 @@ export default function TestLine() {
|
|||
key: 'cz',
|
||||
width: 90,
|
||||
align: 'center',
|
||||
render: (v, r) => <span>{(r.predict && r.water) ? Math.abs((r.predict - r.water)).toFixed(2) : '-'}</span>
|
||||
render: (v, r) => <span>{(r.predict && r.waters) ? Math.abs((r.predict - r.waters)).toFixed(2) : '-'}</span>
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* 替换数组末尾指定数量的元素
|
||||
* @param {Array} arr - 原数组
|
||||
* @param {Array} newValues - 新值数组
|
||||
* @param {number} tn - 替换数量
|
||||
* @returns {Array} 新数组
|
||||
*/
|
||||
const replaceLastItems = (arr, newValues, tn = 1) => {
|
||||
if (!Array.isArray(arr)) {
|
||||
return newValues;
|
||||
}
|
||||
|
||||
const newArr = [...arr];
|
||||
const startIndex = Math.max(0, newArr.length - tn);
|
||||
|
||||
for (let i = 0; i < tn; i++) {
|
||||
if (startIndex + i < newArr.length) {
|
||||
newArr[startIndex + i] = newValues[i];
|
||||
}
|
||||
}
|
||||
|
||||
return newArr;
|
||||
};
|
||||
|
||||
/**
|
||||
* 收集预测雨量数据
|
||||
* @param {Array} data - 表格数据
|
||||
* @param {number} tn - 预测时段数
|
||||
* @returns {Array} 预测雨量数组
|
||||
*/
|
||||
const collectPredictRainfall = (data, tn = 1) => {
|
||||
if (!Array.isArray(data) || data.length === 0) return [];
|
||||
|
||||
const result = [];
|
||||
data.slice(-tn).forEach(item => {
|
||||
result.push((item.predictRainfall === '' || item.predictRainfall==null || item.predictRainfall == undefined) ? item.rains : item.predictRainfall);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理预测雨量的变化
|
||||
* @param {Array} data - 原始数据
|
||||
* @param {Object} changes - 变化的数据 {index: value}
|
||||
* @returns {Array} 处理后的数据
|
||||
*/
|
||||
const handlePredictRainfallChanges =(data, value, index) => {
|
||||
if (!Array.isArray(data)) return [];
|
||||
const newData = [...data];
|
||||
if (newData[index]) {
|
||||
newData[index] = {
|
||||
...newData[index],
|
||||
predictRainfall: value,
|
||||
isModified: true // 标记该项已被修改
|
||||
};
|
||||
}
|
||||
return newData;
|
||||
};
|
||||
const [predictRainfalling, setPredictRainfalling] = useState({});
|
||||
const [tableUpdata, setTableUpdata] = useState([])
|
||||
const tableUpdataRef = useRef(null);
|
||||
tableUpdataRef.current = tableUpdata;
|
||||
const handleRainfallChange = (value, index) => {
|
||||
setPredictRainfalling(prev => ({
|
||||
...prev,
|
||||
[index]: value
|
||||
}));
|
||||
const updatedData = handlePredictRainfallChanges(tableList, value, index);
|
||||
setTableList(updatedData)
|
||||
setTableUpdata(updatedData)
|
||||
tableUpdataRef.current = updatedData
|
||||
};
|
||||
const getHistoryData = async (params) => {
|
||||
setLoading(true)
|
||||
params.stcd = obj[params.code];
|
||||
params.predictRainfallList = tableUpdataRef.current;
|
||||
if (tableUpdataRef.current.length && tableUpdataRef.current.some(item => item.predictRainfall === '' || item.predictRainfall == null || item.predictRainfall == undefined)) {
|
||||
message.warning(`请输入${searchVal.time}个预测雨量值`)
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
try {
|
||||
const result = await httppost2(apiurl.test.find1, params);
|
||||
if (result.code == 200) {
|
||||
|
|
@ -94,20 +188,26 @@ export default function TestLine() {
|
|||
}
|
||||
setHistoryData(responseData)
|
||||
const allBatches = getAllHydroBatches(responseData);
|
||||
const res = await processPredictions(allBatches, params.code)
|
||||
let needData = responseData;
|
||||
let type = tableUpdataRef.current.length > 0 ? 2 :1
|
||||
if (tableUpdataRef.current.length > 0) {
|
||||
needData = tableUpdataRef.current;
|
||||
}
|
||||
// debugger
|
||||
const res = await processPredictions(allBatches, params.code, needData, type)
|
||||
if (res.length > 0) {
|
||||
setLoading(false)
|
||||
setPredictData(res.map(item => ({ ...item, predict: item.predict.toFixed(2) })))
|
||||
const tableData = res.map(item => {
|
||||
const obj = responseData.find(it => it.tm == item.tm)
|
||||
const obj = needData.find(it => it.tm == item.tm)
|
||||
return {
|
||||
...item,
|
||||
predict: item.predict ? item.predict.toFixed(2) : '',
|
||||
water: obj?.waters,
|
||||
rain:obj?.rains
|
||||
waters: obj?.waters ,
|
||||
rains: obj?.rains,
|
||||
predictRainfall:type == 2 ? obj?.predictRainfall:''
|
||||
}
|
||||
})
|
||||
|
||||
setTableList(tableData)
|
||||
}
|
||||
}
|
||||
|
|
@ -129,12 +229,20 @@ export default function TestLine() {
|
|||
* @param {Array} batches - 批次数据
|
||||
* @param {Array} predictions - 预测结果数组
|
||||
* @returns {Array} - 返回处理后的预测结果
|
||||
*/ const processPredictions = async (batches, name) => {
|
||||
*/ const processPredictions = async (batches, name, responseArr, type) => {
|
||||
let arr = [];
|
||||
if (type == 1) {
|
||||
arr = JSON.parse(JSON.stringify(responseArr));
|
||||
arr.slice(-searchVal.time);
|
||||
} else {
|
||||
arr=responseArr
|
||||
}
|
||||
const predictRainArr = collectPredictRainfall(arr, searchVal.time) //收集的输入预测雨量数组
|
||||
const results = [];
|
||||
|
||||
for (const batch of batches) {
|
||||
const prediction = await httppost2('http://202.96.165.23:10100/api/v1/bot/water_infer', {
|
||||
rains: replaceLastItem(batch.rains,searchVal.predictRain),
|
||||
// rains: replaceLastItem(batch.rains,searchVal.predictRain),
|
||||
rains:replaceLastItems(batch.rains,predictRainArr,searchVal.time),
|
||||
waters: batch.waters,
|
||||
name,
|
||||
tn:searchVal.time
|
||||
|
|
@ -176,9 +284,9 @@ export default function TestLine() {
|
|||
}
|
||||
const summaryVal = useMemo(() => {
|
||||
if (tableList.length > 0) {
|
||||
const sum = tableList.reduce((total, cur) => total + Math.abs((cur.predict - cur.water)), 0);
|
||||
const sum = tableList.reduce((total, cur) => total + Math.abs((cur.predict - cur.waters)), 0);
|
||||
const newArr = JSON.parse(JSON.stringify(tableList));
|
||||
const resultMaxOrMin = findMinMaxRain(newArr.map(item => ({ ...item, diff: Math.abs((item.predict - item.water)).toFixed(2) })))
|
||||
const resultMaxOrMin = findMinMaxRain(newArr.map(item => ({ ...item, diff: Math.abs((item.predict - item.waters)).toFixed(2) })))
|
||||
return {
|
||||
avergVal: (sum / tableList.length).toFixed(2),
|
||||
maxVal: resultMaxOrMin?.max,
|
||||
|
|
@ -188,6 +296,28 @@ export default function TestLine() {
|
|||
return {}
|
||||
}
|
||||
}, [tableList])
|
||||
|
||||
useEffect(() => {
|
||||
if (searchVal.time) {
|
||||
setTableUpdata([])
|
||||
tableUpdataRef.current = []
|
||||
}
|
||||
}, [searchVal.time])
|
||||
|
||||
// useEffect(() => {
|
||||
// if (searchVal.code) {
|
||||
// setTableUpdata([])
|
||||
// tableUpdataRef.current = []
|
||||
// }
|
||||
// }, [searchVal.code])
|
||||
|
||||
// useEffect(() => {
|
||||
// if (searchVal.tm) {
|
||||
// setTableUpdata([])
|
||||
// tableUpdataRef.current = []
|
||||
// }
|
||||
// }, [searchVal.tm])
|
||||
|
||||
useEffect(() => {
|
||||
if (searchVal) {
|
||||
getHistoryData(searchVal)
|
||||
|
|
@ -195,6 +325,33 @@ export default function TestLine() {
|
|||
}, [searchVal])
|
||||
|
||||
|
||||
|
||||
|
||||
// 渲染预测雨量输入表单
|
||||
const renderRainfallInputs = () => {
|
||||
const inputs = [];
|
||||
for (let i = 0; i < searchVal.time; i++) {
|
||||
inputs.push(
|
||||
<Form.Item
|
||||
key={i}
|
||||
label={`${i + 1}h`}
|
||||
style={{ marginBottom: 16 }}
|
||||
>
|
||||
<InputNumber
|
||||
value={predictRainfalling[i]}
|
||||
onChange={(value) => handleRainfallChange(value, i)}
|
||||
min={0}
|
||||
precision={1}
|
||||
placeholder={`请输入雨量`}
|
||||
style={{ width: 100 }}
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
return inputs;
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='content-root clearFloat xybm' style={{ paddingBottom: "0" }}>
|
||||
|
|
@ -202,8 +359,16 @@ export default function TestLine() {
|
|||
<Card className='nonebox'>
|
||||
<ToolBar
|
||||
setSearchVal={setSearchVal}
|
||||
setPredictRainfalling={setPredictRainfalling}
|
||||
/>
|
||||
</Card>
|
||||
{
|
||||
searchVal.time && <div style={{ marginTop: 16,marginLeft:10,marginRight:10 }}>
|
||||
<Form layout="inline">
|
||||
{renderRainfallInputs()}
|
||||
</Form>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
historyData.length ? !loading ?
|
||||
<div className="ant-card-body" style={{ padding: "20px 0 0 0"}}>
|
||||
|
|
@ -212,12 +377,12 @@ export default function TestLine() {
|
|||
<div style={{ flex: 1, height: 'calc( 100vh - 400px )', padding: 10 }}>
|
||||
<ReactEcharts option={options} style={{ width: "100%", height: '100%' }} notMerge={true} />
|
||||
</div>
|
||||
<div style={{ width: 600, marginRight: 30 }}>
|
||||
<div style={{ width: 700, marginRight: 30 }}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={tableList}
|
||||
rowKey='tm'
|
||||
pagination={true}
|
||||
pagination={false}
|
||||
scroll={{ x: 600, y: 'calc(100vh - 300px)' }}
|
||||
summary={() => {
|
||||
return (
|
||||
|
|
@ -225,7 +390,7 @@ export default function TestLine() {
|
|||
<Table.Summary.Row>
|
||||
<Table.Summary.Cell index={12} align='center' colSpan={1} >差值最大值时间点</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={1} align='center' colSpan={2}>{summaryVal?.maxVal?.tm || '-'}</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={2} align='center' colSpan={1}>差值最大值</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={2} align='center' colSpan={2}>差值最大值</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={3} align='center' colSpan={1}>{summaryVal?.maxVal?.diff !='NaN'?summaryVal?.maxVal?.diff:"-"}</Table.Summary.Cell>
|
||||
</Table.Summary.Row>
|
||||
{/* <Table.Summary.Row>
|
||||
|
|
@ -236,7 +401,7 @@ export default function TestLine() {
|
|||
</Table.Summary.Row> */}
|
||||
<Table.Summary.Row>
|
||||
<Table.Summary.Cell index={4} align='center' colSpan={1} >差值平均值</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={5} align='center' colSpan={4}>{summaryVal?.avergVal!='NaN'?summaryVal?.avergVal: '-'}</Table.Summary.Cell>
|
||||
<Table.Summary.Cell index={5} align='center' colSpan={6}>{summaryVal?.avergVal!='NaN'?summaryVal?.avergVal: '-'}</Table.Summary.Cell>
|
||||
</Table.Summary.Row>
|
||||
</>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import NormalSelect from '../../components/Form/NormalSelect';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import moment from 'moment';
|
||||
const { RangePicker } = DatePicker;
|
||||
const ToolBar = ({ setSearchVal, setType, save, form1 }) => {
|
||||
const ToolBar = ({ setSearchVal, setType, save, form1,setPredictRainfalling }) => {
|
||||
const navigate = useNavigate();
|
||||
const types = [
|
||||
// {
|
||||
|
|
@ -72,15 +72,22 @@ const ToolBar = ({ setSearchVal, setType, save, form1 }) => {
|
|||
return current && (current > maxDate);
|
||||
};
|
||||
|
||||
const onValuesChange = (val, r) => {
|
||||
if ('time' in val) {
|
||||
setSearchVal({ ...r, time: val.time, etm: moment(r.tm).format("YYYY-MM-DD HH:mm:ss") })
|
||||
setPredictRainfalling({})
|
||||
}
|
||||
}
|
||||
|
||||
const jump = () => {
|
||||
navigate('/');
|
||||
}
|
||||
useEffect(() => {
|
||||
const stm = moment('2024-01-01').format('YYYY-MM-DD 00:00:00')
|
||||
const etm = moment('2024-07-28 11:00:00').format('YYYY-MM-DD 00:00:00')
|
||||
const etm = moment('2024-07-28 11:00:00').format('YYYY-MM-DD HH:00:00')
|
||||
const params = {
|
||||
code: "cq",
|
||||
time: 24,
|
||||
time: 6,
|
||||
predictRain:11,
|
||||
// stm,
|
||||
etm
|
||||
|
|
@ -97,16 +104,16 @@ const ToolBar = ({ setSearchVal, setType, save, form1 }) => {
|
|||
return (
|
||||
<>
|
||||
<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} onValuesChange={onValuesChange}>
|
||||
<Form.Item label="水库" name="code">
|
||||
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
|
||||
<NormalSelect allowClear={false} style={{ width: '150px' }} options={types} />
|
||||
</Form.Item>
|
||||
<Form.Item label="预测时段" name="time">
|
||||
<NormalSelect allowClear style={{ width: '150px' }} options={timeType} />
|
||||
<NormalSelect allowClear={false} style={{ width: '150px' }} options={timeType} />
|
||||
</Form.Item>
|
||||
<Form.Item label="预测降雨量" name="predictRain">
|
||||
{/* <Form.Item label="预测降雨量" name="predictRain">
|
||||
<InputNumber min={0} style={{ width: '150px' }}/>
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
<Form.Item label="时间" name="tm"
|
||||
>
|
||||
<DatePicker
|
||||
|
|
@ -114,7 +121,7 @@ const ToolBar = ({ setSearchVal, setType, save, form1 }) => {
|
|||
disabledDate={disabledFutureDate}
|
||||
style={{ width: "250px" }}
|
||||
format="YYYY-MM-DD HH:00:00"
|
||||
// allowClear={false}
|
||||
allowClear={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue