feat(): 巡查巡检模块开发

master
李神峰 2024-12-26 15:10:07 +08:00
parent f0b8f07df5
commit 043abb1505
38 changed files with 3806 additions and 30 deletions

View File

@ -43,8 +43,8 @@ export function CrudOpRender_text({ command,modify,edit,del,view,status}) {
<div style={{ display: 'inline' }}>
{
status ? (
<Popconfirm title={ `确定要${status.status ==1 ? '停用' : '启用'}吗?`} onConfirm={command('status')}>
<Button style={{ marginRight: 4}} type="link" size="small" title={`${status.status ==1 ? '停用' : '启用'}`}>{ status.status ==1 ? '停用' : '启用'}</Button>
<Popconfirm title={ `确定要${status.status ==1 ? '启用' : '停用'}吗?`} onConfirm={command('status')}>
<Button style={{ marginRight: 4}} type="link" size="small" title={`${status.status ==1 ? '启用' : status.status ==0?'停用' :''}`}>{ status.status ==1 ? '启用' : status.status ==0?'停用' :''}</Button>
</Popconfirm>
) : null
}

View File

@ -23,13 +23,45 @@ const apiurl = {
getDamData: service_xyt + '/gatePore/listByStcd',
getVideo: service_xyt + '/gateValveCctvRel/list'
},
rcgl: {
xcxj: {
xjrw: {
page: service_ykz + "/inspect/task/page",
save: service_ykz + "/inspect/task/insert",
edit: service_ykz + "/inspect/task/update",
delete: service_ykz + "/inspect/task/del",
list: service_ykz + "/inspect/point/listWithItem",
detail: service_ykz + '/inspect/detail/getByTaskId',
info: service_ykz + '/inspect/detail/info'
},
xjwtcl: {
page: service_ykz + "/inspect/detail/page",
},
xjxpz: {
page: service_ykz + "/inspectItem/page",
save: service_ykz + "/inspectItem/insert",
edit: service_ykz + "/inspectItem/update",
delete: service_ykz + "/inspectItem/del",
tree: service_ykz + "/inspect/point/list",
saveTree: service_ykz + "/inspect/point/insert",
editTree: service_ykz + "/inspect/point/update",
deleteTree: service_ykz + "/inspect/point/del",
}
},
},
jcsj: {
bjgl: {
bjgzpz: {
page: service_ykz + '/warnRule/page',
save: service_ykz +'/warnRule/insert',
edit: service_ykz +'/warnRule/update',
delete:service_ykz +'/warnRule/del'
delete: service_ykz + '/warnRule/del',
stop:service_ykz + '/warnRule/startStop'
},
bjjl: {
page: service_ykz + '/warnRecord/page',
export:service_ykz + '/warnRecord/export'
}
},
jcsj: {
@ -39,6 +71,15 @@ const apiurl = {
export:service_ykz + '/stPptnRReal/export'
}
},
aqjc: {
bxjc: {
wypage: service_ykz + '/osmoticShiftR/page',
wysave: service_ykz + '/osmoticShiftR/insert',
wyedit: service_ykz + '/osmoticShiftR/update',
wydelete: service_ykz + '/osmoticShiftR/del',
wyexport:service_ykz + '/osmoticShiftR/export'
}
},
sbwh: {
whfabz: {
page: service_ykz + '/maintainPlan/page',
@ -95,6 +136,12 @@ const apiurl = {
uploadUrl: service_ykz + '/sparePartsInfo/file/upload/singleSimple',
downloadUrl: service_ykz + '/sparePartsInfo/file/download',
export:service_ykz + '/sparePartsInfo/export'
},
zhfxkh: {
page: service_ykz + '/assessAnalysis/page',
save: service_ykz + '/assessAnalysis/insert',
edit: service_ykz + '/assessAnalysis/update',
delete:service_ykz + '/assessAnalysis/del'
}
},
gcyx: {

View File

@ -11,6 +11,7 @@ import Whxmys from "./Sbwh/Whxmys";
import Cgtzgl from "./Sbwh/Cgtzgl";
import Kchsgl from "./Sbwh/Kchsgl";
import Spbjgl from "./Sbwh/Spbjgl";
import Zhfxkh from './Sbwh/Zhfxkh';
import BasicSituation from "./Gcyx/InformationSearch/BasicSituation";
import RunSituation from "./Gcyx/InformationSearch/RunSituation";
import StaticTable from "./Gcyx/InformationSearch/StaticTable";
@ -23,6 +24,13 @@ import UserInfo from './SystemMangant/UserInfo1'
import Dept from './SystemMangant/dept'
import Role from './SystemMangant/role'
import MenuM from './SystemMangant/menuM'
import Bxjc from './SafeWatch/TransformWatch'
import Sljc from './SafeWatch/SlWatch'
import Yjjl from './SafeWatch/WarnRecord'
import Yjgzpz from './SafeWatch/WarnRuleConfig'
import Xjrw from "./Gcyx/xcxj/xjrw"
import Xjwtcl from "./Gcyx/xcxj/xjwtcl"
import Xjxpz from "./Gcyx/xcxj/xjxpz"
import TestLine from './TestLine'
// const HomePage = lazy(() => import('./Home'))
@ -49,6 +57,11 @@ const AppRouters: React.FC = () => {
{ path: 'jcsj/bjgl/bjjl', element: <PoliceRecord /> },
{ path: 'jcsj/bjgl/bjgzpz', element: <PoliceRuleConfig /> },
// 安全监测
{ path: 'aqjc/bxjc', element: <Bxjc /> },
{ path: 'aqjc/sljc', element: <Sljc /> },
{ path: 'aqjc/yjjl', element: <Yjjl /> },
{ path: 'aqjc/yjgzpz', element: <Yjgzpz /> },
// 设备维护
{ path: 'sbwh/wxyhgl/wxfabz', element: <Whfabz /> },
{ path: 'sbwh/wxyhgl/ssgcjl', element: <Ssgcjl /> },
@ -56,13 +69,16 @@ const AppRouters: React.FC = () => {
{ path: 'sbwh/sbwzgl/cgtzgl', element: <Cgtzgl /> },
{ path: 'sbwh/sbwzgl/kchsgl', element: <Kchsgl /> },
{ path: 'sbwh/sbwzgl/bpbjgl', element: <Spbjgl /> },
{ path: 'sbwh/sbwzgl/zhfxkh', element: <Zhfxkh /> },
// 工程运行
// { path: 'gcyx/xxcx/jbqk', element: <BasicSituation /> },
// { path: 'gcyx/xxcx/yxqk', element: <RunSituation /> },
// { path: 'gcyx/xxcx/tjbb', element: <StaticTable /> },
// { path: 'gcyx/xxcx/czrz', element: <OperateLog /> },
// { path: 'gcyx/jsyj/sbgzjl', element: <Sbgzjl /> },
{ path: 'gcyx/xxcx/jbqk', element: <BasicSituation /> },
{ path: 'gcyx/xxcx/yxqk', element: <RunSituation /> },
{ path: 'gcyx/xxcx/tjbb', element: <StaticTable /> },
{ path: 'gcyx/xxcx/czrz', element: <OperateLog /> },
{ path: 'gcyx/jsyj/sbgzjl', element: <Sbgzjl /> },
{ path: 'gcyx/xcxj/xcrw', element: <Xjrw /> },
{ path: 'gcyx/xcxj/xjwtcl', element: <Xjwtcl /> },
{ path: 'gcyx/xcxj/xjxpz', element: <Xjxpz/> },
// 系统管理
{ path: 'xtgl/yhxx', element: <UserInfo /> },
{ path: 'xtgl/bmgl', element: <Dept /> },

View File

@ -0,0 +1,443 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker,Tabs, Tooltip,message,Image,Modal,Typography ,Popconfirm, Descriptions } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined,VideoCameraOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import apiurl from '../../../../service/apiurl';
import NormalSelect from '../../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
import { httpget2 } from '../../../../utils/request';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave,submit }) => {
console.log(record);
const taskTypes = [
{label:"日常巡查",value:0},
{label:"特别检查",value:1},
{label:"汛前巡检",value:2},
]
const statusTypes = [
{label:"未完成",value:0},
{label:"进行中",value:1},
{label:"已完成",value:2},
]
const xjStatus = {
0: "cha",
1:"gou"
}
const renderTooltip = (value) => {
return (
<>
<Descriptions>
<Descriptions.Item label="问题描述" span={3}>
{value?.itemProblemDesc}
</Descriptions.Item>
<Descriptions.Item label="处理建议">
{value?.handleSuggestion}
</Descriptions.Item>
</Descriptions>
</>
)
}
const columns = [
{
title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center",
render: (value, row, index) => <span>{index + 1}</span>
},
{
title: '巡查项', key: 'itemDesc', dataIndex: 'itemDesc', width: 200,
render: (value, row, index) =>
<div style={{ position: "relative" }}>
<div style={{width:"80%",whiteSpace:"nowrap",textOverflow:"ellipsis",overflow:"hidden"}} title={value}>{value}</div>
<span style={{ position: "absolute", top: 0, right: 0 }}>
<Tooltip
title={renderTooltip(row)}
color='#ffffff'
>
<img style={{width:20,height:20}} src={`${process.env.PUBLIC_URL}/assets/xyt/rcgl/wenhao.png`}/>
</Tooltip>
</span>
</div>
},
{ title: '巡查状态', key: 'isNormal', dataIndex: 'isNormal', width: 100, align: "center",
render: (value) => <div>
<img style={{width:value ? 20: 17,height:value ? 20: 17}} src={`${process.env.PUBLIC_URL}/assets/xyt/rcgl/${xjStatus[value]}.png`}
alt='' /></div>
},
{ title: '巡查问题描述', key: 'problemDesc', dataIndex: 'problemDesc', width: 300,ellipsis:true },
{ title: '巡查图片', key: 'inspectPics', dataIndex: 'inspectPics', width: 100,align: "center",
render: (value) => <div>{value ? <a onClick={()=>reviewPic(value)}> { value.length} </a>: ''}</div>
},
{ title: '巡查视频', key: 'inspectVideos', dataIndex: 'inspectVideos', width: 100,align: "center",
render: (value) => <div>{value ? <a onClick={()=>reviewVideo(value)}> { value.length} </a>: ''}</div>
},
{
title: '是否处理', key: 'isHandle', dataIndex: 'isHandle', width: 100,align: "center",
render: (value) => <span>{value? "是" : "否"}</span>
},
{ title: '处理人', key: 'handleUserName', dataIndex: 'handleUserName', width: 150 },
{
title: '操作', key: 'operator', dataIndex: 'operator', width: 150,
render:(value,row) => <a onClick={() =>handleDetail(row)}>处理详情</a>
},
]
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const [form] = Form.useForm();
const [imgVisible, setImgVisible] = useState(false)
const [imgList, setImgList] = useState([])
const [videoOpen, setVideoOpen] = useState(false)
const [videoParams, setVideoParams] = useState({})
const [tabsRender, setTabsRender] = useState([])
const [totals, setTotals] = useState({})
const [handleDetailsOpen, setHandleDetailsOpen] = useState(false)
const [handleDetails, setHandleDetails] = useState({})
const [handleImgfileList, setHandleImgFileList] = useState([]) //上传文件列表
const [handleVideoFileList, setHandleVideoFileList] = useState([]) //上传文件列表
const handleDetail = (row) => {
setHandleDetailsOpen(true)
setHandleDetails(row)
}
const reviewPic = (arrPic) => {
if (arrPic.length > 0) {
setImgVisible(true)
setImgList(arrPic)
}
}
const reviewVideo = (arrVideo) => {
if (arrVideo.length > 0) {
setVideoOpen(true)
setVideoParams(arrVideo[0])
}
}
const renderItems = (items) => {
const result = items.map(o => ({
key: o.pointId,
label: o.name + `(${o.children.filter(r=>r.isNormal == 0).length})`,
children:
<Table
columns={columns}
rowKey={o.id}
pagination={false}
dataSource={o.children}
scroll={{ x: width, y: "calc( 100vh - 400px )" }} />
}))
setTabsRender(result)
}
const getTabsDetail = async (id) => {
let items = {};
try {
const res = await httpget2(apiurl.rcgl.xcxj.xjrw.info,{taskId:id});
renderItems(res.data)
res.data.forEach(o => {
items.isNormalTotal = o.children.filter(item => item.isNormal == 0).length;
items.normalTotal = o.children.filter(item => item.isNormal == 1).length;
})
setTotals(items);
} catch (error) {
console.log(error);
}
}
const handleFile = (arr=[]) => {
const newArr = arr?.map(item => ({
name: item.fileName,
response: {
data: {
filePath: item.filePath,
fileId:item.fileId
}
},
}))
return newArr
}
useEffect(() => {
const handleImgFile = handleFile(handleDetails?.handlePics || []);
const hanldeVideoFile = handleFile(handleDetails?.handleVideos || []);
setHandleImgFileList(handleImgFile)
setHandleVideoFileList(hanldeVideoFile)
}, [handleDetails])
useEffect(() => {
getTabsDetail(record.id)
}, [record])
return (
<div style={{maxHeight:"70vh",overflowY:"auto"}}>
<div
style={{ marginBottom: 20, borderBottom: "1px solid #dfdfdf", width: "100%", paddingBottom: 5 }}>
<span style={{ padding: "0px 3px", backgroundColor: "#0079fe", marginRight: 20 }}></span></div>
<Form
form={form}
{...formItemLayout}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="任务标题"
name="taskTitle"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="任务类型"
name="taskType"
>
<NormalSelect
style={{ width: '100%' }}
allowClear
options={taskTypes}
disabled={mode === 'view'}
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="任务内容"
name="taskContent"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="开始日期"
name="startDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
placeholder=""
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="结束日期"
name="endDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
placeholder=""
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="接收时间"
name="receiveTime"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
placeholder=""
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD HH:mm'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="完成时间"
name="finishTime"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
placeholder=""
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD HH:mm'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="巡查人"
name="inspectUserName"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="任务状态"
name="status"
>
<NormalSelect
disabled={mode==='view'}
style={{width:'100%'}}
allowClear
options={statusTypes}
/>
</Form.Item>
</Col>
</Row>
<div
style={{borderBottom: "1px solid #dfdfdf", width: "100%", paddingBottom: 5,display:"flex" }}>
<span style={{ padding: "0px 3px", backgroundColor: "#0079fe", marginRight: 20 }}></span>
<span>巡查信息</span>
{record?.status == 2 ?
<span style={{ marginLeft: "auto", marginRight: 30 }}>(异常项<span style={{ color: "red" }}>{totals?.isNormalTotal}</span>{totals?.normalTotal})</span>
: null
}
</div>
{
record?.status == 2 ?
<Tabs
defaultActiveKey="1"
items={tabsRender}
tabBarStyle={{marginLeft:20}}
/>
:
<img
src={`${process.env.PUBLIC_URL}/assets/noData.png`}
alt=''
style={{marginLeft: '36%',marginTop:"3%"}}
/>
}
</Form>
<div style={{ display: "none" }}>
<Image.PreviewGroup
preview={{
visible:imgVisible,
onVisibleChange: (vis) => setImgVisible(vis),
}}
>
{
imgList.length > 0 ? imgList.map(item => (
<Image src={ url + item.filePath} key={item?.id}/>
))
: null
}
</Image.PreviewGroup>
</div>
<Modal
open={videoOpen}
width={800}
title="视频预览"
footer={null}
onCancel={() => setVideoOpen(false)}
>
<video
controls
src={url + videoParams?.filePath}
style={{width:"100%",height:"100%"}}
/>
</Modal>
<Modal
open={handleDetailsOpen}
width={800}
title="处理详情"
footer={null}
onCancel={() => setHandleDetailsOpen(false)}
>
<>
<Form
form={form}
{...formItemLayout}
initialValues={handleDetails}
>
<Row>
<Col span={24}>
<Form.Item
label="处理图片"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
handleImgfileList.length > 0 && handleImgfileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理视频"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
handleVideoFileList.length > 0 && handleVideoFileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<div
onClick={() => { setVideoOpen(true); setVideoParams(file)}}
style={{ cursor: 'pointer' }}
>
<VideoCameraOutlined
style={{ fontSize: 40 }}
/>
</div>
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理描述"
name="itemProblemDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
</Form>
</>
</Modal>
</div>
);
}
export default ModalForm;

View File

@ -0,0 +1,351 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, TreeSelect,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import PersonTree from '../../../../components/PersonTree';
import apiurl from '../../../../service/apiurl';
import NormalSelect from '../../../../components/Form/NormalSelect';
import { xyt_httpget2 } from '../../../../utils/request';
import "./index.less"
import moment from 'moment';
import { httpget2 } from '../../../../utils/request';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [itemList, setItemList] = useState([])
const [itemParams, setItemParams] = useState([])
const [list, setList] = useState([])
const taskTypes = [
{label:"日常巡查",value:0},
{label:"特别检查",value:1},
{label:"汛前巡检",value:2},
]
const [form] = Form.useForm();
const handleTree = (arr) => {
const res = arr.map(item => {
item.value = item.id;
item.title = item.itemDesc;
if (item.children) {
item.children = handleTree(item.children)
}
return item;
})
return res
}
const getItemList = async() => {
try {
const res = await httpget2(apiurl.rcgl.xcxj.xjrw.list);
if (res.code === 200) {
const arr1 = res.data.map(item => ({
id: item.id,
itemDesc: item.name,
children: item.children,
disabled:item.children.length > 0 ? false : true
}));
const result = handleTree(arr1)
setList(res.data)
console.log(result);
setItemList(result)
}
} catch (error) {
console.log(error);
}
}
const onfinish = (values) => {
const userId = localStorage.getItem('userId')
const userName = localStorage.getItem('userName')
values.startDate = values.startDate?moment(values.startDate).format("YYYY-MM-DD 00:00:00"):''
values.endDate = values.endDate ? moment(values.endDate).format("YYYY-MM-DD 00:00:00") : ''
values.createUserId = userId
values.createUserName = userName;
values.inspectUserName = deptUserList?.find(item => item.userId == values.inspectUserId)?.nickName
values.items = itemParams;
if (mode === 'save') {
onSave(apiurl.rcgl.xcxj.xjrw.save,values)
}
if (mode == "edit") {
onEdit(apiurl.rcgl.xcxj.xjrw.edit,{...record,...values})
}
}
const itemChange = (a, b, c) => {
const itemArr = a.map(item => {
let pointId;
list.forEach(o => {
if (o.id != item && !pointId) {
pointId = o.children?.find(t => t.id == item)?.pointId;
}
})
return {
itemId: item,
pointId
}
})
setItemParams(itemArr)
}
const getXjInfo = async () => {
try {
const res = await httpget2(apiurl.rcgl.xcxj.xjrw.detail, { taskId: record?.id })
if (res.code === 200) {
const xjd = res.data.map(item => item.itemId)
form.setFieldValue("items", xjd)
setItemParams(res.data)
}
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getItemList()
}, [])
useEffect(() => {
if (mode == "edit") {
getXjInfo()
}
}, [record,mode])
const [deptList, setDeptList] = useState([])
const [deptUserList, setDeptUserList] = useState([])
const buildTree = (data, parentId) => {
let tree = [];
data.forEach((node) => {
node.title = node.deptName;
node.key = node.deptId;
if (node.parentId === parentId) {
let children = buildTree(data, node.deptId);
if (children.length) {
node.children = children;
}
tree.push(node);
}
});
return tree;
}
const handleTreeList = (dept, user) => {
const deptArr = dept.map(item => {
return {
...item,
value: item.deptId,
title: item.deptName,
disabled: item.userId ? false : true,
children: user.filter(u => u.deptId == item.deptId).map(u => ({
...u,
value: u.userId,
title: u.nickName
}))
}
})
console.log("deptArr",deptArr);
const treelist = buildTree(deptArr,0)
return treelist
}
const treeList = useMemo(() => {
if (deptUserList?.length > 0 && deptList?.length > 0) {
return handleTreeList(deptList,deptUserList)
} else {
return []
}
}, [deptUserList, deptList])
// 获取部门数据
const getDeptList = async() => {
try {
const result = await xyt_httpget2(apiurl.rcgl.zbgl.zbb.deptlist);
if (result.code == 200) {
setDeptList(result.data);
getDeptUser(result.data[0])
}
} catch (error) {
console.log(error);
}
}
// 获取部门人员数据
const getDeptUser = async() => {
try {
const result = await xyt_httpget2(apiurl.rcgl.zbgl.zbb.userList, {pageNum:1,pageSize:9999});
if (result.code == 200) {
setDeptUserList(result.rows)
}
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getDeptList()
}, [])
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="任务类型"
name="taskType"
rules={[
{
required: true,
},
]}
>
<NormalSelect
style={{ width: '100%' }}
allowClear
options={taskTypes}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="任务标题"
name="taskTitle"
>
<Input
style={{ width: '100%' }}
allowClear
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="选择巡查人"
name="inspectUserId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<TreeSelect
showSearch
style={{
width: '100%',
}}
dropdownStyle={{
maxHeight: 400,
overflow: 'auto',
}}
allowClear
treeDefaultExpandAll
treeData={treeList}
treeNodeFilterProp='title'
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="巡查项"
name="items"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<TreeSelect
showSearch
style={{
width: '100%',
}}
dropdownStyle={{
maxHeight: 400,
overflow: 'auto',
}}
onChange={itemChange}
allowClear
treeDefaultExpandAll
treeData={itemList}
treeNodeFilterProp='title'
treeCheckable={true}
maxTagCount={1}
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="任务内容"
name="taskContent"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="开始日期"
name="startDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="结束日期"
name="endDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</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,222 @@
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 DetailModalForm from "./detailForm"
import apiurl from '../../../../service/apiurl';
import usePageTable from '../../../../components/crud/usePageTable2';
import { createCrudService } from '../../../../components/crud/_';
import {CrudOpRender_text} from '../../../../components/crud/CrudOpRender';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
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 task = {
0: "未完成",
1: "进行中",
2: "已完成"
}
const taskType = {
1: "日常巡查",
2: "特别检查",
3: "汛前巡检"
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const [tabs, setTabsChange] = useState(0)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{
title: '任务类型', key: 'taskType', dataIndex: 'taskType', width: 200,
render: (value) => <span>{taskType[value]}</span>
},
{ title: '任务标题', key: 'taskTitle', dataIndex: 'taskTitle', width: 250, ellipsis: true },
{title: '任务内容', key: 'taskContent', dataIndex: 'taskContent', width: 200},
{
title: '任务状态', key: 'status', dataIndex: 'status', width: 200,
render: (value) => <span
style={{
display: "flex",
width:"50%",
alignItems: "center",
columnGap:5,
padding: "5px 10px",
color: "#689fff",
border: "1px solid #bbdcff",
background: "#ecf5ff",
borderRadius: "4px"
}}>
<span>{task[value]}</span>
<span style={{
display: "inline-block",
padding: 5,
background:tabs == 1 ? "#ffec00" : tabs == 2 ? "#29c093" : "#d7d7d7"
}}></span>
</span>
},
{title: '巡查人', key: 'inspectUserName', dataIndex: 'inspectUserName', width: 100},
{title: '开始日期', key: 'startDate', dataIndex: 'startDate', width: 200},
{title: '结束日期', key: 'endDate', dataIndex: 'endDate', width: 200},
{title: '问题数量', key: 'problemNum', dataIndex: 'problemNum', width: 100,align: 'center'},
{ title: '待处理', key: 'handleNum', dataIndex: 'handleNum', width: 100,align: 'center'},
{ title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 200 },
{ title: '创建人', key: 'createUserName', dataIndex: 'createUserName', width: 150 },
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={(editBtn && tabs == 0) ? true : false}
del={(delBtn && tabs == 0) ? true : false}
detail={viewBtn ? true : false}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const [modeBtn, setModeBtn] = useState('')
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
setModeBtn(type)
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.rcgl.xcxj.xjrw.delete + `/${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjrw.page).find_noCode);
const { tableProps:tableProps0, search:search0 } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjrw.page).find_noCode);
const { tableProps:tableProps1, search:search1 } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjrw.page).find_noCode);
const { tableProps:tableProps2, search:search2 } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjrw.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
setTabsChange(0)
}
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
status: Number(tabs),
createUserId:userId
}
};
search(params)
}
}, [searchVal, tabs])
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
status: 0,
createUserId:userId
}
};
search0(params)
}
}, [searchVal])
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
status: 1,
createUserId:userId
}
};
search1(params)
}
}, [searchVal])
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
status: 2,
createUserId:userId
}
};
search2(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" }}>
<Tabs
// defaultActiveKey={0}
onChange={(e) => setTabsChange(e)}
activeKey={tabs}
items={[
{
label: `未完成(${tableProps0?.pagination?.total}`,
key: 0,
children:<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
},
{
label: `进行中(${tableProps1?.pagination?.total}`,
key: 1,
children:<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
},
{
label: `已完成(${tableProps2?.pagination?.total}`,
key: 2,
children:<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
}
]}
>
</Tabs>
</div>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
title1="巡查任务详情"
component={modeBtn == "view"? DetailModalForm : ModalForm}
onCrudSuccess={successCallback}
// onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,30 @@
.basic-info{
position: relative;
font-size: 16px;
margin-bottom: 20px;
padding:5px 25px;
border-bottom: 1px solid #eee;
&::before{
position: absolute;
top:8px;
left:0;
content: "";
display: block;
width: 5px;
height: 20px;
background-color: #0079fe;
}
}
.time-line{
width: 50%;
margin-left: 6%;
margin-top: 1%;
.time-line-item{
display: flex;
// align-items: center;
column-gap: 20px;
.item-right{
flex:1
}
}
}

View File

@ -0,0 +1,73 @@
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 types = [
{label:"日常巡查",value:1},
{label:"特别检查",value:2},
{label:"汛前巡检",value:3},
]
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,"years").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="taskType">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</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,347 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined,VideoCameraOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import apiurl from '../../../../service/apiurl';
import NormalSelect from '../../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave,submit }) => {
console.log(record);
const [form] = Form.useForm();
const [imgfileList, setImgFileList] = useState([]) //上传文件列表
const [videoFileList, setVideoFileList] = useState([]) //上传文件列表
const [handleImgfileList, setHandleImgFileList] = useState([]) //上传文件列表
const [handleVideoFileList, setHandleVideoFileList] = useState([]) //上传文件列表
const [videoOpen, setVideoOpen] = useState(false)
const [videoParams, setVideoParams] = useState({})
const onfinish = (values) => {
if (mode === 'edit') {
values.id = record.id;
onEdit(apiurl.rcgl.xcxj.xjrw.edit,values)
}
if (mode === 'save') {
onSave(apiurl.rcgl.xcxj.xjrw.save,values)
}
}
const handleFile = (arr=[]) => {
const newArr = arr?.map(item => ({
name: item.fileName,
response: {
data: {
filePath: item.filePath,
fileId:item.fileId
}
},
}))
return newArr
}
useEffect(() => {
if (mode != 'save') {
// const imgFile = record?.inspectPics?.map(o => ({
// name: o.fileName,
// response: {
// data: {
// filePath: o.filePath,
// fileId:o.fileId
// }
// },
// }))
const imgFile = handleFile(record?.inspectPics);
const videoFile = handleFile(record?.inspectVideos);
const handleImgFile = handleFile(record?.handlePics);
const hanldeVideoFile = handleFile(record?.handleVideos);
setImgFileList(imgFile)
setVideoFileList(videoFile)
setHandleImgFileList(handleImgFile)
setHandleVideoFileList(hanldeVideoFile)
form.setFieldsValue({
...record,
handleTime: record.handleTime ? moment(record.handleTime) : '',
finishTime: record.finishTime? moment(record.finishTime) : ''
})
}
}, [record, mode])
return (
<div style={{maxHeight:"70vh",overflowY:"auto"}}>
<div
style={{ marginBottom: 20, borderBottom: "1px solid #dfdfdf", width: "100%", paddingBottom: 5 }}>
<span style={{ padding: "0px 3px", backgroundColor: "#0079fe", marginRight: 20 }}></span></div>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
>
<Row>
<Col span={12}>
<Form.Item
label="任务标题"
name="taskTitle"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="巡检点"
name="name"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="巡查项"
name="itemDesc"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="巡检问题描述"
name="problemDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="巡查人"
name="inspectUserName"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="巡查时间"
name="finishTime"
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD HH:mm:ss'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="巡查图片"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
imgfileList.length > 0 && imgfileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="巡查视频"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
videoFileList.length > 0 && videoFileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<div
onClick={() => { setVideoOpen(true); setVideoParams(file)}}
style={{ cursor: 'pointer' }}
>
<VideoCameraOutlined
style={{ fontSize: 40 }}
/>
</div>
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<div
style={{ marginBottom: 20, borderBottom: "1px solid #dfdfdf", width: "100%", paddingBottom: 5 }}>
<span style={{ padding: "0px 3px", backgroundColor: "#0079fe", marginRight: 20 }}></span></div>
<Row>
<Col span={12}>
<Form.Item
label="处理状态"
name="isHandle"
>
<NormalSelect
disabled={mode === 'view'}
style={{ width: '100%' }}
allowClear
options={[{label:"待处理",value:0},{label:"已处理",value:1}]} />
</Form.Item>
</Col>
{
(record?.isHandle || record?.isHandle == 0) ?
<Col span={12}>
<Form.Item
label="处理人"
name="handleUserName"
>
<Input disabled={mode==='view'} style={{width:'100%'}} />
</Form.Item>
</Col> : null
}
</Row>
{
record?.isHandle ?
<>
<Row>
<Col span={12}>
<Form.Item
label="处理时间"
name="handleTime"
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD HH:mm:ss'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理内容"
name="handleDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理图片"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
handleImgfileList.length > 0 && handleImgfileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理视频"
name="picId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Row gutter={[16]}>
{
handleVideoFileList.length > 0 && handleVideoFileList.map(file => {
return (
<Col span={12}>
<div className={mode == "view" ? 'file-item view-file' : 'file-item'} >
<div className='file-description'>
<div
onClick={() => { setVideoOpen(true); setVideoParams(file)}}
style={{ cursor: 'pointer' }}
>
<VideoCameraOutlined
style={{ fontSize: 40 }}
/>
</div>
<span>{file.name}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
</> : null
}
<Form.Item {...btnItemLayout}>
<Button type="primary" onClick={() => submit()}>
关闭
</Button>
</Form.Item>
</Form>
<Modal
open={videoOpen}
width={800}
title="视频预览"
footer={null}
onCancel={() => setVideoOpen(false)}
>
<video
controls
src={url + videoParams?.response?.data?.filePath}
style={{width:"100%",height:"100%"}}
/>
</Modal>
</div>
);
}
export default ModalForm;

View File

@ -0,0 +1,197 @@
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';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const role = useSelector(state => state.auth.role);
const viewBtn = role?.rule?.find(item => item.menuName == "详情") || true;
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const [tabs, setTabsChange] = useState(0)
const [imgVisible, setImgVisible] = useState(false)
const [imgList, setImgList] = useState([])
const [videoOpen, setVideoOpen] = useState(false)
const [videoParams, setVideoParams] = useState({})
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ title: '任务标题', key: 'taskTitle', dataIndex: 'taskTitle', width: 250, ellipsis: true },
{title: '巡检点', key: 'name', dataIndex: 'name', width: 200},
{
title: '巡查项', key: 'itemDesc', dataIndex: 'itemDesc', width: 200,
},
{title: '巡查问题描述', key: 'problemDesc', dataIndex: 'problemDesc', width: 200},
{
title: '巡查图片', key: 'inspectPics', dataIndex: 'inspectPics', width: 100,
render: (value) => <div>{value ? <a onClick={()=>reviewPic(value)}> { value.length} </a>: ''}</div>
},
{
title: '巡查视频', key: 'inspectVideos', dataIndex: 'inspectVideos', width: 100,
render: (value) => <div>{value ? <a onClick={()=>reviewVideo(value)}> { value.length} </a>: ''}</div>
},
{
title: '处理状态', key: 'isHandle', dataIndex: 'isHandle', width: 200, align: 'center',
render: (value) => <span style={value == 1 ?{color:"green"}: {color:"red"}}>{ value == 1 ? "已处理" : value == 0 ? "待处理" : ''}</span>
},
{ title: '巡查人', key: 'inspectUserName', dataIndex: 'inspectUserName', width: 150 },
{ title: '巡查完成时间', key: 'finishTime', dataIndex: 'finishTime', width: 200 },
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
detail={viewBtn ? true : false}
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.rcgl.xcxj.xjrw.delete + `/${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjwtcl.page).find_noCode);
const { tableProps:tableProps0, search:search0 } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjwtcl.page).find_noCode);
const { tableProps:tableProps1, search:search1 } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjwtcl.page).find_noCode);
const reviewPic = (arrPic) => {
if (arrPic.length > 0) {
setImgVisible(true)
setImgList(arrPic)
}
}
const reviewVideo = (arrVideo) => {
if (arrVideo.length > 0) {
setVideoOpen(true)
setVideoParams(arrVideo[0])
}
}
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
isHandle: Number(tabs),
inspectUserId:userId
}
};
search(params)
}
}, [searchVal,tabs])
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
isHandle: 0,
inspectUserId:userId
}
};
search0(params)
}
}, [searchVal])
useEffect(() => {
const userId = localStorage.getItem('userId')
if (searchVal) {
const params = {
search: {
...searchVal,
isHandle: 1,
inspectUserId:userId
}
};
search1(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" }}>
<Tabs defaultActiveKey={0} onChange={(e) => setTabsChange(e)} >
<Tabs.TabPane tab={`待处理(${tableProps0?.pagination?.total}`} key={0}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
</Tabs.TabPane>
<Tabs.TabPane tab={`已处理(${tableProps1?.pagination?.total}`} key={1}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
</Tabs.TabPane>
</Tabs>
</div>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
title1="详情"
/>
</div>
<div style={{ display: "none" }}>
<Image.PreviewGroup
preview={{
visible:imgVisible,
onVisibleChange: (vis) => setImgVisible(vis),
}}
>
{
imgList.length > 0 ? imgList.map(item => (
<Image src={ url + item.filePath} key={item?.id}/>
))
: null
}
</Image.PreviewGroup>
</div>
<Modal
open={videoOpen}
width={800}
title="视频预览"
footer={null}
onCancel={() => setVideoOpen(false)}
>
<video
controls
src={url + videoParams?.filePath}
style={{width:"100%",height:"100%"}}
/>
</Modal>
</>
);
}
export default Page;

View File

@ -0,0 +1,30 @@
.basic-info{
position: relative;
font-size: 16px;
margin-bottom: 20px;
padding:5px 25px;
border-bottom: 1px solid #eee;
&::before{
position: absolute;
top:8px;
left:0;
content: "";
display: block;
width: 5px;
height: 20px;
background-color: #0079fe;
}
}
.time-line{
width: 50%;
margin-left: 6%;
margin-top: 1%;
.time-line-item{
display: flex;
// align-items: center;
column-gap: 20px;
.item-right{
flex:1
}
}
}

View File

@ -0,0 +1,53 @@
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 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,"years").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>
{searchBtn ? <Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item> : null }
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,47 @@
li.ant-tree-treenode-disabled > span:not(.ant-tree-switcher),
li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper,
li.ant-tree-treenode-disabled > .ant-tree-node-content-wrapper span{
color: #000 !important;
font-weight: bold;
}
.treeBox1{
.ant-tree-node-content-wrapper{
position: static !important;
}
.hover-ele{
&:hover{
color:#259dff
}
}
}
.AdcdTreeSelectorStyle{
.ant-input-wrapper{
.ant-input-affix-wrapper{
width: 98%;
}
.ant-input-group-addon{
.ant-btn{
width: 34px;
height: 34px;
}
}
}
.treeTitle {
display: flex;
justify-content: space-between;
.treeBtn {
display: none;
}
}
.treeTitle:hover {
.treeBtn {
display: flex;
}
}
}
.no-matter{
opacity: 0.5;
}

View File

@ -0,0 +1,313 @@
import React, { useState, useEffect } from 'react';
import { Tree, Input, Checkbox, Spin,Modal,Form,Col,Row,message,Space } from 'antd';
import { EditOutlined,PlusCircleOutlined, DeleteOutlined,ExclamationCircleOutlined} from '@ant-design/icons';
import './index.less';
import { formItemLayout, btnItemLayout } from '../../../../../components/crud/FormLayoutProps';
import { getXjTreeData } from '../../../../../service/warn';
import apiurl from '../../../../../service/apiurl';
import { httppost3,httpget6 } from '../../../../../utils/request';
const { Search } = Input;
type IProps = {
onSelectFun?: any;
setAdcd?: any;
showCheckbox: any;
tableName?: any;
onChangeOpen?: any;
hasAlertBox?: boolean;//顶部是否有预警条
isFetch?: boolean;
}
const { confirm } = Modal;
const AdcdTreeSelector: React.FC<IProps> = ({ onSelectFun, setAdcd, showCheckbox, tableName, hasAlertBox }) => {
const [loading, setLoading] = useState(true);
const [treeData, setTreeData] = useState([]);
const [newTreeData, setNewTreeData] = useState([]);
const [isFiter, setIsFiter] = useState(false);
const [expandedKeys, setExpandedKeys] = useState([]);
const [checkedKeys, setCheckedKeys] = useState([]);
const [selectedKeys, setSelectedKeys] = useState<any>([]);
const [selectedItem, setSelectedItem] = useState({});
const [autoExpandParent, setAutoExpandParent] = useState(true);
const [treeBoxHeight, setTreeBoxHeight] = useState({});
const [jdOpen, setJdOpen] = useState(false)
const [form] = Form.useForm();
const [mode, setMode] = useState('')
const [itemDetail, setItemDetail] = useState<any>({})
const [orderMax, setOrderMax] = useState<any>(0)
useEffect(() => {
getCustomerTreeData();
}, []);
useEffect(() => {
if(tableName){
setSelectedKeys([]);
}
}, [tableName]);
useEffect(()=>{
//根据预警条计/多选框计算高度
if(hasAlertBox){
if(showCheckbox){
setTreeBoxHeight({height:"calc( 100vh - 240px )"})
}else{
setTreeBoxHeight({height:"calc( 100vh - 210px )"})
}
}else{
if(showCheckbox){
setTreeBoxHeight({height:"calc( 100vh - 224px )"})
}else{
setTreeBoxHeight({height:"calc( 100vh - 194px )"})
}
}
},[hasAlertBox])
const getCustomerTreeData = async () => {
const adcdTreedata: any = await getXjTreeData();
const item:any = adcdTreedata
if (item) {
setSelectedKeys([item[0]?.id])
setAdcd(item[0]?.id)
}
if (adcdTreedata.length > 0) {
handelTreeData(adcdTreedata);
setTreeData(adcdTreedata);
setLoading(false);
setOrderMax(Math.max(...adcdTreedata.map((item:any) => item?.orderIndex)))
} else {
setLoading(false);
setTreeData([]);
}
};
// @ts-ignore
const handelTreeData = (data) => {
if (data.length > 0) {
// @ts-ignore
data.forEach(item => {
item.title = item.name;
item.key = item.id;
if (item.children && item.children.length > 0) {
handelTreeData(item.children);
}
});
}
}
const onExpand = (expandedKeysValue:any) => {
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
const onSelect = (selectedKeysValue:any, info:any) => {
setSelectedKeys(selectedKeysValue);
setSelectedItem(info);
if (info.selectedNodes.length > 0) {
let selectData = info.selectedNodes[0];
let adcdVal = "";
adcdVal = selectData.key;
let params = { id: adcdVal };
if(onSelectFun){
onSelectFun(params);
}
if(setAdcd){
setAdcd(adcdVal)
}
} else {
let params = { id: "" };
if(onSelectFun){
onSelectFun(params);
}
if(setAdcd){
setAdcd("")
}
}
};
// 删除
const deleteJd = (v: any) => {
confirm({
title: '删除',
icon: <ExclamationCircleOutlined />,
content: '确认删除此数据',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk: async() => {
try {
const res = await httpget6(apiurl.rcgl.xcxj.xjxpz.deleteTree + `/${v.id}`)
if (res.code === 200) {
message.success('删除成功');
getCustomerTreeData();
}
if (res.code === 400) {
message.error(res.description);
}
} catch (error) {
console.log(error);
}
},
onCancel() {
console.log('Cancel');
},
});
}
// 新增节点
const saveJd = (v: any) => {
if (v) {
// form.setFieldValue('name', v.title);
setItemDetail(v);
}
setJdOpen(true);
setMode("save");
}
// 编辑节点
const editJd = (v: any) => {
setJdOpen(true);
form.setFieldsValue(v);
setMode("edit");
setItemDetail(v);
}
const onOk = async () => {
const name = form.getFieldValue('name');
const url = mode == "save" ? apiurl.rcgl.xcxj.xjxpz.saveTree : apiurl.rcgl.xcxj.xjxpz.editTree;
let saveParams = {
name,
parentId: itemDetail?.id || undefined,
orderIndex:itemDetail?.orderIndex || orderMax
}
let editParams = {
...itemDetail,
name
}
try {
const res = await httppost3(url, mode == "save" ? saveParams:editParams)
if (res.code == 200) {
message.success(mode == "save" ? '新增成功' : '编辑成功');
setJdOpen(false);
getCustomerTreeData();
form.resetFields();
} else if (res.code == 400) {
message.error(res.description);
}
} catch (error) {
console.log(error);
}
}
return (
<div className='AdcdTreeSelectorStyle'>
<div
style={{
padding: '10px',
color: "#409eff",
borderBottom: "1px solid #dfdfdf",
marginBottom: 20,
cursor: "pointer"
}}
onClick={saveJd}
></div>
{
loading?
<div style={{position:"absolute",top:"200px",left:"35%",background:"#fff",padding:"20px 30px",borderRadius:"10px"}}>
<Spin tip="正在加载..." size="large" spinning={loading} />
</div>:null
}
<div className="treeBox1" style={{...treeBoxHeight,marginTop:"10px"}}>
<div style={{ width: "300px"}}>
{
treeData.length > 0 &&
<Tree
defaultExpandAll={true}
blockNode={false}
onExpand={onExpand}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={isFiter ? newTreeData : treeData}
showLine={true}
titleRender={(v: any) => {
return (
<div
style={{width:200}}
className='treeTitle'
>
<span>{v.title}</span>
<Space
size={4}
className='treeBtn'
>
{/* <PlusCircleOutlined
style={{ fontSize: 15 }}
title='新增'
onClick={(e) => {
e.stopPropagation();
saveJd(v);
}}
className='hover-ele'
/> */}
<EditOutlined
title='编辑'
style={{ fontSize: 15 }}
onClick={(e) => {
e.stopPropagation();
editJd(v);
}}
className='hover-ele'
/>
<DeleteOutlined
title='删除'
style={{ fontSize: 15 }}
onClick={(e) => {
e.stopPropagation();
deleteJd(v);
}}
className='hover-ele'
/>
</Space>
</div>
)
}}
/>
}
</div>
</div>
<Modal
open={jdOpen}
title={mode == "save" ? "新增" : '编辑'}
destroyOnClose
onCancel={() => { setJdOpen(false); form.resetFields()}}
onOk={onOk}
>
<Form form={form} {...formItemLayout}>
<Row>
<Col span={24}>
<Form.Item
label="巡检点"
name="name"
rules={[{required: true}]}
>
<Input allowClear/>
</Form.Item>
</Col>
</Row>
</Form>
</Modal>
</div>
);
};
export default AdcdTreeSelector;

View File

@ -0,0 +1,110 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, TreeSelect, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import { httpget2, httppost2,xyt_httpget2 } from '../../../../utils/request';
import apiurl from '../../../../service/apiurl';
import NormalSelect from '../../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [form] = Form.useForm();
const onfinish = (values) => {
values.pointId = record.code;
if (mode === 'edit') {
values.id = record.id;
values.status = record.status;
onEdit(apiurl.rcgl.xcxj.xjxpz.edit,values)
}
if (mode === 'save') {
onSave(apiurl.rcgl.xcxj.xjxpz.save,values)
}
}
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={24}>
<Form.Item
label="巡检项描述"
name="itemDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="问题描述"
name="problemDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="处理建议"
name="handleSuggestion"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="排序号"
name="orderIndex"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</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,141 @@
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,Switch } from 'antd';
import {FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux';
import AdcdTreeSelector from "./AdcdTreeSelector";
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';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const role = useSelector(state => state.auth.role);
console.log(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 checkType = {
1: "低风险",
2: "一般风险",
3: "较大风险",
4:"重大风险"
}
const risk = {
1: "low",
2: "yiban",
3: "jiaoda",
4:"zhongda"
}
const refModal = useRef();
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{title: '巡检项描述', key: 'itemDesc', dataIndex: 'itemDesc', width: 240},
{
title: '问题描述', key: 'problemDesc', dataIndex: 'problemDesc', width: 320,ellipsis:true},
{
title: '处理建议', key: 'handleSuggestion', dataIndex: 'handleSuggestion', width: 200 },
{
title: '排序号', key: 'orderIndex', dataIndex: 'orderIndex', width: 100,
},
{
title: '是否启用', key: 'status', dataIndex: 'status', width: 200,
render: (v, r) => <Switch
checkedChildren="启用"
unCheckedChildren="禁用"
checked={v == 0 ? true : false} onChange={(e) => {
onEdit(apiurl.rcgl.xcxj.xjxpz.edit,{...r, status:e ? 0 : 1})
}} />
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={editBtn ? true : false}
del={delBtn ? true : false}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const [code, setCode] = useState()
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave({code});
} else if (type === 'edit') {
refModal.current.showEdit({ ...params,code });
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDeleteGet(apiurl.rcgl.xcxj.xjxpz.delete + `/${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.rcgl.xcxj.xjxpz.page).find_noCode);
const onEdit = (path,values) => {
createCrudService(path).edit(values).then((result) => {
if (result?.code === 200) {
refresh()
}
})
}
useEffect(() => {
if (code) {
let params = {
search: {
menuId:code,
}
};
search(params)
}
}, [code]);
return (
<>
<div className='content-box' style={{ backgroundColor: '#fff', height: '100%',display:'flex',padding:'10px' }}>
<div className='lf adcdTreeSelectorBox' style={{height:'calc(100vh - 168px)',width:'340px'}}>
<AdcdTreeSelector hasAlertBox={false} setAdcd={setCode}/>
</div>
<div className='AdcdTreeTableBox' style={{flex:1,overflowX:"auto"}}>
<Card className='nonebox'>
<ToolBar
onSave={command('save')}
role={role}
/>
</Card>
<Table
columns={columns}
rowKey="id"
{...tableProps}
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
/>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={refresh}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,30 @@
.basic-info{
position: relative;
font-size: 16px;
margin-bottom: 20px;
padding:5px 25px;
border-bottom: 1px solid #eee;
&::before{
position: absolute;
top:8px;
left:0;
content: "";
display: block;
width: 5px;
height: 20px;
background-color: #0079fe;
}
}
.time-line{
width: 50%;
margin-left: 6%;
margin-top: 1%;
.time-line-item{
display: flex;
// align-items: center;
column-gap: 20px;
.item-right{
flex:1
}
}
}

View File

@ -0,0 +1,43 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import moment from 'moment';
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role }) => {
console.log("role",role);
const addBtn = role?.rule?.find(item => item.menuName == "新增");
const [form] = Form.useForm();
const onFinish = (values) => {
let dateSo;
if (values.tm) {
dateSo = {
start: moment(values.tm[0]).format('YYYY-MM-DD 00:00:00'),
end: moment(values.tm[1]).format('YYYY-MM-DD 00:00:00')
}
}
delete values.tm
setSearchVal({...values, dateSo});
}
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
{
(onSave) ?
<Form.Item>
<Button onClick={onSave} type='primary'>新增</Button>
</Form.Item>
:null
}
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,72 @@
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 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 types = {
0: "设备维修",
1: '设备更换',
2:"结构加固"
}
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '监测断面', key: 'projectName', dataIndex: 'projectName', width: 150},
{ title: '测点编号', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{ title: '测压管水位(m)', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{ title: '渗压(KPa)', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{ title: '振弦(Hz)', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{ title: '温度(℃)', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{
title: '监测时间', key: 'createTime', dataIndex: 'createTime', width: 140,
},
];
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 exportExcel = () => {
let params = {
...searchVal,
}
httppost5(apiurl.sbwh.cgtzgl.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,71 @@
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, exportFile1, storeData, role }) => {
const types = [
{
label: "设备维修",
value: 0
},
{
label: "设备更换",
value: 1
}, {
label: "结构加固",
value: 2
},
]
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="projectName">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item label="测点编号" name="maintainType">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</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

@ -0,0 +1,97 @@
import React, { useEffect, useState, useMemo, useRef } from 'react';
import { Form, Button, Input, Row, Upload, Col, Table, DatePicker, InputNumber, message, Image, Modal, Typography, Popconfirm } from 'antd';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import "./index.less"
import moment from 'moment';
const { RangePicker } = DatePicker
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const [form] = Form.useForm();
const onfinish = (values) => {
values.tm = values.tm ? moment(values.tm).format('YYYY-MM-DD 00:00:00') : undefined
if (mode === 'edit') {
onEdit(apiurl.aqjc.bxjc.wyedit, { ...record, ...values })
}
if (mode === 'save') {
onSave(apiurl.aqjc.bxjc.wysave, values)
}
}
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="监测点"
name="stationCode"
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="X方向位移(mm)"
name="x"
>
<InputNumber disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="Y方向位移(mm)"
name="y"
>
<InputNumber disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="H方向位移(mm)"
name="h"
>
<InputNumber disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="上报时间"
name="tm"
getValueFromEvent={(e, dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode === 'view'} format={'YYYY-MM-DD'} style={{ width: '100%' }} allowClear />
</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,143 @@
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 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 { httppost5 } from '../../../utils/request';
import { exportFile } from '../../../utils/tools.js';
const Page = () => {
const types = {
0: "设备维修",
1: '设备更换',
2: "结构加固"
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const [tabsActive, setTabsActive] = useState("1")
const wColumns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ title: '监测点', key: 'stationCode', dataIndex: 'stationCode', width: 150},
{ title: 'X方向位移(mm)', key: 'x', dataIndex: 'x', width: 150},
{ title: 'Y方向位移(mm)', key: 'y', dataIndex: 'y', width: 150 },
{ title: 'H方向位移(mm)', key: 'h', dataIndex: 'h', width: 150 },
{
title: '上报时间', key: 'tm', dataIndex: 'tm', width: 140,
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right', align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={true}
del={true}
view={true}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const jColumns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{ title: '监测点', key: 'stationCode', dataIndex: 'stationCode', width: 150},
{ title: '缝开度(mm)', key: 'createUserName', dataIndex: 'createUserName', width: 150 },
{
title: '监测时间', key: 'tm', dataIndex: 'tm', width: 140,
},
];
const columns = useMemo(() => {
return tabsActive == '1' ? wColumns : jColumns
},[tabsActive])
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.aqjc.bxjc.wydelete + `/${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.aqjc.bxjc.wypage).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
// 导出
const exportExcel = () => {
let params = {
...searchVal,
}
httppost5(apiurl.aqjc.bxjc.wyexport, params).then(res => {
exportFile(`${tabsActive == '1' ? '水平位移':'结构缝开度'}.xlsx`,res.data)
})
}
useEffect(() => {
const params = {
search: {
...searchVal,
}
};
search(params)
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{ paddingBottom: "0" }}>
<Tabs
defaultActiveKey="1"
onChange={(e) => {setTabsActive(e) }}
items={[
{
label: '水平位移',
key: '1',
},
{
label: '结构缝开度',
key: '2',
}
]}
/>
<div className='lf CrudAdcdTreeTableBox' style={{ width: "100%", overflowY: "auto" }}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
tabsActive={tabsActive}
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>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={successCallback}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,60 @@
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, tabsActive, exportFile1 }) => {
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="stationCode">
<Input allowClear style={{ width: '150px' }} />
</Form.Item>
<Form.Item label={`${tabsActive == '1' ? '上报时间' : '监测时间'}`} 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>
{
(onSave && tabsActive == '1') ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
: null
}
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,83 @@
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 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 types = {
0: "水平位移",
1: '结构缝开度',
2: "渗流监测",
3:'环境量监测'
}
const statusTypes = {
0: "报警中",
1: '已解除',
}
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{
title: '监测类型', key: 'projectName', dataIndex: 'projectName', width: 150,
render: (v) => <span>{types[v]}</span>
},
{ title: '监测点', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{ title: '监测值', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{
title: '状态', key: 'projectAddr', dataIndex: 'projectAddr', width: 150,
render: (v) => <span>{statusTypes[v]}</span>
},
{ title: '预警依据', key: 'projectAddr', dataIndex: 'projectAddr', width: 250},
{ title: '预警时间', key: 'projectAddr', dataIndex: 'projectAddr', width: 150},
{
title: '持续时长', key: 'createTime', dataIndex: 'createTime', width: 150,
},
];
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 exportExcel = () => {
let params = {
...searchVal,
}
httppost5(apiurl.sbwh.cgtzgl.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,88 @@
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, exportFile1, storeData, role }) => {
const types = [
{
label: "水平位移",
value: 0
},
{
label: "结构缝开度",
value: 1
},
{
label: "渗流监测",
value: 2
},
{
label: "环境量监测",
value: 3
}
]
const typeStatus = [
{
label: "报警中",
value: 0
},
{
label: "已解除",
value: 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="projectName">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item label="预警时间" name="tm">
<RangePicker
allowClear
showTime
style={{ width: "330px" }}
format="YYYY-MM-DD HH:mm:ss"
/>
</Form.Item>
<Form.Item label="状态" name="status">
<NormalSelect allowClear style={{ width: '150px' }} options={typeStatus} />
</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

@ -0,0 +1,106 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
const { RangePicker } = DatePicker
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const types = [
{
label: "闸后流量",
value: 0,
},
{
label: "雨量",
value: 1,
},
{
label: "闸前水位",
value:2,
},
{
label: "闸后水位",
value: 3,
},
]
const [form] = Form.useForm();
const onfinish = (values) => {
values.eventsDate = values.eventsDate?moment(values.eventsDate).format("YYYY-MM-DD 00:00:00"):''
if (mode === 'edit') {
onEdit(apiurl.jcsj.bjgl.bjgzpz.edit,{...record,...values})
}
if (mode === 'save') {
onSave(apiurl.jcsj.bjgl.bjgzpz.save,values)
}
}
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="监测项目"
name="type"
rules={[{ required: true }]}
>
<NormalSelect allowClear style={{ width: '100%' }} options={types} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="阈值下限"
name="upperLimit"
rules={[{ required: true }]}
>
<InputNumber disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="阈值上限"
name="lowerLimit"
rules={[{ required: true }]}
>
<InputNumber disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="备注"
name="remark"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</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,128 @@
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 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 { httppost2 } from '../../../utils/request';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const types = {
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: 'type', dataIndex: 'type', width: 150,
render: (v) => <span>{types[v]}</span>
},
{ title: '阈值下限', key: 'upperLimit', dataIndex: 'upperLimit', width: 150},
{ title: '阈值上限', key: 'lowerLimit ', dataIndex: 'lowerLimit', width: 150},
{
title: '是否启用', key: 'status', dataIndex: 'status', width: 150,
render: (v) => <span>{ v == 1 ? '否': v==0?'是':''}</span>
},
{
title: '配置时间', key: 'createTime', dataIndex: 'createTime', width: 150,
},
{
title: '最近报警时间', key: 'eventsDate', dataIndex: 'eventsDate', width: 140,
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={ true }
del={ true }
status={{status:row.status,bol:true}}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const stopStatus = async (params) => {
try {
const res = await httppost2(apiurl.jcsj.bjgl.bjgzpz.stop, params)
if (res.code == 200) {
message.success(`${params.status ? '停用':'启用'}成功`)
refresh()
}
} catch (error) {
console.log(error);
}
}
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.jcsj.bjgl.bjgzpz.delete + `/${params.id}`);
} else if (type == 'status') {
stopStatus({ id: params.id, status: params.status == 1 ? 0 : params.status == 0 ? 1 : ''})
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.jcsj.bjgl.bjgzpz.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
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}
onSave={command('save')}
/>
</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}
/>
</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, role }) => {
const types = [
{
label: "闸后流量",
value: 0,
},
{
label: "雨量",
value: 1,
},
{
label: "闸前水位",
value: 2,
},
{
label: "闸后水位",
value: 3,
},
]
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="type">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item>
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
{
(onSave) ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
:null
}
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,173 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import {getCurrentQuarter,getQuarterStartEndDates} from "../../../utils/tools"
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
const { RangePicker } = DatePicker
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const types = [
{
label: "年度",
value: 1
},
{
label: "季度",
value: 2
},{
label: "月度",
value: 3
},
]
const [form] = Form.useForm();
const [taskType, setTaskType] = useState(2)
const onfinish = (values) => {
const userId = localStorage.getItem('userId')
const userName = localStorage.getItem('userName')
values.createUserId = userId;
values.createUserName = userName;
values.startDate =values.dateRangeSo? moment(values.dateRangeSo[0]).format("YYYY-MM-DD 00:00:00") :'';
values.endDate = values.dateRangeSo ? moment(values.dateRangeSo[1]).format("YYYY-MM-DD 23:59:59") : '';
if (mode === 'edit') {
onEdit(apiurl.sbwh.zhfxkh.edit,{...record,...values})
}
if (mode === 'save') {
onSave(apiurl.sbwh.zhfxkh.save,values)
}
}
const onvaluesChange = (changedValues) => {
if ("assessFreq" in changedValues) {
setTaskType(changedValues["assessFreq"]);
}
}
useEffect(() => {
if (mode != 'save') {
let dataSo = record.startDate && record.endDate ?
[moment(record.startDate), moment(record.startDate)] : ''
form.setFieldValue("dateRangeSo", dataSo)
}else{
form.setFieldValue("assessFreq", 2)
}
}, [record,mode])
useEffect(() => {
if (mode == "save") {
if (taskType == 2) {
const { startDate, endDate } = getQuarterStartEndDates(getCurrentQuarter('').value, moment().year());
form.setFieldValue("assessBatch", moment())
form.setFieldValue("dateRangeSo",[moment(startDate), moment(endDate)])
} else if (taskType == 1) {
form.setFieldValue("assessBatch", moment())
form.setFieldValue("dateRangeSo",[moment().startOf('year'), moment().endOf('year')])
} else {
form.setFieldValue("assessBatch", moment().format('YYYY-MM-DD'))
form.setFieldValue("dateRangeSo",[moment().startOf('month'), moment().endOf('month')])
}
}
}, [taskType,mode])
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
onValuesChange={onvaluesChange}
>
<Row>
<Col span={12}>
<Form.Item
label="考核对象"
name="objectName"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="考核频次"
name="assessFreq"
rules={[{ required: true }]}
>
<NormalSelect
allowClear
disabled={mode==='view'}
style={{ width: "100%" }}
options={types}
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="考核批次"
name="assessBatch"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
rules={[
{
required: true,
},
]}
>
<DatePicker
disabled={mode === 'view'}
// format={'YYYY-MM-DD'}
style={{ width: '100%' }}
allowClear
picker={taskType == 2 ? "quarter" : taskType == 1 ? "year" : "month"}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="考核周期"
name="dateRangeSo"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => {
return {
value: value ? [value[0]&&moment(value[0]),value[1]&&moment(value[1])] : undefined
};
}}
>
<RangePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="考核分数"
name="assessScore"
>
<InputNumber disabled={mode==='view'} style={{width:'100%'}} allowClear />
</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,113 @@
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 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';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const types = {
1: '年度',
2: "季度",
3:'月度'
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '考核对象', key: 'objectName', dataIndex: 'objectName', width: 150},
{
title: '考核频次', key: 'assessFreq', dataIndex: 'assessFreq', width: 140,
render: (value) => <span>{types[value]}</span>,
},
// { title: '考核批次', key: 'assessBatch', dataIndex: 'assessBatch', width: 140},
{
title: '考核周期', key: 'zq', dataIndex: 'zq', width: 230,
render: (_,r) => <span>{r.startDate && r.endDate ? `${r.startDate} - ${r.endDate}` : ''}</span>
},
{ title: '考核分数', key: 'assessScore', dataIndex: 'assessScore', width: 140},
{
title: '创建时间', key: 'createTime', dataIndex: 'createTime', width: 140,
},
{
title: '考核创建人', key: 'createUserName', dataIndex: 'createUserName', width: 140,
},
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={ true }
del={ true }
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.sbwh.zhfxkh.delete + `/${params.id}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.sbwh.zhfxkh.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
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}
onSave={command('save')}
/>
</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}
/>
</div>
</>
);
}
export default Page;

View File

View File

@ -0,0 +1,67 @@
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, role }) => {
const types = [
{
label: "年度",
value: 1
},
{
label: "季度",
value: 2
},{
label: "月度",
value: 3
},
]
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="objectName">
<Input allowClear style={{width:'150px'}}/>
</Form.Item>
<Form.Item label="考核频次" name="assessFreq">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item>
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
{
(onSave) ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
:null
}
</Form>
</div>
</>
);
}
export default ToolBar;

View File

@ -158,12 +158,17 @@ const Page = () => {
<div style={{ width: '45%' }}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width, y: "calc( 100vh - 400px )" }} />
</div>
<div style={{ width: '55%',height:570}} >
<div style={{ width: '55%', height: 570 }} >
{
historyList.length > 0 ?
<ReactEcharts
option={pxOptions || {}}
style={{ width: "100%", height: '100%' }}
notMerge={true}
/>
/> :
<div style={{textAlign: "center", margin: "10%"}}><img src={`${process.env.PUBLIC_URL}/assets/noData.png`} alt=""/></div>
}
</div>
</div>
</div>

View File

@ -3,6 +3,8 @@
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)))
const type = data[0]?.type
const unit = type == 0 ? 'm³/s' : type == 3 ? 'mm' : 'm'
return {
tooltip: {
trigger: "axis",
@ -40,7 +42,7 @@ export default function options(data = []) {
},
axisLabel: {
color: "#7a869a",
formatter: '{value} m³/s'
formatter: `{value} ${unit}`
},
axisTick: {
show: false

View File

@ -10,8 +10,8 @@ const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const types = {
0: "闸后流量",
1: '闸前水位',
2:'闸后水位'
2: '闸前水位',
3:'闸后水位'
}
const types1 = {
0: "报警中",
@ -21,34 +21,34 @@ const Page = () => {
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{
title: '监测项目', key: 'name', dataIndex: 'name', width: 150,
title: '监测项目', key: 'type', dataIndex: 'type', width: 150,
render: (v) => <span>{types[v]}</span>
},
{ title: '监测值', key: 'adress', dataIndex: 'adress', width: 150},
{ title: '阈值下限', key: 'adress', dataIndex: 'adress', width: 150},
{ title: '阈值上限', key: 'adress', dataIndex: 'adress', width: 150},
{ title: '监测值', key: 'val', dataIndex: 'val', width: 150},
{ title: '阈值下限', key: 'lowerLimit', dataIndex: 'lowerLimit', width: 150},
{ title: '阈值上限', key: 'upperLimit', dataIndex: 'upperLimit', width: 150},
{
title: '状态', key: 'adress', dataIndex: 'adress', width: 150,
title: '状态', key: 'status', dataIndex: 'status', width: 150,
render: (v) => <span>{types[v]}</span>
},
{
title: '报警时间', key: 'eventsDate', dataIndex: 'eventsDate', width: 140,
title: '报警时间', key: 'warnTime', dataIndex: 'warnTime', width: 140,
},
{
title: '持续时长', key: 'eventsDate', dataIndex: 'eventsDate', width: 140,
title: '持续时长', key: 'duration', dataIndex: 'duration', width: 140,
},
];
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.bjgl.bjjl.page).find_noCode);
const exportExcel = () => {
let params = {
...searchVal,
}
httppost5(apiurl.pxjh.export, params).then(res => {
exportFile(`统计报表.xlsx`,res.data)
httppost5(apiurl.jcsj.bjgl.bjjl.export, params).then(res => {
exportFile(`报警记录.xlsx`,res.data)
})
}
useEffect(() => {

View File

@ -13,11 +13,11 @@ const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
},
{
label: "闸前水位",
value: 1,
value: 2,
},
{
label: "闸后水位",
value: 2,
value: 3,
},
]
@ -34,15 +34,15 @@ const ToolBar = ({ setSearchVal, onSave, storeData, exportFile1 }) => {
const [form] = Form.useForm();
const onFinish = (values) => {
let dateSo;
let dateTimeRangeSo ;
if (values.tm) {
dateSo = {
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, dateSo});
setSearchVal({...values, dateTimeRangeSo});
}

View File

@ -7,6 +7,7 @@ import apiurl from '../../../../service/apiurl';
import usePageTable from '../../../../components/crud/usePageTable2';
import { createCrudService } from '../../../../components/crud/_';
import {CrudOpRender_text} from '../../../../components/crud/CrudOpRender';
import { httppost2 } from '../../../../utils/request';
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
@ -29,7 +30,7 @@ const Page = () => {
{ title: '阈值上限', key: 'lowerLimit ', dataIndex: 'lowerLimit', width: 150},
{
title: '是否启用', key: 'status', dataIndex: 'status', width: 150,
render: (v) => <span>{ v == 1 ? '停用': '启用'}</span>
render: (v) => <span>{ v == 1 ? '否': v==0?'是':''}</span>
},
{
title: '配置时间', key: 'createTime', dataIndex: 'createTime', width: 150,
@ -51,6 +52,17 @@ const Page = () => {
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const stopStatus = async (params) => {
try {
const res = await httppost2(apiurl.jcsj.bjgl.bjgzpz.stop, params)
if (res.code == 200) {
message.success(`${params.status ? '停用':'启用'}成功`)
refresh()
}
} catch (error) {
console.log(error);
}
}
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
@ -60,6 +72,8 @@ const Page = () => {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDeleteGet(apiurl.jcsj.bjgl.bjgzpz.delete + `/${params.id}`);
} else if (type == 'status') {
stopStatus({ id: params.id, status: params.status == 1 ? 0 : params.status == 0 ? 1 : ''})
}
}