tsg-web/src/views/rcgl/byfz/bypc/precessForm.js

741 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import React, { useEffect, useState, useMemo, useRef } from 'react';
import { Form, Button, Input, Row, Upload, Col, Table, TreeSelect, DatePicker, InputNumber, message, Image, Radio, Modal, Descriptions, Tabs, Tooltip } from 'antd';
import { VideoCameraOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import BasicCrudModal from '../../../../components/crud/BasicCrudModal';
import { CrudOpRender_text } from '../../../../components/crud/CrudOpRender';
import apiurl from '../../../../service/apiurl';
import FormComponent from "./formCom"
import NormalSelect from '../../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
import { httpget2, xyt_httpget2, httppost2 } from '../../../../utils/request';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9100/gs-tsg"
const ModalForm = ({ mode, record, refresh, setPrecessVisible }) => {
const taskTypes = [
{ label: "日常巡查", value: 1 },
{ label: "特别检查", value: 2 },
{ label: "汛前巡检", value: 3 },
]
const xjStatus = {
0: "cha",
1: "gou"
}
const [form] = Form.useForm();
const [form1] = Form.useForm();
const [precessType, setPrecessType] = useState()
const [itemList, setItemList] = useState([])
const [itemParams, setItemParams] = useState([])
const [list, setList] = useState([])
const [totals, setTotals] = useState({})
const [tabsRender, setTabsRender] = useState([])
const [imgVisible, setImgVisible] = useState(false)
const [imgList, setImgList] = useState([])
const [videoOpen, setVideoOpen] = useState(false)
const [videoParams, setVideoParams] = 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 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>
{value === null ? '' :
<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 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 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.inspectTask = values.isWarn == 2 ? {
startDate: values.startDate || '',
endDate: values.endDate || '',
inspectUserName: deptUserList?.find(item => item.userId == values.inspectUserId)?.nickName,
items: itemParams,
inspectUserId: values?.inspectUserId,
taskContent: values?.taskContent,
taskTitle: values?.taskTitle,
taskType: values?.taskType,
createUserId: userId,
createUserName: userName
} : null
if (mode === 'save') {
onSave(apiurl.rcgl.byfz.bypc.process, values)
}
}
const onSave = async (url, params) => {
const newParams = { ...params, order: record?.order, obDate: record?.obDate }
try {
const { code, data } = await httppost2(url, newParams);
if (code == 200) {
message.success('处理成功')
setPrecessVisible(false)
refresh();
}
} catch (error) {
console.log(error);
}
}
const onValuesChange = (v, r) => {
setPrecessType(r.isWarn)
}
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 [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()
getItemList()
}, [])
const handleFile = (arr = []) => {
const newArr = arr?.map(item => ({
name: item.fileName,
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(() => {
if (mode != 'save' && record.jcskByRProcessVo) {
const backParmas = {
...record.jcskByRProcessVo,
isWarn: 2,
}
form.setFieldsValue(backParmas)
setPrecessType(2)
getTabsDetail(record?.jcskByRProcessVo?.id)
}
}, [mode, record])
useEffect(() => {
if (record && mode == 'save') {
const title = record?.obDate ? record?.obDate + '白蚁处理' : ""
const content = (record?.order && record?.obDate)? record?.order + '白蚁监测点于' + record?.obDate + '监测到白蚁入侵,请尽快排查处理':""
const initalObj = {
"hours": 24,
"taskType": 2,
"taskTitle":title,
"taskContent":content,
"startDate": moment(),
"endDate":moment().add(7,'day')
}
for (let key in initalObj) {
form.setFieldValue(key,initalObj[key])
}
}
}, [record,mode])
return (
<div>
{mode == 'view' &&
<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}
onValuesChange={onValuesChange}
>
<Row>
<Col span={24}>
<Form.Item
label="单点报警取消"
name="isWarn"
labelCol={{ span: 4 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<Radio.Group disabled={mode === 'view'} >
<Radio value={1}>误报并取消报警</Radio>
<Radio value={2}>取消报警并创建工单</Radio>
</Radio.Group>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="单点位报警重复豁免时长(h)"
name="hours"
rules={[
{
required: true,
},
]}
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
>
<InputNumber disabled={mode === 'view'} min={0} style={{ width: '30%' }} allowClear />
</Form.Item>
</Col>
</Row>
{precessType == 2 ?
<Row>
<Col span={12}>
<Form.Item
label="任务类型"
name="taskType"
rules={[
{
required: true,
},
]}
>
<NormalSelect
disabled={mode === 'view'}
style={{ width: '100%' }}
allowClear
options={taskTypes}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="任务标题"
name="taskTitle"
rules={[
{
required: true,
},
]}
>
<Input
disabled={mode === 'view'}
style={{ width: '100%' }}
allowClear
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
label="选择巡查人"
name="inspectUserId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[
{
required: true,
},
]}
>
<TreeSelect
disabled={mode === 'view'}
showSearch
style={{
width: '100%',
}}
dropdownStyle={{
maxHeight: 400,
overflow: 'auto',
}}
allowClear
treeDefaultExpandAll
treeData={treeList}
treeNodeFilterProp='title'
/>
</Form.Item>
</Col>
{
mode != 'view' &&
<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>
}
<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>
<Col span={12}>
<Form.Item
label="开始日期"
name="startDate"
rules={[
{
required: true,
},
]}
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"
rules={[
{
required: true,
},
]}
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> : null
}
{(mode == 'view') &&
<>
<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?.jcskByRProcessVo?.status == 2 ?
<span style={{ marginLeft: "auto", marginRight: 30 }}>(异常项<span style={{ color: "red" }}>{totals?.isNormalTotal}</span>{totals?.normalTotal})</span>
: null
}
</div>
{
record?.jcskByRProcessVo?.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%" }}
/>
}
</>
}
{
mode === 'view' ? null : (
<>
<Form.Item wrapperCol={{ span: 3, offset: 21 }} style={{ marginTop: "4%" }}>
<Button type="primary" htmlType="submit" >
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</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={form1}
{...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.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="handleDesc"
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;