feat(): 预警信息、预警规则开发

master
李神峰 2025-11-27 17:40:39 +08:00
parent e986bbc5d5
commit 71bca6f4b9
8 changed files with 627 additions and 0 deletions

View File

@ -226,6 +226,17 @@ const apiurl = {
},
sy: {
yjxx: {
page: service_fxdd + "/warningRule/info/page",
},
yjxxpz: {
page: service_fxdd + "/warningRule/page",
edit: service_fxdd + '/warningRule/update',
save: service_fxdd + '/warningRule/insert',
del: service_fxdd + "/warningRule/del/",
}
},
// 防汛准备
fxzb1: {
ddgc: {

View File

@ -21,6 +21,8 @@ import Fxya from './fxzb/fxya'
import Hsybjs from './fxzb/hsybjs'
import Ybfagl from './fxzb/ybfagl'
import Csgl from './fxzb/csgl'
import Yjxx from './fxzb/yjxx'
import Gzpz from './fxzb/gzpz'
import Qxdw_Gc from './fxzb/qxdw/gc/index.js'
import Qxwl_Gc from './fxzb/qxwl/gc'
@ -162,6 +164,10 @@ const AppRouters: React.FC = () => {
{ path: 'sy/hsyb/ybfagl', element: <Ybfagl /> },
{ path: 'sy/hsyb/csgl', element: <Csgl /> },
// 四预-洪水预警
{ path: 'sy/hsyj/yjxx', element: <Yjxx/> },
{ path: 'sy/hsyj/gzpz', element: <Gzpz /> },
// 调度规程
{ path: 'sy/ddgc', element: <Ddgc /> },

175
src/views/fxzb/gzpz/form.js Normal file
View File

@ -0,0 +1,175 @@
import React, { useEffect, useState, useMemo, useRef } from 'react';
import { Form, Button, Input, Row, Upload, Col, Table, DatePicker, InputNumber, message, Image, Modal, Radio, Popconfirm } from 'antd';
import { DeleteOutlined, VideoCameraOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [form] = Form.useForm();
const onfinish = (values) => {
const userId = localStorage.getItem('userId')
values.userId = userId
if (mode === 'edit') {
onEdit(apiurl.sy.yjxxpz.edit, { ...record, ...values })
}
if (mode === 'save') {
onSave(apiurl.sy.yjxxpz.save, values)
}
}
useEffect(() => {
if (mode == "save") {
const name = localStorage.getItem('userName')
form.setFieldValue("createName", name)
form.setFieldValue("createTime", moment())
}
}, [mode])
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="规则名称"
name="ruleName"
rules={[{ required: true }]}
>
<Input style={{ width: '100%' }} allowClear disabled={mode === 'view'} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="预警等级"
name="warningLevel"
rules={[{ required: true }]}
>
<NormalSelect
options={[
{ label: '蓝色', value: 0 },
{ label: '黄色', value: 1 },
{ label: '橙色', value: 2 },
{ label: '红色', value: 3 }
]}
allowClear={true}
style={{ width: '100%' }}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="启用状态"
name="status"
rules={[{ required: true }]}
>
<Radio.Group disabled={mode === 'view'}>
<Radio value={0}>未启用</Radio>
<Radio value={1}>启用</Radio>
</Radio.Group>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="规则配置"
required
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={16}>
<Col span={8}>
<Form.Item name="configTarget" rules={[{ required: true }]} noStyle>
<NormalSelect
allowClear
style={{ width: '100%' }}
disabled={mode === 'view'}
placeholder="请选择对象"
options={[
{ label: '未来1h水库预报水位', value: 1 },
{ label: '未来3h水库预报水位', value: 3 },
{ label: '未来6h水库预报水位', value: 6 },
{ label: '未来12h水库预报水位', value: 12 },
{ label: '未来24h水库预报水位', value: 24 },
]}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="configRelation" rules={[{ required: true }]} noStyle>
<NormalSelect
allowClear
style={{ width: '100%' }}
disabled={mode === 'view'}
placeholder="请选择关系"
options={[
{ label: '>', value: '>' },
{ label: '≥', value: '>=' },
]}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="configThreshold" rules={[{ required: true }]} noStyle>
<NormalSelect
allowClear
style={{ width: '100%' }}
disabled={mode === 'view'}
placeholder="请选择阈值"
options={[
{ label: '汛限水位(109.00m)', value: 5 },
{ label: '设计洪水位(111.89m)', value: 10 },
{ label: '校核洪水位(113.06m)', value: 20 },
]}
/>
</Form.Item>
</Col>
</Row>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="创建人"
name="createName"
>
<Input disabled={true} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="创建时间"
name="createTime"
getValueFromEvent={(e, dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={true} style={{ width: '100%' }} allowClear format={"YYYY-MM-DD HH:mm:ss"} />
</Form.Item>
</Col>
</Row>
{
mode === 'view' ? null : (
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
);
}
export default ModalForm;

View File

@ -0,0 +1,105 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Modal, Form, Input, Button, Row,Col, Timeline, message, Tabs,Image } from 'antd';
import {FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_';
import {CrudOpRender_text} from '../../../components/crud/CrudOpRender';
import moment from 'moment';
const url = "http://223.75.53.141:9100/gs-tsg"
const Page = () => {
const role = useSelector(state => state.auth.role);
const editBtn = role?.rule?.find(item => item.menuName == "编辑")|| true;
const viewBtn = role?.rule?.find(item => item.menuName == "查看")|| true;
const delBtn = role?.rule?.find(item => item.menuName == "删除")|| true;
const levelObj = {
0: "蓝色",
1: "黄色",
2: "橙色",
3: "红色",
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ title: '预警时间', key: 'createTime', dataIndex: 'createTime', width: 140, align: "center", },
{ title: '规则名称', key: 'ruleName', dataIndex: 'ruleName', width: 140, align: "center", },
{ title: '预警等级', key: 'warningLevel', dataIndex: 'warningLevel', width: 100, align: "center", render: (v) => <span>{levelObj[v]}</span> },
{ title: '预警信息', key: 'ruleInfo', dataIndex: 'ruleInfo', width: 300, align: "center", },
{
title: '操作', key: 'operation', width: 100, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text view={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit({ ...params });
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDeleteGet(apiurl.sy.yjxxpz.delete + `${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.sy.yjxxpz.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
useEffect(() => {
if (searchVal) {
const params = {
search: {
...searchVal,
}
};
search(params)
}
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{paddingRight:"0",paddingBottom:"0"}}>
<div className='lf CrudAdcdTreeTableBox' style={{width:"100%",overflowY:"auto"}}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
/>
</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>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={successCallback}
// onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,57 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import moment from 'moment';
import NormalSelect from '../../../components/Form/NormalSelect';
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role }) => {
const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true;
const searchBtn = role?.rule?.find(item => item.menuName == "查询")|| true;
const [form] = Form.useForm();
const onFinish = (values) => {
setSearchVal({...values})
}
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="规则名称" name="ruleName">
<Input allowClear style={{width:200}}/>
</Form.Item>
<Form.Item label="预警等级" name="warningLevel">
<NormalSelect
allowClear
style={{ width: '150px' }}
options={[
{ label: '蓝色', value: 0 },
{ label: '黄色', value: 1 },
{ label: '橙色', value: 2 },
{ label: '红色', value: 3 }
]}
/>
</Form.Item>
{searchBtn ? <Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item> : null }
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
{
(onSave && addBtn) ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
:null
}
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,90 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Radio ,Popconfirm } from 'antd';
import { DeleteOutlined,VideoCameraOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [form] = Form.useForm();
const onfinish = (values) => {
const userId = localStorage.getItem('userId')
values.userId = userId
if (mode === 'edit') {
onEdit(apiurl.rcgl.wxyh.edit,{...record,...values})
}
if (mode === 'save') {
onSave(apiurl.rcgl.wxyh.save,values)
}
}
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="规则名称"
name="ruleName"
rules={[{ required: true }]}
>
<Input style={{ width: '100%' }} allowClear disabled={mode === 'view'} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="预警等级"
name="warningLevel"
rules={[{ required: true }]}
>
<NormalSelect
options={[
{ label: '蓝色', value: 0 },
{ label: '黄色', value: 1 },
{ label: '橙色', value: 2 },
{ label: '红色', value: 3 }
]}
allowClear={true}
style={{ width: '100%' }}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="启用状态"
name="status"
rules={[{ required: true }]}
>
<Radio.Group disabled={mode === 'view'}>
<Radio value={0}>未启用</Radio>
<Radio value={1}>启用</Radio>
</Radio.Group>
</Form.Item>
</Col>
</Row>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
);
}
export default ModalForm;

View File

@ -0,0 +1,105 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card, Modal, Form, Input, Button, Row,Col, Timeline, message, Tabs,Image } from 'antd';
import {FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_';
import {CrudOpRender_text} from '../../../components/crud/CrudOpRender';
import moment from 'moment';
const url = "http://223.75.53.141:9100/gs-tsg"
const Page = () => {
const role = useSelector(state => state.auth.role);
const editBtn = role?.rule?.find(item => item.menuName == "编辑")|| true;
const viewBtn = role?.rule?.find(item => item.menuName == "查看")|| true;
const delBtn = role?.rule?.find(item => item.menuName == "删除")|| true;
const levelObj = {
0: "蓝色",
1: "黄色",
2: "橙色",
3: "红色",
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ title: '预警时间', key: 'createTime', dataIndex: 'createTime', width: 140, align: "center", },
{ title: '规则名称', key: 'ruleName', dataIndex: 'ruleName', width: 140, align: "center", },
{ title: '预警等级', key: 'warningLevel', dataIndex: 'warningLevel', width: 100, align: "center", render: (v) => <span>{levelObj[v]}</span> },
{ title: '预警信息', key: 'ruleInfo', dataIndex: 'ruleInfo', width: 300, align: "center", },
{
title: '操作', key: 'operation', width: 100, fixed: 'right', align: 'center',
render: (value, row, index) => (<CrudOpRender_text view={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit({ ...params });
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDeleteGet(apiurl.sy.yjxxpz.delete + `${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.sy.yjxxpz.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
useEffect(() => {
if (searchVal) {
const params = {
search: {
...searchVal,
}
};
search(params)
}
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{paddingRight:"0",paddingBottom:"0"}}>
<div className='lf CrudAdcdTreeTableBox' style={{width:"100%",overflowY:"auto"}}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
/>
</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>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={successCallback}
// onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,78 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import moment from 'moment';
import NormalSelect from '../../../components/Form/NormalSelect';
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role }) => {
const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true;
const searchBtn = role?.rule?.find(item => item.menuName == "查询")|| true;
const [form] = Form.useForm();
const onFinish = (values) => {
let dateTimeRangeSo;
if (values.tm) {
dateTimeRangeSo = {
start: moment(values.tm[0]).format('YYYY-MM-DD 00:00:00'),
end: moment(values.tm[1]).format('YYYY-MM-DD 23:59:59')
}
}
delete values.tm
setSearchVal({...values, dateTimeRangeSo});
}
useEffect(() => {
let dateTimeRangeSo = {
start: moment().subtract(1,"months").format('YYYY-MM-DD 00:00:00'),
end: moment().format('YYYY-MM-DD 23:59:59')
}
form.setFieldValue("tm", [moment(dateTimeRangeSo.start), moment(dateTimeRangeSo.end)])
setSearchVal({ dateTimeRangeSo })
}, [])
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="预警时间" name="tm">
<RangePicker
allowClear
style={{ width: "300px" }}
format="YYYY-MM-DD"
/>
</Form.Item>
<Form.Item label="预警等级" name="warningLevel">
<NormalSelect
allowClear
style={{ width: '150px' }}
options={[
{ label: '蓝色', value: 0 },
{ label: '黄色', value: 1 },
{ label: '橙色', value: 2 },
{ label: '红色', value: 3 }
]}
/>
</Form.Item>
{searchBtn ? <Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item> : null }
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
{
(onSave && addBtn) ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
:null
}
</Form>
</div>
</>
);
}
export default ToolBar;