From 945d241bcf549a2c272477748c86095bf0878e74 Mon Sep 17 00:00:00 2001 From: zhangyongtian <1181606322@qq.com> Date: Sat, 07 Sep 2024 16:54:29 +0800 Subject: [PATCH] feat: 对接事件流转 --- gz-customerSystem/src/components/ProgressStep/VisitStep.jsx | 173 ++++----- gz-customerSystem/src/views/register/eventFlow/component/AssignedModel.jsx | 110 +++++- gz-customerSystem/src/views/register/matterDetail/index.jsx | 15 gz-customerSystem/src/views/register/eventFlow/component/BackModel.jsx | 77 ++++ gz-customerSystem/src/components/SelectObjModal/selectPerson.jsx | 153 ++++---- gz-customerSystem/src/views/register/eventFlow/component/EventFlow.jsx | 162 +++++---- gz-customerSystem/src/views/register/eventFlow/index.jsx | 117 +++++- gz-customerSystem/src/components/ProgressStep/index.less | 31 + gz-customerSystem/src/views/register/eventFlow/component/EscalationModel.jsx | 68 +++ gz-customerSystem/src/router/router.js | 2 10 files changed, 590 insertions(+), 318 deletions(-) diff --git a/gz-customerSystem/src/components/ProgressStep/VisitStep.jsx b/gz-customerSystem/src/components/ProgressStep/VisitStep.jsx index 7a40a68..14e906f 100644 --- a/gz-customerSystem/src/components/ProgressStep/VisitStep.jsx +++ b/gz-customerSystem/src/components/ProgressStep/VisitStep.jsx @@ -7,117 +7,100 @@ * @Description: 来访登记步骤条 */ -import React, { useEffect, useState } from 'react'; -import { Tooltip, Space } from 'antd'; -import Icon, { PaperClipOutlined, RollbackOutlined, EllipsisOutlined } from '@ant-design/icons'; +import React, { Fragment, useEffect, useState } from 'react'; +import { Tooltip } from 'antd'; import { ledger_8, ledger_7, ledger_12, ledger_13 } from '../../assets/images'; -import NameCard from '../NameCard'; import * as $$ from '../../utils/utility'; -import FilesDrawer from '../FilesDrawer'; import './index.less'; /** - * progressData:'', // 流程数据 + * progressData: { + * assistCaseFlowList: [],//配合部门流程数组 + * handleCaseFlowList: [],//承办部门流程数组 + * }, // 流程数据 + * hasTab: false,//是否有部门切换 */ -const ProgressStep = ({ progressData }) => { +const ProgressStep = ({ progressData, hasTab }) => { + const [proType, setProType] = useState('handleCaseFlowList') const iconMap = { - 1: ledger_8, - 2: ledger_7, - 3: ledger_12, - 4: ledger_13 + 1: ledger_7,//完成 + 2: ledger_12,//回退 + 3: ledger_13//上报 } + const btnList = [ + { + value: 'handleCaseFlowList', + label: '承办部门' + }, + { + value: 'assistCaseFlowList', + label: '配合部门' + }, + ] - // 已处理列表第一个元素 - const dom1 = (x) => ( - <div> - <div className="myStep-item-p"> - <span>{x.handlerUserName || '-'}</span> - </div> - <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> - <span>操作人:</span> - <span>{x.operationName}</span> - </div> - <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> - <span>经办时间:</span> - <span>{$$.timeFormat(x.finishTime)}</span> - </div> - </div> - ); - // 已处理列表后面 元素 - const dom2 = (x) => ( - <div> - <div className="myStep-item-p"> - <span>{x.handlerUserName || '-'}</span> - </div> - {x.operationName && - <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> - <span>操作人:</span> - <span>{x.operationName}</span> - </div> - } - <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> - <span>操作时间:</span> - <span>{$$.timeFormat(x.finishTime)}</span> - </div> - { - x.handleContent && - <div className='myStep-item-p-yy' style={{ width: '200px' }}> - <span className='myStep-item-p-yy-l'> - {x.handleResult == '2' ? - <span>退回<Tooltip placement="top" title={x.handleContent || ''}><span>{`(${x.handleContent})` || '-'}</span></Tooltip></span> - : x.taskNode == 'F22_00019-3' && x.handleResult == '1' ? - // 22_00025-1:调解成功,22_00025-2:调解不成功 - <span>调解结果:<Tooltip placement="top" title={x.mediResult == '22_00025-1' ? '调解成功' : x.mediResult == '22_00025-2' ? '调解不成功' : '-'}><span>{`${x.mediResult == '22_00025-1' ? '调解成功' : x.mediResult == '22_00025-2' ? '调解不成功' : '-'}` || '-'}</span></Tooltip></span> - : <Tooltip placement="top" title={x.handleContent || ''}><span>{x.handleContent || '-'}</span></Tooltip>} - </span> - { - x.fileInfoList?.length > 0 && - <div style={{ marginTop: '4px' }}> - <FilesDrawer name={<> - <PaperClipOutlined style={{ marginRight: '4px' }} /> - <span>{x.taskNode == 'F22_00019-3' && x.handleResult == '1' ? '调解协议书' : '处理附件'}</span> - </>} filesData={x.fileInfoList} title="经办附件" /> - </div> - } - </div> - } - </div> - ); - - // 办理中 - const dom3 = (x) => ( - <div> - <div className="myStep-item-p"> - <span style={{ color: 'rgba(0,0,0,0.50)' }}>待受理</span> - </div> - <div className="myStep-item-p"> - <span>{x.handlerUserName}</span> - </div> - </div> - ); + useEffect(() => { + setProType('handleCaseFlowList') + }, [progressData]) return ( - <> - {progressData.length !== 0 - ? progressData.map((x, t) => { + <Fragment> + {hasTab && + <div className='tabBtn'> + {btnList.map((item, index) => { + return <div + className={`tabBtn-btn ${proType === item.value ? 'tabBtn-active' : ''}`} + key={item.value} + onClick={() => { setProType(item.value) }} + style={{ marginRight: (index + 1) !== btnList.length ? '20px' : '0' }} + >{item.label}</div> + })} + + </div> + } + {progressData[proType] && progressData[proType].length !== 0 + ? progressData[proType].map((x, t) => { return ( <div key={t + 1}> <div className="myStep-item"> - {t === progressData.length - 1 ? null : <div className={`${!x.handleContent ? 'myStep-item-divider' : x.fileInfoList?.length > 0 ? 'myStep-item-divider2' : "myStep-item-divider1"} ${x.status === '2' && 'myStep-item-divider-success'}`} />} - <div className={`myStep-item-icon1 myStep-item-${x.status === '1' ? 'noStarted1' : 'success1'}`}> - <div className="myStep-item-title">{x.taskNodeName}</div> - <img className='myStep-item-img' src={iconMap[x.status]} alt="" /> + {t === progressData[proType].length - 1 ? null : <div className={`${!x.handleContent ? 'myStep-item-divider' : x.fileInfoList?.length > 0 ? 'myStep-item-divider2' : "myStep-item-divider1"} ${x.status === '2' && 'myStep-item-divider-success'}`} />} + <div className={`myStep-item-icon1 myStep-item-${x.status === 1 ? 'noStarted1' : 'success1'}`}> + <div className="myStep-item-title">{x.nodeShowName || '事件流转'}</div> + <img className='myStep-item-img' src={x.status === 1 ? ledger_8 : iconMap[x.taskType]} alt="" /> </div> <div className="myStep-item-right"> - { - t === 0 && dom1(x || {}) - } - { - t !== 0 && <> - { - x.status === '1' ? dom3(x || {}) : dom2(x || {}) + {t === progressData[proType].length - 1 ? + <div> + <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> + {x.processName} + </div> + <div className="myStep-item-p"> + <span>{x.handleUnitName || '-'}</span> + </div> + </div> + : + <div> + <div className="myStep-item-p"> + <span>{x.handleUnitName || '-'}</span> + </div> + {x.handleUserName && + <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> + <span>操作人:</span> + <span>{x.handleUserName}</span> + </div> } - </> + <div className="myStep-item-p" style={{ color: 'rgba(0,0,0,0.50)' }}> + <span>操作时间:</span> + <span>{$$.timeFormat(x.handleTime)}</span> + </div> + { + x.handleNotes && + <div className='myStep-item-p-yy' style={{ width: '200px' }}> + <span className='myStep-item-p-yy-l'> + <span><Tooltip placement="top" title={x.handleNotes || ''}><span>{x.handleNotes || '-'}</span></Tooltip></span> + </span> + </div> + } + </div> } </div> </div> @@ -125,7 +108,7 @@ ); }) : <div style={{ padding: '100px 0' }}>{$$.MyEmpty()}</div>} - </> + </Fragment> ); }; diff --git a/gz-customerSystem/src/components/ProgressStep/index.less b/gz-customerSystem/src/components/ProgressStep/index.less index e37d54a..e574fab 100644 --- a/gz-customerSystem/src/components/ProgressStep/index.less +++ b/gz-customerSystem/src/components/ProgressStep/index.less @@ -12,6 +12,7 @@ border-color: #bfbfbf; } } + &-success1 { background-color: @main-color; @@ -29,10 +30,10 @@ } &-noStarted1 { - background-color: rgba(185,99,211,1); + background-color: rgba(185, 99, 211, 1); &::after { - border-color: rgba(185,99,211,1); + border-color: rgba(185, 99, 211, 1); } } @@ -117,7 +118,7 @@ } } - &-divider2 { + &-divider2 { position: absolute; top: 0; left: 24px; @@ -158,18 +159,21 @@ margin-top: 4px; display: flex; align-items: flex-start; + &-flex { display: flex; flex-direction: column; justify-content: center; align-items: center; margin-top: 8px; + &-title { font-size: 12px; line-height: 20px; color: @text-color-secondary; } } + &-yy { display: flex; flex-direction: column; @@ -178,6 +182,7 @@ border-radius: 5px; padding: 4px 8px; color: rgba(0, 0, 0, 0.5); + &-l { overflow: hidden; white-space: nowrap; @@ -197,3 +202,23 @@ } } } + +.tabBtn { + display: flex; + margin-bottom: 12px; + + &-btn { + height: 32px; + background: #ffffff; + border: 1px solid #e5e6eb; + border-radius: 4px; + color: #e5e6eb; + padding: 4px 8px; + cursor: pointer; + } + + &-active { + color: #1a6fb8; + border-color: #1a6fb8; + } +} \ No newline at end of file diff --git a/gz-customerSystem/src/components/SelectObjModal/selectPerson.jsx b/gz-customerSystem/src/components/SelectObjModal/selectPerson.jsx index 4a9c2e0..7f92877 100644 --- a/gz-customerSystem/src/components/SelectObjModal/selectPerson.jsx +++ b/gz-customerSystem/src/components/SelectObjModal/selectPerson.jsx @@ -18,7 +18,20 @@ // 获取人员,组织,部门数据 function getDataApi(type, searchData) { - const url = type === 'person' ? 'ctUser/userChoose' : type === 'unit' ? 'ctUser/unitList' : 'ctUser/deptList'; + let url + switch (type) { + case 'dept': + url = `ctUnit/unitChoose` + break; + case 'person': + url = 'ctUser/userChoose' + break + case 'unit': + url = 'ctUser/unitList' + break + default: + break; + } return $$.ax.request({ url, type: 'get', data: searchData, service: 'cust' }); } @@ -31,36 +44,37 @@ * onClose, // 关闭 * onOk, // 点击确定的回调 */ -const SelectObjModal = ({ visible = false, checkKeys = [], type = 'person', isCheckbox = false, searchData = {}, onClose, onOk, }) => { +const SelectObjModal = ({ visible = false, checkKeys = [], type = 'dept', isCheckbox = false, searchData = {}, onClose, onOk, }) => { + const nameStr = type === 'person' ? '人员' : type === 'unit' ? '组织' : '部门'; + // 默认调解员查询'22_00024-4' + const searchRole = type === 'person' ? { roleCode: '22_00024-4' } : {}; const [data, setData] = useState([]); - const [checkedKeys, setCheckedKeys] = useState({ keys: [], items: [] }); - const [expandedKeys, setExpandedKeys] = useState([]); - const [searchValue, setSearchValue] = useState(''); - const [autoExpandParent, setAutoExpandParent] = useState(true); - const [dataList, setDataList] = useState([]); - // tree复选框选择 - function handleCheck(checkedKeys, e) { - if (!isCheckbox && checkedKeys.checked.length > 1) { - $$.info({ type: 'warning', content: '当前选择只可单选' }); - return; + useEffect(() => { + if (!visible) return; + // 获取数据 + async function getData() { + // global.setSpinning(true); + const res = await getDataApi(type, { ...searchRole, ...searchData }); + // global.setSpinning(false); + if (res.type) { + setData(res.data || []); + } } - let checkedNodes = e.checkedNodes; - checkedNodes.forEach((x) => delete x.children); - setCheckedKeys({ keys: checkedKeys.checked, items: checkedNodes }); - } - - // 删除选项 - function handleDelete(t) { - checkedKeys.keys.splice(t, 1); - checkedKeys.items.splice(t, 1); - setCheckedKeys({ ...checkedKeys }); - } + if (checkKeys.length !== 0) { + let keys = []; + checkKeys.forEach((x) => keys.push(x.value)); + setCheckedKeys({ keys, items: checkKeys }); + } else { + setCheckedKeys({ keys: [], items: [] }); + } + getData(); + }, [type, visible]); // 搜索 useEffect(() => { @@ -80,35 +94,6 @@ setDataList(arr); handleSearch('', arr); }, [data]); - - const getParentKey = (key, tree) => { - let parentKey; - for (let i = 0; i < tree.length; i++) { - const node = tree[i]; - if (node.children) { - if (node.children.some((item) => item.value === key)) { - parentKey = node.value; - } else if (getParentKey(key, node.children)) { - parentKey = getParentKey(key, node.children); - } - } - } - return parentKey; - }; - - function handleSearch(value, dataList) { - const newExpandedKeys = dataList - .map((item) => { - if (item.label.indexOf(value) > -1) { - return getParentKey(item.value, data); - } - return null; - }) - .filter((item, i, self) => item && self.indexOf(item) === i); - setExpandedKeys(newExpandedKeys); - setSearchValue(value); - setAutoExpandParent(true); - } const treeData = useMemo(() => { const loop = (data) => @@ -146,32 +131,52 @@ return loop(data); }, [searchValue, data]); - // 默认调解员查询'22_00024-4' - const searchRole = type === 'person' ? { roleCode: '22_00024-4' } : {}; + // tree复选框选择 + function handleCheck(checkedKeys, e) { + if (!isCheckbox && checkedKeys.checked.length > 1) { + $$.info({ type: 'warning', content: '当前选择只可单选' }); + return; + } + let checkedNodes = e.checkedNodes; + checkedNodes.forEach((x) => delete x.children); + setCheckedKeys({ keys: checkedKeys.checked, items: checkedNodes }); + } - console.log(checkedKeys.keys,'checkedKeys.keyscheckedKeys.keys') - useEffect(() => { - if (!visible) return; - // 获取数据 - async function getData() { - global.setSpinning(true); - const res = await getDataApi(type, { ...searchRole, ...searchData }); - global.setSpinning(false); - if (res.type) { - setData(res.data || []); + // 删除选项 + function handleDelete(t) { + checkedKeys.keys.splice(t, 1); + checkedKeys.items.splice(t, 1); + setCheckedKeys({ ...checkedKeys }); + } + + const getParentKey = (key, tree) => { + let parentKey; + for (let i = 0; i < tree.length; i++) { + const node = tree[i]; + if (node.children) { + if (node.children.some((item) => item.value === key)) { + parentKey = node.value; + } else if (getParentKey(key, node.children)) { + parentKey = getParentKey(key, node.children); + } } } - if (checkKeys.length !== 0) { - let keys = []; - checkKeys.forEach((x) => keys.push(x.value)); - setCheckedKeys({ keys, items: checkKeys }); - } else { - setCheckedKeys({ keys: [], items: [] }); - } - getData(); - }, [type, visible]); + return parentKey; + }; - const nameStr = type === 'person' ? '人员' : type === 'unit' ? '组织' : '部门'; + function handleSearch(value, dataList) { + const newExpandedKeys = dataList + .map((item) => { + if (item.label.indexOf(value) > -1) { + return getParentKey(item.value, data); + } + return null; + }) + .filter((item, i, self) => item && self.indexOf(item) === i); + setExpandedKeys(newExpandedKeys); + setSearchValue(value); + setAutoExpandParent(true); + } return ( <Modal diff --git a/gz-customerSystem/src/router/router.js b/gz-customerSystem/src/router/router.js index c6d277a..c341bbf 100644 --- a/gz-customerSystem/src/router/router.js +++ b/gz-customerSystem/src/router/router.js @@ -217,7 +217,7 @@ <Route path="judicialOverview" element={<JudicialOverview />} /> {/* 来访登记*/} <Route path="visit/:id?" element={<Visit />} /> - <Route path="visit/eventFlow" element={<EventFlow />} /> + <Route path="visit/eventFlow/:caseTaskId?/:caseId?" element={<EventFlow />} /> <Route path="visit/handleFeedback" element={<HandleFeedback />} /> <Route path="visit/fileMessage" element={<FileMessage />} /> <Route path="visit/closingReview" element={<ClosingReview />}/> diff --git a/gz-customerSystem/src/views/register/eventFlow/component/AssignedModel.jsx b/gz-customerSystem/src/views/register/eventFlow/component/AssignedModel.jsx index caf18e2..fbcbc7c 100644 --- a/gz-customerSystem/src/views/register/eventFlow/component/AssignedModel.jsx +++ b/gz-customerSystem/src/views/register/eventFlow/component/AssignedModel.jsx @@ -1,37 +1,84 @@ -import React, { useRef, useState } from 'react' +import React, { useRef, useState, useEffect } from 'react' import { Row, Col } from 'antd'; import { Form, Input, Button, Select } from '@arco-design/web-react'; import ArcoUpload from '@/components/ArcoUpload'; import { Scrollbars } from "react-custom-scrollbars"; import SelectObjModal from '@/components/SelectObjModal/selectPerson'; +import { useParams } from 'react-router-dom'; +import * as $$ from '@/utils/utility'; const FormItem = Form.Item; const TextArea = Input.TextArea; -const Option = Select.Option; -const options = ['Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Chengdu', 'Wuhan']; +const appUrl = $$.appUrl; + +function assign(data) { + return $$.ax.request({ url: `caseTask/assign`, type: 'post', service: 'mediate', data }); +} + +function delFile(id) { + return $$.ax.request({ url: `fileInfo/deleteFileById`, type: 'get', service: 'sys', data: { id } }); +} export default function BackModel(props) { + const routeData = useParams(); const formRef = useRef(); const [isModalVisible, setIsModalVisible] = useState(false); const [wantUser, setWantUser] = useState({}); + const [mainDept, setMainDept] = useState('handleUnit');//判断打开弹窗的是承办部门还是配合部门 + const [selectOptions, setSelectOptions] = useState({});//两个部门选择的options + + useEffect(() => { + }, []) + const handleSubmit = () => { formRef.current.validate(undefined, (errors, values) => { - console.log(errors, values); + if (!errors) { + handleAssign({ + caseTaskId: routeData.caseTaskId, + assignContent: values.assignContent, + handleUnitId: wantUser['handleUnit'][0].value, + handleUnitName: wantUser['handleUnit'][0].name, + assistUnitList: wantUser['assistUnit'] && wantUser['assistUnit'].map(item => { + return { + uitId: item.value, + uitName: item.name + } + }) + }) + } }) } const handleTemplate = (type) => { if (type === 1) { - formRef.current.setFieldValue('trueName', '本事项经初步核实,认为属于贵部门职责范围内的矛盾纠纷化解工作。请组织专门人员负责此事,尽快查明事实真相,依法依规进行处理,并在处理过程中充分考虑当事人的合理诉求,确保公平公正,维护当事人的合法权益。同时,请务必保持与当事人的沟通畅通,及时反馈办理进展,以增强矛盾纠纷化解工作的透明度和公信力。') + formRef.current.setFieldValue('assignContent', '本事项经初步核实,认为属于贵部门职责范围内的矛盾纠纷化解工作。请组织专门人员负责此事,尽快查明事实真相,依法依规进行处理,并在处理过程中充分考虑当事人的合理诉求,确保公平公正,维护当事人的合法权益。同时,请务必保持与当事人的沟通畅通,及时反馈办理进展,以增强矛盾纠纷化解工作的透明度和公信力。') } else { - formRef.current.setFieldValue('trueName', '') + formRef.current.setFieldValue('assignContent', '') } } - const handleFocus = (e) => { - e.stopPropagation() - setIsModalVisible(true) + //交办请求 + const handleAssign = async (data) => { + const res = await assign(data) + if (res.type) { + $$.infoSuccess({ content: '交办成功!' }); + props.onCancel() + } + } + + //删除文件 + const handleDelFile = async (id) => { + const res = await delFile(id) + if (res.type) { + $$.infoSuccess({ content: '删除成功!' }); + } + } + + //form数据同步要提交的数据 + const handleSync = (field, value) => { + wantUser[field] = wantUser[field].filter(item => value.indexOf(item.value) != -1) + setWantUser(wantUser); } return ( @@ -49,13 +96,20 @@ <Col span={24}> <FormItem label={(<div style={{ display: 'flex' }}>承办部门<div className="must">必填</div></div>)} - field='bumen' + field='handleUnit' + rules={[{ required: true, message: '请选择承办部门' }]} > <Select mode='multiple' placeholder='请选择承办部门' allowClear - onFocus={handleFocus} + onFocus={(e) => { + e.stopPropagation() + setIsModalVisible(true) + setMainDept('handleUnit') + }} + options={selectOptions['handleUnit']} + onChange={(v) => { handleSync('handleUnit', v) }} > </Select> </FormItem> @@ -63,18 +117,20 @@ <Col span={24}> <FormItem label={(<div style={{ display: 'flex' }}>配合部门<div style={{ color: '#86909C' }}>(可多选)</div></div>)} - field='peihe' + field='assistUnit' > <Select mode='multiple' placeholder='请选择配合部门' allowClear + onFocus={(e) => { + e.stopPropagation() + setIsModalVisible(true) + setMainDept('assistUnit') + }} + options={selectOptions['assistUnit']} + onChange={(v) => { handleSync('assistUnit', v) }} > - {options.map((option) => ( - <Option key={option} value={option}> - {option} - </Option> - ))} </Select> </FormItem> </Col> @@ -85,7 +141,7 @@ </div> <FormItem label={(<div style={{ display: 'flex' }}>交办意见<div className="must">必填</div></div>)} - field='trueName' + field='assignContent' rules={[{ required: true, message: '请选择回退理由' }]} > <TextArea @@ -98,10 +154,11 @@ <Col span={24} className="doubleFile"> <ArcoUpload params={{ - action: ``, + action: `${appUrl.fileUrl}/${appUrl.sys}/api/web/fileInfo/upload?mainId=${props.caseId}&ownerId=${routeData.caseTaskId}&ownerType=22_00018-501`, }} field='file' label='附件材料' + handleDelFile={handleDelFile} /> </Col> </Row> @@ -118,12 +175,23 @@ </div> <SelectObjModal visible={isModalVisible} - checkKeys={wantUser.wantUserId ? [{ label: wantUser.wantUserName, value: wantUser.wantUserId }] : undefined} + checkKeys={wantUser[mainDept]} onOk={(value) => { + console.log(value); setIsModalVisible(false); - setWantUser({ wantUserId: value.keys[0], wantUserName: value.items[0].name }); + wantUser[mainDept] = value.items + setWantUser(wantUser); + selectOptions[mainDept] = value.items.map(item => ({ + label: item.name, + value: item.value + })) + setSelectOptions(selectOptions) + formRef.current.setFieldValue(mainDept, value.items.map(item => item.value)) + }} onClose={() => setIsModalVisible(false)} + type='dept' + isCheckbox={mainDept === 'handleUnit' ? false : true} /> </div> ) diff --git a/gz-customerSystem/src/views/register/eventFlow/component/BackModel.jsx b/gz-customerSystem/src/views/register/eventFlow/component/BackModel.jsx index a353b0c..a7e9b0e 100644 --- a/gz-customerSystem/src/views/register/eventFlow/component/BackModel.jsx +++ b/gz-customerSystem/src/views/register/eventFlow/component/BackModel.jsx @@ -1,15 +1,30 @@ -import React, { useRef } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { Row, Col } from 'antd'; import { Form, Input, Button, Radio } from '@arco-design/web-react'; import ArcoUpload from '@/components/ArcoUpload'; import { Scrollbars } from "react-custom-scrollbars"; +import * as $$ from '@/utils/utility'; const RadioGroup = Radio.Group; const FormItem = Form.Item; const TextArea = Input.TextArea; +const appUrl = $$.appUrl; + +function getId() { + return $$.ax.request({ url: `caseUtils/getNewTimeId`, type: 'get', service: 'utils' }); +} + +function delFile(id) { + return $$.ax.request({ url: `fileInfo/deleteFileById`, type: 'get', service: 'sys', data: { id } }); +} + +function returnApply(data) { + return $$.ax.request({ url: `caseTask/returnApply`, type: 'post', service: 'mediate', data }); +} export default function BackModel(props) { const formRef = useRef(); + const [id, setId] = useState(); const options = [ { label: '不属于本部门的职能范围', @@ -32,9 +47,50 @@ value: 5 }, ] - const handleSubmit = () => { + useEffect(() => { + getAppId() + }, []) + + //获取id + const getAppId = async () => { + const res = await getId() + if (res.type) { + setId(res.data) + } } + + const handleSubmit = () => { + if (formRef.current) { + formRef.current.validate(undefined, (errors, values) => { + if (!errors) { + handleReturn({ + id, + caseId: props.caseId, + returnContent: values.returnContent + }) + } + }) + } + } + + //删除文件 + const handleDelFile = async (id) => { + const res = await delFile(id) + if (res.type) { + $$.infoSuccess({ content: '删除成功!' }); + } + } + + //回退请求 + const handleReturn = async (data) => { + const res = await returnApply(data) + if (res.type) { + $$.infoSuccess({ content: '提交申请成功!' }); + props.onCancel() + } + } + return ( <div> <Scrollbars style={{ height: '550px' }} autoHide> @@ -50,17 +106,23 @@ <Col span={24}> <FormItem label={(<div style={{ display: 'flex' }}>回退理由<div className="must">必填</div></div>)} - field='trueName' + field='backType' rules={[{ required: true, message: '请选择回退理由' }]} > - <RadioGroup direction='vertical' options={options}> - </RadioGroup> + <RadioGroup + direction='vertical' + options={options} + onChange={(value) => { + const obj = options.find(item => item.value === value) + formRef.current.setFieldValue('returnContent', obj.label) + }} + /> </FormItem> </Col> <Col span={24}> <FormItem label=' ' - field='luyou' + field='returnContent' rules={[{ required: true, message: '回退理由不能为空' }]} > <TextArea @@ -72,10 +134,11 @@ <Col span={24} className="doubleFile"> <ArcoUpload params={{ - action: ``, + action: `${appUrl.fileUrl}/${appUrl.sys}/api/web/fileInfo/upload?mainId=${props.caseId}&ownerId=${id}&ownerType=22_00018-520`, }} field='file' label='附件材料' + handleDelFile={handleDelFile} /> </Col> </Row> diff --git a/gz-customerSystem/src/views/register/eventFlow/component/EscalationModel.jsx b/gz-customerSystem/src/views/register/eventFlow/component/EscalationModel.jsx index 6ccf1a5..9db6691 100644 --- a/gz-customerSystem/src/views/register/eventFlow/component/EscalationModel.jsx +++ b/gz-customerSystem/src/views/register/eventFlow/component/EscalationModel.jsx @@ -1,27 +1,81 @@ -import React, { useRef } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { Row, Col } from 'antd'; import { Form, Input, Button } from '@arco-design/web-react'; import ArcoUpload from '@/components/ArcoUpload'; import { Scrollbars } from "react-custom-scrollbars"; import { escalation } from '@/assets/images/icon'; +import * as $$ from '@/utils/utility'; const FormItem = Form.Item; const TextArea = Input.TextArea; +const appUrl = $$.appUrl; + +function getId() { + return $$.ax.request({ url: `caseUtils/getNewTimeId`, type: 'get', service: 'utils' }); +} + +function delFile(id) { + return $$.ax.request({ url: `fileInfo/deleteFileById`, type: 'get', service: 'sys', data: { id } }); +} + +function appearApply(data) { + return $$.ax.request({ url: `caseTask/appearApply`, type: 'post', service: 'mediate', data }); +} export default function BackModel(props) { const formRef = useRef(); + const [id, setId] = useState() + + useEffect(() => { + getAppId() + }, []) + + //获取id + const getAppId = async () => { + const res = await getId() + if (res.type) { + setId(res.data) + } + } const handleSubmit = () => { formRef.current.validate(undefined, (errors, values) => { - console.log(errors, values); + if (formRef.current) { + formRef.current.validate(undefined, (errors, values) => { + if (!errors) { + handleEscala({ + id, + caseId: props.caseId, + returnContent: values.returnContent + }) + } + }) + } }) } const handleTemplate = (type) => { if(type === 1) { - formRef.current.setFieldValue('trueName', '经初步核查,该事项较为复杂,且涉及多个相关部门的协调配合,为确保能够高效、妥善地解决当事人的问题,特此请求上级给予指导和支持。') + formRef.current.setFieldValue('returnContent', '经初步核查,该事项较为复杂,且涉及多个相关部门的协调配合,为确保能够高效、妥善地解决当事人的问题,特此请求上级给予指导和支持。') } else { - formRef.current.setFieldValue('trueName', '') + formRef.current.setFieldValue('returnContent', '') + } + } + + //上报请求 + const handleEscala = async (data) => { + const res = await appearApply(data) + if (res.type) { + $$.infoSuccess({ content: '提交申请成功!' }); + props.onCancel() + } + } + + //删除文件 + const handleDelFile = async (id) => { + const res = await delFile(id) + if (res.type) { + $$.infoSuccess({ content: '删除成功!' }); } } @@ -54,10 +108,9 @@ </div> <FormItem label={(<div style={{ display: 'flex' }}>上报意见<div className="must">必填</div></div>)} - field='trueName' + field='returnContent' rules={[{ required: true, message: '请选择回退理由' }]} > - <TextArea autoSize={{ minRows: 4, maxRows: 8 }} placeholder='请填写回退的具体理由' @@ -68,10 +121,11 @@ <Col span={24} className="doubleFile"> <ArcoUpload params={{ - action: ``, + action: `${appUrl.fileUrl}/${appUrl.sys}/api/web/fileInfo/upload?mainId=${props.caseId}&ownerId=${id}&ownerType=22_00018-512`, }} field='file' label='附件材料' + handleDelFile={handleDelFile} /> </Col> </Row> diff --git a/gz-customerSystem/src/views/register/eventFlow/component/EventFlow.jsx b/gz-customerSystem/src/views/register/eventFlow/component/EventFlow.jsx index 318fd38..252ab71 100644 --- a/gz-customerSystem/src/views/register/eventFlow/component/EventFlow.jsx +++ b/gz-customerSystem/src/views/register/eventFlow/component/EventFlow.jsx @@ -9,82 +9,86 @@ import AssignedModel from './AssignedModel'; import MatterDetail from '../../matterDetail'; import SupervisingView from "../../matterDetail/Supervising"; +import * as $$ from '@/utils/utility'; const TabPane = Tabs.TabPane; const Step = Steps.Step; -const fakeData = [ - { - handlerUserName: '天河区棠下街综治中心', - finishTime: new Date().getTime() - 24 * 60 * 60 * 1000, // 一天前的时间 - handleResult: '1', - status: '2', - taskNodeName: '来访登记', - mediResult: '22_00025-1', - handleContent: '调解成功,双方达成一致意见。', - operationName: '李晓明' - }, - { - handlerUserName: '系统派单', - finishTime: new Date().getTime() - 12 * 60 * 60 * 1000, // 半天前的时间 - handleResult: '1', - status: '2', - taskNodeName: '事件流转', - mediResult: '22_00025-1', - handleContent: '派单至:白云区新市街市场监管所', - }, - { - handlerUserName: '白云区新市街市场监管所', - finishTime: new Date().getTime() - 11 * 60 * 60 * 1000, // 半天前的时间 - handleResult: '1', - status: '2', - taskNodeName: '事件流转', - mediResult: '22_00025-1', - handleContent: '已签收', - operationName: '赵菲菲' - }, - { - handlerUserName: '白云区新市街市场监管所', - finishTime: new Date().getTime() - 10 * 60 * 60 * 1000, // 半天前的时间 - handleResult: '1', - status: '3', - taskNodeName: '事件回退', - mediResult: '22_00025-1', - // handleContent: '已签收', - operationName: '赵菲菲' - }, - { - handlerUserName: '白云区新市街综治中心', - finishTime: new Date().getTime() - 9 * 60 * 60 * 1000, // 半天前的时间 - handleResult: '1', - status: '2', - taskNodeName: '回退审核', - mediResult: '22_00025-1', - handleContent: '通过', - operationName: '赵菲菲' - }, - { - handlerUserName: '天河区棠下街综治中心', - finishTime: new Date().getTime() - 6 * 60 * 60 * 1000, // 6小时前的时间 - handleResult: '2', - status: '1', - taskNodeName: '事件流转', - mediResult: '22_00025-1', - handleContent: '案件已被签收,准备开始调解。', - operationName: '李晓明' - }, -]; +function getListCaseFlow(data) { + return $$.ax.request({ url: `caseTask/listCaseFlow`, type: 'get', service: 'mediate', data }); +} export default function EventFlow(props) { + const myButton = [ + { + label: '受理', + type: 'primary', + click: () => { }, + key: 'sl', + }, + { + label: '提交', + type: 'primary', + click: () => { }, + key: 'tj', + }, + { + label: '自行受理', + type: 'primary', + click: () => { }, + key: 'zxsl', + }, + { + label: '回退', + type: 'outline', + click: () => setBackVisible(true), + key: 'ht', + status: 'danger' + }, + { + label: '交办', + type: 'outline', + click: () => setAssignedVisible(true), + key: 'jb', + }, + { + label: '上报', + type: 'outline', + click: () => setEscalationVisible(true), + key: 'sb', + }, + ] const scrollRef = useRef(null) const [backVisible, setBackVisible] = useState(false) const [height, setHeight] = useState(500) const [escalationVisible, setEscalationVisible] = useState(false) const [assignedVisible, setAssignedVisible] = useState(false) + const [staticButtonList, setStaticButtonList] = useState([]) + const [progressData, setProgressData] = useState({}) useEffect(() => { + if (props.authorData) { + const { buttonList } = props.authorData; + setStaticButtonList(myButton.filter(item => { + const flag = buttonList.some(result => { + if (result.id === item.key) { + return true + } + }) + return flag + })) + } + }, [props.authorData]) + + useEffect(() => { + getData() onWindowResize() window.addEventListener("resize", onWindowResize); + // 返回一个函数,该函数会在组件卸载前执行 + return () => { + // 组件销毁时执行 + window.removeEventListener("resize", onWindowResize); + }; }, []) const onWindowResize = () => { @@ -96,6 +100,16 @@ } setHeight(getSize().windowH - offsetTop - 16) }; + + //获取流程信息 + const getData = async () => { + const res = await getListCaseFlow({ + caseId: props.caseId + }) + if(res.type) { + setProgressData(res.data) + } + } return ( <Fragment> @@ -116,7 +130,7 @@ ref={scrollRef} autoHide > - <MatterDetail /> + <MatterDetail caseId={props.caseId}/> <div className='dataSync-hasTabPage' style={{ marginTop: '-8px' }}> <Tabs defaultActiveTab='1' > <TabPane @@ -127,7 +141,7 @@ </span> } > - <ProgressStep progressData={fakeData} /> + <ProgressStep progressData={progressData} /> </TabPane> <TabPane key='2' @@ -150,26 +164,22 @@ visible={backVisible} onOk={() => setBackVisible(false)} onCancel={() => { setBackVisible(false) }} - autoFocus={false} - focusLock={true} footer={null} unmountOnExit={true} maskClosable={false} > - <BackModel /> + <BackModel caseId={props.caseId} onCancel={() => { setBackVisible(false) }}/> </Modal> <Modal title='上报' visible={escalationVisible} onOk={() => setEscalationVisible(false)} onCancel={() => { setEscalationVisible(false) }} - autoFocus={false} - focusLock={true} footer={null} unmountOnExit={true} maskClosable={false} > - <EscalationModel /> + <EscalationModel caseId={props.caseId} onCancel={() => { setEscalationVisible(false) }}/> </Modal> <Modal title='交办' @@ -179,17 +189,17 @@ footer={null} unmountOnExit={true} maskClosable={false} + autoFocus={false} + focusLock={false} > - <AssignedModel /> + <AssignedModel caseId={props.caseId} onCancel={() => { setAssignedVisible(false) }}/> </Modal> <div className="dataSync-excel"> <Space size="large" style={{ margin: '4px 14px' }}> - <Button type="primary" >受理</Button> - <Button type="primary" >提交</Button> - <Button type="primary" >自行受理</Button> - <Button type='outline' status='danger' onClick={() => setBackVisible(true)}>回退</Button> - <Button type='outline' onClick={() => setAssignedVisible(true)}>交办</Button> - <Button type='outline' onClick={() => setEscalationVisible(true)}>上报</Button> + {staticButtonList?.map(item => { + const { label, key, click, ...rest } = item; + return <Button key={key} onClick={click} {...rest} >{label}</Button> + })} <Button type='secondary' >返回上级页面</Button> </Space> </div> diff --git a/gz-customerSystem/src/views/register/eventFlow/index.jsx b/gz-customerSystem/src/views/register/eventFlow/index.jsx index 2606507..c6453a2 100644 --- a/gz-customerSystem/src/views/register/eventFlow/index.jsx +++ b/gz-customerSystem/src/views/register/eventFlow/index.jsx @@ -7,7 +7,7 @@ * @Description: 来访登记 */ -import React, { useState, useRef, Fragment } from "react"; +import React, { useState, useRef, Fragment, useEffect } from "react"; import NewPage from '@/components/NewPage'; import * as $$ from '@/utils/utility'; import "@arco-themes/react-gzzz/css/arco.css"; @@ -17,33 +17,100 @@ import EventFlow from './component/EventFlow'; import Examine from "./component/Examine"; import ApplyInfo from "../matterDetail/ApplyInfo"; +import { useParams } from 'react-router-dom'; const Step = Steps.Step; const TabPane = Tabs.TabPane; +function getTabButton(data) { + return $$.ax.request({ url: `caseTask/getTabButton`, type: 'get', service: 'mediate', data }); +} +const myTab = [ + { + img: Matter, + label: '详情', + key: 'dslxq', + }, + { + img: Matter, + label: '事项详情', + key: 'sxxq', + }, + { + img: applyRecord, + label: '申请记录', + key: 'sqjl', + }, + { + img: examine, + label: '回退审核', + key: 'htsh', + }, + { + img: examine, + label: '上报审核', + key: 'sbsh', + }, + { + img: examine, + label: '结案审核', + key: 'jash', + }, + { + img: examine, + label: '联合处置申请审核', + key: 'lhczsh', + }, +] const Organization = () => { - const [current, setCurrent] = useState(2); - const [tabsActive, setTabsActive] = useState('1'); - const [tabsList, setTabList] = useState([ - { - img: Matter, - label: '详情', - key: '1' - }, - { - img: applyRecord, - label: '申请记录', - key: '2', - }, - { - img: examine, - label: '审核', - key: '3', - }, - ]) - const [disTab, setDisTab] = useState(true) + const routeData = useParams(); + const [authorData, setAuthorData] = useState({}); + const [tabsList, setTabsList] = useState([]); + const [tabsActive, setTabsActive] = useState(); + const [disTab, setDisTab] = useState(true); + useEffect(() => { + getAuthor() + }, []) + + //获取权限tab和按钮权限 + const getAuthor = async () => { + const res = await getTabButton({ + caseTaskId: routeData.caseTaskId + }) + if (res.type) { + const { tabList } = res.data + setAuthorData(res.data) + if (tabList.length === 0) { + //没有tab就不展示 + setDisTab(false) + } else { + setTabsList(myTab.filter(item => { + const flag = tabList.some(result => { + if (result.id === item.key) { + return true + } + }) + return flag + })) + setTabsActive(tabList[0].id) + } + } + } + + //根据id定义组件 + const getTypeDom = (key) => { + if (key === 'dslxq' || key === 'sxxq') { + return <EventFlow authorData={authorData} caseId={routeData.caseId} /> + } + if (key === 'sqjl') { + return <ApplyInfo /> + } + if (key === 'htsh' || key === 'sbsh' || key === 'jash' || key === 'lhczsh') { + return <Examine type={key} /> + } + } return ( <div style={{ position: 'relative' }}> @@ -53,9 +120,9 @@ } > {disTab ? <Tabs - defaultActiveTab='1' onChange={(v) => setTabsActive(v)} className='myTabContent' + activeTab={tabsActive} > {tabsList?.map(item => { return <TabPane @@ -67,12 +134,10 @@ </span> } > - {tabsActive === '1' && <EventFlow />} - {tabsActive === '2' && <ApplyInfo />} - {tabsActive === '3' && <Examine />} + {getTypeDom(item.key)} </TabPane> })} - </Tabs> : <EventFlow /> + </Tabs> : <EventFlow authorData={authorData} /> } </NewPage> </div> diff --git a/gz-customerSystem/src/views/register/matterDetail/index.jsx b/gz-customerSystem/src/views/register/matterDetail/index.jsx index e607ee9..a058c98 100644 --- a/gz-customerSystem/src/views/register/matterDetail/index.jsx +++ b/gz-customerSystem/src/views/register/matterDetail/index.jsx @@ -143,11 +143,15 @@ // 更多数据... ]; - + + useEffect(() => { + console.log(props); + getCaseInfo(props.caseId) + }, [props.caseId]) //获取id - const getCaseInfo = async () => { - const res = await getCaseInfoApi('24083010062110001') + const getCaseInfo = async (id) => { + const res = await getCaseInfoApi(id) if (res.type) { let data = res.data @@ -160,11 +164,6 @@ } } - - - // useEffect(() => { - // getCaseInfo() - // }, []) return ( <div style={{ position: 'relative' }}> -- Gitblit v1.8.0