123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- import React, { useEffect, useState, useRef, useMemo, memo } from 'react';
- import {
- Modal,
- Input,
- Select,
- List,
- Row,
- Col,
- Table,
- message,
- Steps,
- Space,
- Button,
- Popover,
- Cascader,
- AutoComplete,
- } from 'antd';
- import Flow from '@/components/Flow/index';
- import { connect } from 'dva';
- import { GetTokenFromUrl, getToken } from '@/utils/utils';
- import { MODELS, useXFlowApp, useModelAsync } from '@antv/xflow';
- import { CheckOutlined } from '@ant-design/icons';
- import {
- queryDelPurchaseExcel,
- queryDingInstanceDetail,
- queryRecordSheet,
- queryVserionByNode,
- } from '@/services/boom';
- import { async } from '@antv/x6/lib/registry/marker/async';
- import VersionModal from './VersionModal';
- import AuditFlow from './AuditFlow';
- const { Option } = Select;
- const { Step } = Steps;
- const { TextArea } = Input;
- const localData = JSON.parse(localStorage.ggDetaiData || '{}');
- const PAGE_SIZE = 8;
- // 提交
- function FlowModal(props) {
- let token = getToken();
- const SELECT_TYPE = {
- NAME: '0',
- TYPE: '1',
- CREATOR: '2',
- };
- const {
- visible,
- version,
- onClose,
- onChangeVersion,
- onDelVersion,
- form,
- loading,
- flowDetail,
- dispatch,
- isOut,
- onCommit,
- commitLoading,
- currentUser,
- typeOptions,
- userList,
- } = props;
- const [data, setData] = useState([]);
- const [showData, setShowData] = useState([]);
- const [nodeLoading, setNodeLoading] = useState(false);
- const [pageSize, setPageSize] = useState(PAGE_SIZE);
- const [stepsData, setStepsData] = useState([]);
- const [versionVisible, setVersionVisible] = useState(false);
- const [selectType, setSelectType] = useState(SELECT_TYPE.NAME);
- const [inputValue, setInputValue] = useState('');
- const graphData = useMemo(() => {
- if (!flowDetail) return;
- let nodes = flowDetail.nodes?.map(item => ({
- ...item,
- isCheck: item.Id == version.template_node_id,
- }));
- return {
- nodes,
- edges: flowDetail.edges,
- };
- }, [flowDetail, version.template_node_id]);
- useEffect(() => {
- if (!visible) updateSteps([]);
- }, [visible, version]);
- useEffect(() => {
- if (stepsData.length <= 0) {
- setPageSize(PAGE_SIZE);
- } else {
- setPageSize(PAGE_SIZE - stepsData.length);
- }
- }, [stepsData]);
- const handleSelectNode = async args => {
- let res;
- const id = args.nodeId || args.nodeIds[0];
- if (!id) return;
- let node = graphData.nodes.find(item => item.id == id);
- setNodeLoading(true);
- try {
- res = await queryVserionByNode({ template_node_id: node.Id });
- let data = [];
- if (!res.data.excel_version_tree) setData([]);
- res.data.excel_version_tree?.map(arr => {
- if (res.data.flow_id) {
- data = [...data, { ...arr, flow_id: res.data.flow_id }];
- } else {
- data = [...data, arr];
- }
- });
- data.sort((a, b) => b.id - a.id);
- data.forEach((item, id) => {
- //解决key报错问题
- data[id].key = `${id}-${item.name}`;
- item.isParent = true;
- });
- console.log(data);
- setData(data);
- } catch (error) {
- console.log(error);
- }
- setNodeLoading(false);
- updateSteps([]);
- };
- const updateSteps = (data, curNodeId) => {
- let newData = [];
- let set = new Set();
- data.forEach(item => set.add(item.template_node_id));
- let list = [...set];
- if (set.has(curNodeId)) {
- set.delete(curNodeId);
- list = [curNodeId, ...set];
- }
- let dataList = list.map(template_node_id => {
- let itemDataList = data.filter(item => item.template_node_id == template_node_id);
- let curid = 3;
- let status = 'process';
- itemDataList.forEach(item => {
- if (item.audit_status != 3 && item.node_id <= curid) curid = item.node_id - 1;
- if (item.audit_status == 2) status = 'error';
- });
- let curNode = flowDetail.nodes.find(item => item.Id == itemDataList[0].template_node_id);
- const seqList = itemDataList[0].FlowInfo.FlowNodes.filter(
- item => item.template_node_id == template_node_id
- ).sort((a, b) => a.seq - b.seq);
- let obj = {
- status,
- current: curid,
- list: seqList,
- name: curNode?.label || itemDataList[0].FlowInfo.name,
- };
- // itemDataList.forEach((itemData, idx) => {
- // if (idx >= obj.list.length) return;
- // obj.list[idx].auditor = itemData.AuthorInfo.CName;
- // });
- return obj;
- });
- setStepsData(dataList);
- };
- // const updateSteps = async (data, curNodeId) => {
- // const dataList = [];
- // for (let i = 0; i < data.length; i++) {
- // let curNode = flowDetail.nodes.find(item => item.Id == data[i].template_node_id);
- // console.log(curNode);
- // const response = await queryDingInstanceDetail({
- // process_instance_id: data[i].ding_instance_id, //创建表单成功返回的id
- // });
- // if (response) {
- // const processInstance = response.data?.process_instance;
- // let data = {
- // processCode: '',
- // deptId: '14169890',
- // tasks: [],
- // // userId: '16569001414345099',
- // // deptId: currentUser.DingDepId || getCurrentUser()?.DingDepId,
- // userId: currentUser.DingUserId || getCurrentUser()?.DingUserId,
- // formComponentValues: [],
- // activityId: '',
- // cc_userids: [],
- // status: 'undefined',
- // name: curNode?.label || '未知节点',
- // };
- // if (processInstance?.tasks && processInstance.tasks?.length > 0) {
- // // let item = flowDetail.nodes.find(item => item.Id == version.template_node_id);
- // // if (!item) return data;
- // const { tasks, form_component_values, cc_userids } = processInstance;
- // data.processCode = curNode.process_code;
- // data.activityId = tasks[tasks.length - 1]?.activity_id;
- // data.tasks = tasks || [];
- // data.cc_userids = cc_userids;
- // data.formComponentValues = form_component_values?.filter(curNode => curNode.name);
- // }
- // dataList.push(data);
- // }
- // }
- // console.log(dataList);
- // setStepsData(dataList);
- // };
- const handleChangeClick = item => {
- let file = isOut ? 'newList' : 'detail';
- let type = item.flow_id ? '/queryAuditRecord' : '/queryAuditExcel';
- console.log(`${file}${type}`, item);
- dispatch({
- type: `${file}${type}`,
- payload: {
- excel_id: item.id,
- pageSize: 100,
- },
- callback: res => {
- updateSteps(res, item.template_node_id);
- },
- });
- };
- const columns = useMemo(() => {
- return [
- {
- title: '名称',
- width: '25%',
- render: item => (
- <span style={{ color: item.audit_status != 0 ? '#9b9b9b' : '' }}>
- {item.id == version.id && !item.isParent && (
- <CheckOutlined style={{ marginRight: 10 }} />
- )}
- {item.version_no && !item.children?.length
- ? `${item.version_name}.${item.version_no}`
- : item.version_name}
- </span>
- ),
- },
- {
- title: '创建人',
- width: '15%',
- render: item => {
- return (
- item.isParent && (
- <span>{userList.find(cur => cur.ID == item.author)?.CName || '-'}</span>
- )
- );
- },
- },
- {
- title: '分类',
- width: '15%',
- render: item => {
- return (
- item.isParent && (
- <span>{typeOptions.find(cur => cur.id == item.classify_id)?.name}</span>
- )
- );
- },
- },
- {
- title: '状态',
- width: '15%',
- render: item => {
- if (!item.flow_id && item.isParent) return;
- let style = { color: getColor(item) };
- let txt = '';
- let dom = '';
- switch (item.audit_status) {
- case 0:
- txt = '未提交';
- break;
- case 1:
- txt = '待审批';
- break;
- case 2:
- txt = '已拒绝';
- break;
- case 3:
- txt = '已通过';
- break;
- case 4:
- txt = '已提交';
- break;
- }
- if (item.status == 1) txt = '已失效';
- // 显示拒绝原因
- if (item.audit_comment) {
- dom = (
- <Popover content={item.audit_comment} title="原因">
- {txt}
- </Popover>
- );
- } else {
- dom = txt;
- }
- return item.audit_status != 0 ? (
- <Button onClick={() => onDelVersion(item)}>{dom}</Button>
- ) : (
- <span style={style}>{dom}</span>
- );
- },
- },
- {
- title: '操作',
- width: '20%',
- render: item =>
- (item.flow_id || !item.isParent) &&
- item.id != version.id && (
- <Space>
- <a
- onClick={() => {
- console.log(item);
- onChangeVersion(item);
- onClose();
- }}
- >
- 加载
- </a>
- {item.audit_status == 0 &&
- item.author == currentUser.ID && ( //自己创建的&&未提交的清单自己可以删除
- <a
- onClick={() => {
- onDelVersion({ excel_id: item.id });
- }}
- >
- 删除
- </a>
- )}
- </Space>
- ),
- },
- ];
- }, [version]);
- const childColumns = useMemo(() => {
- return [
- {
- title: '名称',
- width: '50%',
- render: item => (
- <span style={{ color: item.audit_status != 0 ? '#9b9b9b' : '' }}>
- {item.id == version.id && !item.isParent && (
- <CheckOutlined style={{ marginRight: 10 }} />
- )}
- {item.version_no && !item.children?.length
- ? `${item.version_name}.${item.version_no}`
- : item.version_name}
- </span>
- ),
- },
- {
- title: '状态',
- render: item => {
- if (!item.flow_id && item.isParent) return;
- let style = { color: getColor(item) };
- let txt = '';
- let dom = '';
- switch (item.audit_status) {
- case 0:
- txt = '未提交';
- break;
- case 1:
- txt = '待审批';
- break;
- case 2:
- txt = '已拒绝';
- break;
- case 3:
- txt = '已通过';
- break;
- case 4:
- txt = '已提交';
- break;
- }
- if (item.status == 1) txt = '已失效';
- // 显示拒绝原因
- if (item.audit_comment) {
- dom = (
- <Popover content={item.audit_comment} title="原因">
- {txt}
- </Popover>
- );
- } else {
- dom = txt;
- }
- return item.audit_status != 0 ? (
- <Button onClick={() => onDelVersion(item)}>{dom}</Button>
- ) : (
- <span style={style}>{dom}</span>
- );
- },
- },
- {
- title: '操作',
- width: '30%',
- render: item =>
- (item.flow_id || !item.isParent) &&
- item.id != version.id && (
- <Space>
- <a
- onClick={() => {
- console.log(item);
- onChangeVersion(item);
- onClose();
- }}
- >
- 加载
- </a>
- {item.audit_status == 0 &&
- item.author == currentUser.ID && ( //自己创建的&&未提交的清单自己可以删除
- <a
- onClick={() => {
- onDelVersion({ excel_id: item.id });
- }}
- >
- 删除
- </a>
- )}
- </Space>
- ),
- },
- ];
- }, [version]);
- const onChange = value => {
- updateSteps([]);
- };
- useEffect(() => {
- if (!inputValue) {
- setShowData(data);
- return;
- }
- let resultData = [...data];
- switch (selectType) {
- case SELECT_TYPE.NAME:
- resultData = data.filter(item => item.version_name.includes(inputValue));
- break;
- case SELECT_TYPE.TYPE:
- const classify = typeOptions.find(item => item.name.includes(inputValue));
- if (classify) {
- resultData = data.filter(item => item.classify_id == classify.id);
- }
- break;
- case SELECT_TYPE.CREATOR:
- resultData = data.filter(item => item.AuthorInfo?.CName.includes(inputValue));
- break;
- }
- setShowData(resultData);
- }, [inputValue, data]);
- return (
- <>
- <Modal
- confirmLoading={loading}
- destroyOnClose
- title="流程图"
- visible={visible}
- onCancel={onClose}
- footer={false}
- width="98%"
- >
- <Row gutter={8}>
- <Col span={14}>
- <Flow meta={{ type: 'view' }} flowDetail={graphData} onSelectNode={handleSelectNode} />
- </Col>
- <Col span={10}>
- <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
- <div style={{ fontSize: '16px' }}>清单列表</div>
- {isOut && (
- <Button
- type="primary"
- style={{ float: 'right', marginBottom: '10px' }}
- onClick={() => setVersionVisible(true)}
- >
- 新建清单
- </Button>
- )}
- </div>
- <div style={{ display: 'flex' }}>
- <Select
- defaultValue={selectType}
- style={{ width: '30%' }}
- onChange={value => {
- setSelectType(value);
- setInputValue('');
- }}
- >
- <Option value={SELECT_TYPE.NAME}>名称:</Option>
- <Option value={SELECT_TYPE.TYPE}>分类:</Option>
- <Option value={SELECT_TYPE.CREATOR}>创建人:</Option>
- </Select>
- <Input
- placeholder="请输入"
- value={inputValue}
- onChange={e => setInputValue(e.target.value)}
- />
- <Button type="primary" style={{ marginLeft: '10px' }}>
- 搜索
- </Button>
- </div>
- <div style={{ width: '100%', marginTop: '10px' }}>
- <Table
- style={{ maxHeight: '80%' }}
- columns={columns}
- dataSource={showData} //data
- loading={nodeLoading}
- bordered={false}
- pagination={{ position: ['none', 'none'], pageSize: 999, onChange }}
- scroll={{ y: 65 * pageSize }}
- // childrenColumnName="none"
- // expandable={{
- // expandedRowRender: record => (
- // <Table
- // columns={columns}
- // dataSource={record.children}
- // pagination={{ position: ['none', 'none'] }}
- // />
- // ),
- // rowExpandable: record => record.children?.length > 0,
- // }}
- />
- </div>
- {stepsData.map((item, idx) => (
- <div key={`${item.name}_${idx}`} style={{ marginBottom: '20px' }}>
- <div style={{ marginBottom: '4px' }}>{item.name}</div>
- <Steps size="small" current={item.current} status={item.status}>
- {item.list.map(node => (
- <Step
- key={`${node.id}_${node.node}`}
- title={node.node}
- description={`审批人:${node.AuditorUser?.CName || '-'}`}
- />
- ))}
- </Steps>
- </div>
- ))}
- </Col>
- </Row>
- </Modal>
- <VersionModal
- typeOptions={typeOptions}
- visible={versionVisible}
- onClose={() => setVersionVisible(false)}
- onOk={values => {
- onCommit?.(values, null, () => {
- setVersionVisible(false);
- });
- }}
- loading={commitLoading}
- />
- </>
- );
- }
- const getColor = item => {
- let color = '';
- switch (item.audit_status) {
- case 2:
- // 审批拒绝
- color = '#f5222d';
- break;
- case 3:
- // 审批成功
- color = '#7cb305';
- break;
- case 4:
- // 历史清单
- color = '#9b9b9b';
- break;
- default:
- break;
- }
- return color;
- };
- export default connect(({ loading, user }) => ({
- loading,
- currentUser: user.currentUser,
- userList: user.list,
- }))(FlowModal);
- // export default FlowModal;
|