Эх сурвалжийг харах

Squashed commit of the following:
merge devlop_0715
commit 6c38bc02e3ad84491745076a2f5abf2241bbd06f
Author: Renxy <18510891294@163.com>
Date: Fri Jul 22 15:57:38 2022 +0800

修改地址

commit d06b6ae6af266634f7f742559402069e4296d585
Author: Renxy <18510891294@163.com>
Date: Fri Jul 22 15:56:03 2022 +0800

修改查看流程/历史版本

commit 9fdd0969977a5a10205684cb66d4d27b8fcb5a39
Author: Renxy <18510891294@163.com>
Date: Wed Jul 20 20:18:38 2022 +0800

多节点审批/业务节点权限控制

commit b7c21ca5d7abd551ef8913defacd2b834f53a5d3
Author: Renxy <18510891294@163.com>
Date: Fri Jul 15 16:44:49 2022 +0800

添加业务节点权限配置

Renxy 2 жил өмнө
parent
commit
66bd343da7

+ 4 - 4
public/luckysheet.html

@@ -7,20 +7,20 @@
     <title>Document</title>
 
    <!-- 线上发布使用路径 -->
-   <!-- <link rel="stylesheet" href="/bom/Luckysheet/plugins/css/pluginsCss.css" />
+   <link rel="stylesheet" href="/bom/Luckysheet/plugins/css/pluginsCss.css" />
    <link rel="stylesheet" href="/bom/Luckysheet/plugins/plugins.css" />
    <link rel="stylesheet" href="/bom/Luckysheet/css/luckysheet.css" />
    <link rel="stylesheet" href="/bom/Luckysheet/assets/iconfont/iconfont.css" />
    <script src="/bom/Luckysheet/plugins/js/plugin.js"></script>
-   <script src="/bom/Luckysheet/luckysheet.umd.js"></script> -->
+   <script src="/bom/Luckysheet/luckysheet.umd.js"></script>
 
    <!-- 本地开发使用路径 -->
-   <link rel='stylesheet' href='http://localhost:3000/plugins/css/pluginsCss.css' />
+   <!-- <link rel='stylesheet' href='http://localhost:3000/plugins/css/pluginsCss.css' />
    <link rel='stylesheet' href='http://localhost:3000/plugins/plugins.css' />
    <link rel='stylesheet' href='http://localhost:3000/css/luckysheet.css' />
    <link rel='stylesheet' href='http://localhost:3000/assets/iconfont/iconfont.css' />
    <script src="http://localhost:3000/plugins/js/plugin.js"></script>
-   <script src="http://localhost:3000/luckysheet.umd.js"></script>
+   <script src="http://localhost:3000/luckysheet.umd.js"></script> -->
   </head>
   <body>
     <div

+ 1 - 0
src/components/Flow/config-toolbar.ts

@@ -235,6 +235,7 @@ namespace NSToolbarConfig {
                 };
               });
               console.log(data);
+              console.log(JSON.stringify(data));
               localStorage.graphData = JSON.stringify(data);
               return null;
             },

+ 1 - 1
src/components/Flow/node/fields/radio.tsx

@@ -29,7 +29,7 @@ const SelectField: React.FC<IProps> = props => {
         }}
       >
         {options.map(item => (
-          <Radio value={item.value}>{item.label}</Radio>
+          <Radio key={`${item.value}-${item.label}`} value={item.value}>{item.label}</Radio>
         ))}
       </Radio.Group>
     </div>

+ 33 - 3
src/components/Flow/node/rect/mapServe.tsx

@@ -1,6 +1,6 @@
 import React, { useState, useEffect } from 'react';
 import { FlowchartFormWrapper } from '@antv/xflow';
-import { Button, message } from 'antd';
+import { Button, message, Select } from 'antd';
 import LuckyExcel from 'luckyexcel';
 import {
   Position,
@@ -13,6 +13,7 @@ import {
 } from '../fields';
 import { PREFIX } from '../constants';
 import { UnityAction } from '@/utils/utils';
+import { connect } from 'dva';
 
 export interface IConfig {
   label?: string;
@@ -31,6 +32,7 @@ export interface IConfig {
   version_name?: string;
   data?: any;
   excel_info?: any;
+  role_list?:string;
 }
 
 const defaultConfig: IConfig = {
@@ -39,8 +41,9 @@ const defaultConfig: IConfig = {
 };
 
 const Component = (props: any) => {
-  const { config, plugin = {} } = props;
+  const { config, plugin = {}, roleList } = props;
   const { updateNode } = plugin;
+  const [options, setOptions] = useState([])
   const [nodeConfig, setNodeConfig] = useState<IConfig>({
     ...defaultConfig,
     ...config,
@@ -113,6 +116,17 @@ const Component = (props: any) => {
   }, [config]);
   // console.log(nodeConfig, config)
 
+  useEffect(() => {
+    if(!roleList || roleList.length <= 0) return;
+    let op = []
+    console.log(roleList)
+    roleList.filter(cur=>cur.RoleType == 4).forEach(item => {
+      op.push({label:`${item.Name}(${item.ID})`, value:item.ID})
+    })
+    setOptions(op);
+    console.log(op)
+  },[roleList])
+
   return (
     <div className={`${PREFIX}-panel-body`}>
       <div className={`${PREFIX}-panel-group`}>
@@ -166,6 +180,20 @@ const Component = (props: any) => {
             <div>{nodeConfig.excel_info?.file_name}</div>
           </>
         )}
+        <div className='group'>
+          <label>权限</label>
+          <Select
+            value= {nodeConfig.role_list ? nodeConfig.role_list.split(",").map(item=>Number(item)) : []}
+            mode="multiple"
+            allowClear
+            style={{ width: '100%' }}
+            placeholder="选择权限"
+            onChange={(v: number[]) => {
+              onNodeConfigChange('role_list', v.join(','))
+            }}
+            options={options}
+          />
+        </div>
       </div>
       <div className={`${PREFIX}-panel-group`}>
         <h5>样式</h5>
@@ -229,10 +257,12 @@ const Component = (props: any) => {
   );
 };
 
-export default function RecthServe(props: any) {
+function RecthServe(props: any) {
   return (
     <FlowchartFormWrapper {...props}>
       {(config, plugin) => <Component {...props} plugin={plugin} config={config} />}
     </FlowchartFormWrapper>
   );
 }
+
+export default connect(({ flow }) => ({ roleList: flow.roleList }))(RecthServe);

+ 151 - 69
src/pages/PurchaseAdmin/PurchaseList/Detail/CommitAuditModal.js

@@ -1,66 +1,71 @@
 import React, { useEffect, useState, useRef, useMemo } from 'react';
-import { Form } from '@ant-design/compatible';
 import '@ant-design/compatible/assets/index.css';
-import { Modal, Input, Select, message } from 'antd';
+import { Modal, Input, Select, message, Cascader, Form } from 'antd';
 import { connect } from 'dva';
+import { isArray, result } from 'lodash';
+import { useForm } from 'rc-field-form';
+import { async } from '@antv/x6/lib/registry/marker/async';
 
 const { TextArea } = Input;
 const { Option } = Select;
 
 // 提交
 function CommitAuditModal(props) {
-  const { visible, onClose, onOk, form, loading, version, versionList, flowDetail } = props;
+  const { visible, onClose, onOk, loading, version, versionList, flowDetail } = props;
   const [auditId, setAuditId] = useState();
-  const handleOk = () => {
-    form.validateFields((err, fieldsValue) => {
-      if (err) return;
-      let approvalNode = flowDetail.nodes.find?.(item => item.Id == fieldsValue.node_id);
-      let serviceNode = flowDetail.nodes.find?.(
-        item => item.Id == fieldsValue.next_template_node_id
-      );
-      let params = {
-        desc: fieldsValue.desc,
-        // 审核流程id
-        flow_id: approvalNode?.flow_id || 0,
-        node_level_id: approvalNode?.flow_id ? 1 : 0,
-
-        id: version.id,
-        project_id: version.project_id,
-        cur_template_node_id: version.template_node_id * 1, // 当前节点
-        template_node_id: approvalNode?.Id, // 将要流转的节点
-        next_template_node_id: serviceNode.Id * 1, // 审核完成后的业务节点
+  const [data, setData] = useState([])
+  const [length, setLength] = useState(1)
+  const [formData, setFromData] = useState({})
+  const [form] = Form.useForm();
+  useEffect(() => {
+    const { edges, nodes } = flowDetail;
+    let Id = version.template_node_id;
+    const currentId = flowDetail.nodes.find?.(item => item.Id == Id)?.node_id
+    const data = treeData(currentId)
+    if(data.length <= 0) setAuditId(currentId)
+    setData(data)
+  }, [auditId, version.template_node_id])
+  
+  useEffect(()=>{
+    form.resetFields()
+  },[visible])
 
-        // 模板id.一致就行
-        template_id: version.template_id,
-        cur_template_id: version.template_id,
-        next_template_id: version.template_id,
-      };
-      if (approvalNode?.Id) {
-        if (!approvalNode?.flow_id) {
-          message.error('审批节点未绑定审批流程!请联系管理员。');
-          return;
-        }
-      }
+  const treeData = (currentId) => {
+    const list = getNextNodes(currentId,'custom-circle');
+    const fun = (nodes) => {
+      const re = nodes?.forEach((item, idx)=>{
+        const data = getNextNodes(item.Id,'custom-circle');
+        if(data || data.length > 0) list.push(...data);
+        fun(data)
+      })
+    }
+    fun(list)
+    console.log(list)
+    const fun2 = (list) => {
+      const parents = list.filter(item=>list.findIndex(node=>node.Id == item.parentId) == -1)
+      let translator = (parents, children) => {
+        setLength(length+1)
+        parents.forEach((parent) => {
+            children.forEach((current, index) => {
+                if (current.parentId === parent.Id) {
+                    let temp = JSON.parse(JSON.stringify(children))
+                    temp.splice(index, 1)
+                    translator([current], temp)
+                    if(!parent.children.find(item=>item.Id == current.Id))parent.children.push(current)
+                }
+            })
+        })
+      }   
+      translator(parents, list)   
+      return parents
+    } 
+    return fun2(list)
+  }
 
-      // // 判断业务节点是否允许多清单
-      // if (!serviceNode.muti_version) {
-      //   //audit_status=4 表示为清单推进后留存的副本.不计入多清单计算
-      //   let serviceVersion = versionList.find(
-      //     item => item.audit_status != 4 && item.template_node_id == serviceNode.Id
-      //   );
-      //   if (serviceVersion) {
-      //     message.error(
-      //       `流转失败!业务节点【${serviceNode.label}】为单清单节点。已存在清单【${serviceVersion.version_name}】。`
-      //     );
-      //     return;
-      //   }
-      // }
-      setAuditId();
-      onOk(params);
-    });
-  };
   const currentNodeId = useMemo(() => {
     let Id = version.template_node_id;
+    console.log("+++++++++++++++++++++", version)
+    setAuditId(currentNodeId)
     return flowDetail.nodes.find?.(item => item.Id == Id)?.node_id;
   }, [flowDetail, version]);
   /**
@@ -75,13 +80,15 @@ function CommitAuditModal(props) {
     let targetIds = edges
       .filter(edge => edge.source.cell == currentId)
       .map(item => item.target.cell);
+    edges.filter(edge =>  edge.source.cell == currentId)
     let auditNodes = nodes.filter(node => {
       if (type && node.name != type) {
         return false;
       }
       return targetIds.indexOf(node.id) != -1;
     });
-    return auditNodes || [];
+    const result = auditNodes.map(item=>{return { label:item.label, value:item.Id, Id:item.node_id,parentId:currentId, children:[]}})
+    return result || [];
   };
 
   const changeAudit = id => {
@@ -89,6 +96,89 @@ function CommitAuditModal(props) {
     setAuditId(node.node_id);
   };
 
+  const onChange = (value) => {
+    changeAudit(value[value.length-1])
+  };
+
+  const onFinish = async() => {
+    var fieldsValue = await form.validateFields();
+
+    const getFlowPath = (node) => { //[134, 135]
+      let itemData = {}
+      const Function = (curId,index) => {
+        if(!curId) return;
+        let data = {}
+        let approvalNode = flowDetail.nodes.find?.(item => item.Id == curId);
+        data.template_id = version.template_id;
+        data.flow_id = approvalNode?.flow_id || 0;
+        data.node_level_id = approvalNode?.flow_id ? 1 : 0;
+        data.template_node_id = approvalNode?.Id;
+        index++;
+        const res = Function(node[index], index);
+        if(res) {
+          data.flow_path = [res]
+        }
+        return data
+      }
+      itemData = Function(node[0], 0)
+      return itemData
+    }
+    let  result = Object.values(fieldsValue).map(item=> {if(item && Array.isArray(item)) return item}).filter(item=>item)
+    let serviceNode = flowDetail.nodes.find?.(
+      item => item.Id == fieldsValue.next_template_node_id
+    );
+    let params = {
+      desc: fieldsValue.desc,
+      // 审核流程id
+      // flow_id: approvalNode?.flow_id || 0,
+      // node_level_id: approvalNode?.flow_id ? 1 : 0,
+
+      id: version.id,
+      project_id: version.project_id,
+      cur_template_node_id: version.template_node_id * 1, // 当前节点
+      next_template_node_id: serviceNode.Id * 1, // 审核完成后的业务节点
+      // template_node_id: result[0][0], // 将要流转的节点审批节点
+      // flow_path:flow_path, //审批节点数组
+      // 模板id.一致就行
+      template_id: version.template_id,
+      cur_template_id: version.template_id,
+      next_template_id: version.template_id,
+    };
+    if(result.length <= 0){
+      //直接走业务节点
+    }else if(result.length <= 1 && result[0]?.length <= 1){
+      //单个审批节点
+      let approvalNode = flowDetail.nodes.find?.(item => item.Id == result[0][0]);
+      params.flow_id = approvalNode?.flow_id || 0;
+      params.node_level_id = approvalNode?.flow_id ? 1 : 0;
+      params.template_node_id = result[0][0]; // 将要流转的节点审批节点
+    }else{
+      //多节点审批
+      params.template_node_id = result[0][0]; // 将要流转的节点审批节点
+      params.flow_path = result.map(item=>getFlowPath(item));
+    }
+    console.log("flow_path    ",params)
+
+    
+    //   if (approvalNode?.Id) {
+    //     if (!approvalNode?.flow_id) {
+    //       message.error('审批节点未绑定审批流程!请联系管理员。');
+    //       return;
+    //     }
+    //   }
+    
+    // setAuditId();
+    onOk(params);
+  }
+
+  const CascaderNode = (index) => {
+    return(
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label={`审批节点${index+1}`} name={`circle${index}`} key={`circle${index}`}>
+        <Cascader style={{ width: '100%' }}  options={data} onChange={onChange} />
+      </Form.Item>
+    )
+  }
+
   return (
     <Modal
       confirmLoading={loading}
@@ -99,29 +189,21 @@ function CommitAuditModal(props) {
         setAuditId();
         onClose();
       }}
-      onOk={handleOk}
-    >
-      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="审批节点">
-        {form.getFieldDecorator('node_id')(
-          <Select style={{ width: '100%' }} onChange={changeAudit}>
-            {getNextNodes(currentNodeId, 'custom-circle').map(item => (
-              <Option key={item.Id}>{item.label}</Option>
-            ))}
-          </Select>
-        )}
-      </Form.Item>
-      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="业务节点">
-        {form.getFieldDecorator('next_template_node_id')(
+      onOk={onFinish}
+    > 
+    <Form form={form}>
+      {data.map((item, idx)=>  data.length == 1? CascaderNode(''): CascaderNode(idx) )}
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="业务节点" name='next_template_node_id' >
           <Select style={{ width: '100%' }}>
-            {getNextNodes(auditId || currentNodeId, auditId ? 'custom-rect' : '').map(item => (
-              <Option key={item.Id}>{item.label}</Option>
+            {getNextNodes(data.length < 0 ?currentNodeId : auditId,  'custom-rect' ).map(item => (
+              <Option key={item.value}>{item.label}</Option>
             ))}
           </Select>
-        )}
       </Form.Item>
-      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="备注信息">
-        {form.getFieldDecorator('desc')(<Input.TextArea />)}
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="备注信息" name="desc">
+        <Input.TextArea />
       </Form.Item>
+    </Form>
     </Modal>
   );
 }
@@ -129,4 +211,4 @@ function CommitAuditModal(props) {
 export default connect(({ xflow, detail }) => ({
   flowDetail: xflow.flowDetail,
   versionList: detail.versionList,
-}))(Form.create()(CommitAuditModal));
+}))(CommitAuditModal);

+ 143 - 0
src/pages/PurchaseAdmin/PurchaseList/Detail/CommitAuditModalNew.js

@@ -0,0 +1,143 @@
+import React, { useEffect, useState, useRef, useMemo } from 'react';
+import { Form } from '@ant-design/compatible';
+import '@ant-design/compatible/assets/index.css';
+import { Modal, Input, Select, message } from 'antd';
+import { connect } from 'dva';
+
+const { TextArea } = Input;
+const { Option } = Select;
+
+// 提交
+function CommitAuditModal(props) {
+  const { visible, onClose, onOk, form, loading, version, versionList, flowDetail } = props;
+  const [auditId, setAuditId] = useState();
+  const handleOk = () => {
+    form.validateFields((err, fieldsValue) => {
+      console.log("-------",fieldsValue )
+      if (err) return;
+      let approvalNode = flowDetail.nodes.find?.(item => item.Id == fieldsValue.node_id);
+      let serviceNode = flowDetail.nodes.find?.(
+        item => item.Id == fieldsValue.next_template_node_id
+      );
+      let params = {
+        desc: fieldsValue.desc,
+        // 审核流程id
+        flow_id: approvalNode?.flow_id || 0,
+        node_level_id: approvalNode?.flow_id ? 1 : 0,
+
+        id: version.id,
+        project_id: version.project_id,
+        cur_template_node_id: version.template_node_id * 1, // 当前节点
+        template_node_id: approvalNode?.Id, // 将要流转的节点审批节点
+        next_template_node_id: serviceNode.Id * 1, // 审核完成后的业务节点
+
+        // 模板id.一致就行
+        template_id: version.template_id,
+        cur_template_id: version.template_id,
+        next_template_id: version.template_id,
+      };
+      if (approvalNode?.Id) {
+        if (!approvalNode?.flow_id) {
+          message.error('审批节点未绑定审批流程!请联系管理员。');
+          return;
+        }
+      }
+      // // 判断业务节点是否允许多清单
+      // if (!serviceNode.muti_version) {
+      //   //audit_status=4 表示为清单推进后留存的副本.不计入多清单计算
+      //   let serviceVersion = versionList.find(
+      //     item => item.audit_status != 4 && item.template_node_id == serviceNode.Id
+      //   );
+      //   if (serviceVersion) {
+      //     message.error(
+      //       `流转失败!业务节点【${serviceNode.label}】为单清单节点。已存在清单【${serviceVersion.version_name}】。`
+      //     );
+      //     return;
+      //   }
+      // }
+
+
+      setAuditId();
+      // onOk(params);
+    });
+  };
+  const currentNodeId = useMemo(() => {
+    let Id = version.template_node_id;
+    return flowDetail.nodes.find?.(item => item.Id == Id)?.node_id;
+  }, [flowDetail, version]);
+  /**
+   *
+   * @param {*} currentId 当前节点
+   * @param {*} type 下一个节点的类型  custom-circle: 审批节点   custom-rect: 业务节点
+   * @returns
+   */
+  const getNextNodes = (currentId, type) => {
+    const { edges, nodes } = flowDetail;
+    if (!currentId) return [];
+    let targetIds = edges
+      .filter(edge => edge.source.cell == currentId)
+      .map(item => item.target.cell);
+    let auditNodes = nodes.filter(node => {
+      if (type && node.name != type) {
+        return false;
+      }
+      return targetIds.indexOf(node.id) != -1;
+    });
+    return auditNodes || [];
+  };
+
+  const changeAudit = id => {
+    let node = flowDetail.nodes.find?.(item => item.Id == id);
+    setAuditId(node.node_id);
+  };
+
+  return (
+    <Modal
+      confirmLoading={loading}
+      destroyOnClose
+      title="提交流转目标"
+      visible={visible}
+      onCancel={() => {
+        setAuditId();
+        onClose();
+      }}
+      onOk={handleOk}
+    >
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="审批节点">
+        {form.getFieldDecorator('node_id')(
+          <Select style={{ width: '100%' }} onChange={changeAudit}>
+            {getNextNodes(currentNodeId, 'custom-circle').map(item => (
+              <Option key={item.Id}>{item.label}</Option>
+            ))}
+          </Select>
+        )}
+      </Form.Item>
+      {/* <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="审批节点2">
+        {form.getFieldDecorator('nod_id')(
+          <Select style={{ width: '100%' }} onChange={changeAudit}>
+            {getNextNodes(auditId || currentNodeId, 'custom-circle').map(item => (
+              <Option key={item.Id}>{item.label}</Option>
+            ))}
+          </Select>
+        )}
+      </Form.Item> */}
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="业务节点">
+        {form.getFieldDecorator('next_template_node_id')(
+          <Select style={{ width: '100%' }}>
+            {getNextNodes(auditId || currentNodeId, auditId ? 'custom-rect' : '').map(item => (
+              <Option key={item.Id}>{item.label}</Option>
+            ))}
+          </Select>
+        )}
+      </Form.Item>
+      <Form.Item labelCol={{ span: 7 }} wrapperCol={{ span: 15 }} label="备注信息">
+        {form.getFieldDecorator('desc')(<Input.TextArea />)}
+      </Form.Item>
+    </Modal>
+  );
+}
+
+export default connect(({ xflow, detail }) => ({
+  flowDetail: xflow.flowDetail,
+  versionList: detail.versionList,
+}))(Form.create()(CommitAuditModal));

+ 70 - 7
src/pages/PurchaseAdmin/PurchaseList/Detail/FlowModal.js

@@ -1,5 +1,5 @@
 import React, { useEffect, useState, useRef, useMemo } from 'react';
-import { Modal, Input, Select, List, Row, Col, Table } from 'antd';
+import { Modal, Input, Select, List, Row, Col, Table, message, Steps, Space, Button } from 'antd';
 import Flow from '@/components/Flow/index';
 import { connect } from 'dva';
 import { GetTokenFromUrl, getToken } from '@/utils/utils';
@@ -7,15 +7,19 @@ import { MODELS, useXFlowApp, useModelAsync } from '@antv/xflow';
 import { CheckOutlined } from '@ant-design/icons';
 import { queryVserionByNode } from '@/services/boom';
 import { async } from '@antv/x6/lib/registry/marker/async';
+const { Step } = Steps;
 
 const { TextArea } = Input;
 const localData = JSON.parse(localStorage.ggDetaiData || '{}');
 
 // 提交
 function FlowModal(props) {
-  const { visible, version, onClose, onChangeVersion, form, loading, flowDetail } = props;
+  const { visible, version, onClose, onChangeVersion, form, loading, flowDetail, dispatch } = props;
   const [data, setData] = useState([]);
   const [nodeLoading, setNodeLoading] = useState(false);
+  const [pageSize, setPageSize] = useState(9)
+  const [stepsData, setStepsData] = useState([])
+  const [auditvisible, setAuditVisible] = useState(false);
   // const app = useXFlowApp();
   // const appRef = userRef()
 
@@ -30,6 +34,10 @@ function FlowModal(props) {
     };
   }, [flowDetail, version.template_node_id]);
 
+  useEffect(() => {
+    if(!visible) setAuditVisible(false);
+  }, [visible, version])
+
   const handleSelectNode = async args => {
     let res;
     const id = args.nodeId || args.nodeIds[0];
@@ -41,17 +49,53 @@ function FlowModal(props) {
       let data = [];
       Object.values(res.data.excel_version).map(arr => {
         if (res.data.flow_id) {
-          data = [...data, arr[0]];
+          data = [...data, {...arr[0], flow_id:res.data.flow_id}];
+          console.log(data)
         } else {
           data = [...data, ...arr];
         }
       });
+      //解决key报错问题
+      data.forEach((item, id)=>data[id].key=`${id}-${item.name}`)
+      console.log(data.length)
       setData(data);
     } catch (error) {
       console.log(error);
     }
     setNodeLoading(false);
+    setAuditVisible(false);
+  };
+
+  const updateSteps = (data) => {
+    let newData = []
+    data?.forEach(item => {
+      let list = {
+        current: item.audit_status == 0 ? item.audit_status : item.audit_status-1,
+        list:item.FlowInfo.FlowNodes,
+        name:item.FlowInfo.name,
+      }
+      newData.push(list);
+    })
+    setStepsData(newData)
+    setPageSize(pageSize - data.length)
   };
+
+  const handleChangeClick = (item) => {
+    message.success('哈哈哈哈')
+    dispatch({
+      type: 'detail/queryAuditExcel',
+      payload: {
+        excel_id: item.id,
+        // project_id: item.project_id,
+        // template_id:item.template_id,
+        // template_node_id:item.template_node_id,
+      },
+      callback: res => {
+        updateSteps(res);
+      },
+    });
+    setAuditVisible(true)
+  }
   const columns = useMemo(() => {
     return [
       {
@@ -68,7 +112,7 @@ function FlowModal(props) {
         title: '状态',
         width: '33%',
         render: item => {
-          let style = { color: getColor(item) };
+          let style = {  color: getColor(item) };
           let txt = '';
           switch (item.audit_status) {
             case 0:
@@ -87,7 +131,11 @@ function FlowModal(props) {
               txt = '已提交';
               break;
           }
-          return <span style={style}>{txt}</span>;
+          return <Button onClick={()=>handleChangeClick(item)}>{txt}</Button>
+          // (item.audit_status == 1 || item.audit_status == 4) ? 
+          //   <Button onClick={()=>handleChangeClick(item)}>{txt}</Button> :
+          //   <span style={style} >{txt}</span>
+              
         },
       },
       {
@@ -121,8 +169,23 @@ function FlowModal(props) {
         <Col span={18}>
           <Flow meta={{ type: 'view' }} flowDetail={graphData} onSelectNode={handleSelectNode} />
         </Col>
-        <Col span={6}>
-          <Table columns={columns} dataSource={data} loading={nodeLoading} bordered={false} />
+        <Col span={6} >
+          <div style={{width:'100%'}}>
+            <Table style={{maxHeight:'90%'}} columns={columns} dataSource={data} loading={nodeLoading} bordered={false} pagination={{ pageSize}}/>
+          </div>
+          <Space direction="vertical" size='8' style={{ display: auditvisible ? 'flex' : 'none' }}>
+            {stepsData.map((item ,idx)=> <div key={`${item.name}_${idx}`} style={{marginBottom:'8px'}}>
+              <div style={{marginBottom:'4px'}}>{item.name}</div>
+              <Steps size='small' current={item.current} >
+                {item.list.map(node => 
+                  <Step
+                    key={`${node.id}_${node.node}`}
+                    title={node.node}
+                  />
+                )}
+              </Steps>
+            </div>)}
+          </Space>
         </Col>
       </Row>
     </Modal>

+ 121 - 0
src/pages/PurchaseAdmin/PurchaseList/Detail/HistoryDrawer.js

@@ -0,0 +1,121 @@
+import React, { useEffect, useState, useRef, useMemo } from 'react';
+import { UserOutlined } from '@ant-design/icons';
+import { Form } from '@ant-design/compatible';
+import '@ant-design/compatible/assets/index.css';
+import { Drawer, Descriptions, Card, Table } from 'antd';
+import moment from 'moment';
+import { connect } from 'dva';
+import CommentContent from '@/components/CommentContent';
+
+// 评论
+function HistoryDrawer(props) {
+  const {
+    visible,
+    onClose,
+    version,
+    loading,
+    dispatch,
+    versionTree,
+  } = props;
+  const columns = useMemo(() => {
+    return [
+      {
+        title: '名称',
+        width: '33%',
+        render: item => (
+          <div style={{ color: '#9b9b9b'}}>
+            {/* {item.id == version.id && <dix style={{ marginRight: 10 }} />} */}
+            {`${item.version_name}.${item.version_no}`}
+          </div>
+        ),
+      },
+      // {
+      //   title: '状态',
+      //   width: '33%',
+      //   render: item => {
+      //     let style = { color: getColor(item) };
+      //     let txt = '';
+      //     switch (item.audit_status) {
+      //       case 0:
+      //         txt = '未提交';
+      //         break;
+      //       case 1:
+      //         txt = '待审批';
+      //         break;
+      //       case 2:
+      //         txt = '拒绝';
+      //         break;
+      //       case 3:
+      //         txt = '通过';
+      //         break;
+      //       case 4:
+      //         txt = '已提交';
+      //         break;
+      //     }
+      //     return <span style={style}>{txt}</span>;
+      //   },
+      // },
+      {
+        title: '操作',
+        render: item =>
+          item.id != version.id && (
+            <a
+              onClick={() => {
+                onChangeVersion(item);
+                onClose();
+              }}
+            >
+              切换
+            </a>
+          ),
+      },
+    ];
+  }, [version]);
+  // const [commentList, setCommentList] = useState([]);
+
+  // const handleSubmitBom = (value, callback) => {
+  //   if (!value) return;
+  //   dispatch({
+  //     type: 'detail/addBomComment',
+  //     payload: {
+  //       excel_id: version.id,
+  //       comment: value,
+  //     },
+  //     callback,
+  //   });
+  // };
+  // const handleSubmitCell = (value, callback) => {
+  //   if (!value) return;
+  //   dispatch({
+  //     type: 'detail/addComment',
+  //     payload: {
+  //       ...cellPosition.current,
+  //       comment: value,
+  //     },
+  //     callback,
+  //   });
+  // };
+
+  useEffect(() => {
+    console.log("====================================",versionTree)
+  }, [version.id]);
+
+  return (
+    <Drawer
+      width={600}
+      title="历史版本"
+      mask={false}
+      placement="right"
+      onClose={onClose}
+      visible={visible}
+    >
+      <Table columns={columns} dataSource={versionTree} bordered={false} />
+    </Drawer>
+  );
+}
+export default connect(({ detail, user, loading }) => ({
+  comment: detail.comment,
+  userList: user.list,
+  bomComment: detail.bomComment,
+  loading: loading,
+}))(HistoryDrawer);

+ 54 - 18
src/pages/PurchaseAdmin/PurchaseList/Detail/Index.js

@@ -21,6 +21,7 @@ import CommentContent from '@/components/CommentContent';
 import MergeModal from './MergeModal';
 import { GetTokenFromUrl, getToken } from '@/utils/utils';
 import { queryDetail } from '@/services/boom';
+import HistoryDrawer from './HistoryDrawer';
 const LocalData = localStorage.luckysheet;
 
 const { Option } = Select;
@@ -38,8 +39,10 @@ function Detail(props) {
     versionList,
     auditList,
     flowDetail,
+    versionTree,
     match: { params },
   } = props;
+  const [versionTreeVisible, setVersionTreeVisible] = useState(false);
   const [commentVisible, setCommentVisible] = useState(false);
   const [mergeVisible, setMergeVisible] = useState(false);
   const [compareVisible, setCompareVisible] = useState(false);
@@ -215,6 +218,7 @@ function Detail(props) {
   };
 
   const onCommit = (values, id) => {
+    console.log("=================================", values, id)
     let currentNode = flowDetail.nodes.find?.(item => item.Id == version.template_node_id);
     let currentData = sheetRef.current.getSheetJson().data;
     let sheets = JSON.parse(JSON.stringify(currentData));
@@ -248,6 +252,7 @@ function Detail(props) {
       new_version: '0',
       audit_status: 0,
       data: JSON.stringify(sheets),
+      base_id: version.id,
     };
     dispatch({
       type: 'detail/commitSheet',
@@ -374,13 +379,13 @@ function Detail(props) {
               },
             });
             if (flow.current == flow.list.FlowNodes.length - 1) {
-              // 最后一个审核节点通过后  需要更新version id
-              localStorage.excelId = newVersion.id;
-              setVersion({
-                ...version,
-                flow_id: newVersion.flow_id,
-                id: newVersion.id,
-              });
+              // 最后一个审核节点通过后  需要更新version id 不更不更,留在原地
+              // localStorage.excelId = newVersion.id;
+              // setVersion({
+              //   ...version,
+              //   flow_id: newVersion.flow_id,
+              //   id: newVersion.id,
+              // });
             }
           },
         });
@@ -531,7 +536,20 @@ function Detail(props) {
     ];
     // version.audit_status:4 为副本。不可操作
     if (version.audit_status != 4) {
-      menuList.push(<Menu.Item key="commitAudit">提交流转</Menu.Item>);
+      //判断权限配置,如果配置了,就指定权限的人可提交,没配置就全部人都可提交
+      const getIsSubmit = () => {
+        const nodeId = version.template_node_id;
+        if (!flowDetail?.nodes || !nodeId) return;
+        const node = flowDetail.nodes.find(item => item.Id == nodeId);
+        if(node.name=='custom-circle') return ;
+        if( node?.role_list && node?.role_list.length > 0){
+          return node.role_list.split(",").some(id=> currentUser.roleList?.find(role=>role.ID == id))
+        } 
+        return true;
+      }
+      console.log('是否有权限提交流转',getIsSubmit())
+      if(getIsSubmit()) menuList.push(<Menu.Item key="commitAudit">提交流转</Menu.Item>);
+      
 
       if (!isAuditor && canEdit() && !version.flow_id) {
         // menuList.push(<Menu.Item key="edit">编辑</Menu.Item>);
@@ -707,6 +725,13 @@ function Detail(props) {
       localStorage.excelId = id;
     }
     setVersion(version);
+    //请求历史版本
+    dispatch({
+      type:'detail/queryVersionsTree',
+      payload: {
+        excel_id: version.id || localStorage.excelId,
+      },
+    })
 
     // 判断是否审批节点
     if (version.flow_id) {
@@ -729,12 +754,12 @@ function Detail(props) {
       callback: newVersion => {
         setCommitAuditVisible(false);
         // 更新version
-        localStorage.excelId = newVersion.id;
-        changeVersion({
-          ...version,
-          ...newVersion,
-          version_id: version.id
-        });
+        // localStorage.excelId = newVersion.id;
+        // changeVersion({
+        //   ...version,
+        //   ...newVersion,
+        //   version_id: version.id
+        // });
         // 更新flow流程图
         dispatch({
           type: 'xflow/queryBoomFlowDetail',
@@ -785,6 +810,7 @@ function Detail(props) {
     dispatch({
       type: 'user/fetch',
     });
+    
   }, []);
 
   useEffect(() => {
@@ -828,15 +854,17 @@ function Detail(props) {
           )}
           <span style={{ marginLeft: 20 }}>{renderNode()}</span>
         </div>
-        <div className={styles.btns}>
+        <div className={styles.btns}> 
+          <Button type="primary" style={{ marginRight: 20 }} onClick={() => setVersionTreeVisible(true)}>
+            历史版本
+          </Button>
           <Avatar.Group style={{ marginRight: 20 }}>
-            {user.map(item => (
-              <Avatar style={{ backgroundColor: '#008dff' }} size="large">
+            {user.map((item, id) => (
+              <Avatar key={`${id}-${item.name}`} style={{ backgroundColor: '#008dff' }} size="large">
                 {item.Name}
               </Avatar>
             ))}
           </Avatar.Group>
-
           {renderBtns()}
         </div>
         <input
@@ -874,6 +902,13 @@ function Detail(props) {
         </div>
       )}
 
+      <HistoryDrawer 
+        versionTree={versionTree}
+         version={version}
+         visible={versionTreeVisible}
+         onClose={() => setVersionTreeVisible(false)}
+      />
+
       <CommentContent
         title="单元格沟通记录"
         comment={comment}
@@ -951,5 +986,6 @@ export default connect(({ detail, user, xflow, loading }) => ({
   currentUser: user.currentUser,
   roleList: detail.roleList,
   versionList: detail.versionList,
+  versionTree: detail.versionTree,
   loading,
 }))(Detail);

+ 19 - 0
src/pages/PurchaseAdmin/PurchaseList/Detail/models/detail.js

@@ -28,6 +28,8 @@ import {
   queryBomComment,
   approve,
   queryAuthority,
+  queryVersionsTree,
+  queryAuditExcel,
 } from '@/services/boom';
 import { queryRole } from '@/services/SysAdmin';
 import { setCurrentUser } from '@/utils/authority';
@@ -68,6 +70,8 @@ export default {
     fileList: [],
     roleList: [],
     authority: [],
+    versionTree:[],
+    auditExcel:[],
   },
 
   effects: {
@@ -487,6 +491,21 @@ export default {
         });
       }
     },
+    *queryVersionsTree({ payload }, { call, put }) {
+      const response = yield call(queryVersionsTree, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { versionTree: response.data },
+        });
+      }
+    },
+    *queryAuditExcel({ payload,  callback  }, { call, put }) {
+      const response = yield call(queryAuditExcel, payload);
+      if (response) {
+        callback && callback(response.data?.all);
+      }
+    },
   },
 
   reducers: {

+ 624 - 117
src/pages/PurchaseAdmin/PurchaseList/Flow/FlowDetail.json

@@ -10,10 +10,22 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "293a90b5" },
-          { "group": "right", "id": "92334433" },
-          { "group": "bottom", "id": "c2ab5849" },
-          { "group": "left", "id": "6079a903" }
+          {
+            "group": "top",
+            "id": "293a90b5"
+          },
+          {
+            "group": "right",
+            "id": "92334433"
+          },
+          {
+            "group": "bottom",
+            "id": "c2ab5849"
+          },
+          {
+            "group": "left",
+            "id": "6079a903"
+          }
         ]
       },
       "isCustom": true,
@@ -31,15 +43,27 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "a61170c3" },
-          { "group": "right", "id": "821f59c0" },
-          { "group": "bottom", "id": "17360bc4" },
-          { "group": "left", "id": "15d1b217" }
+          {
+            "group": "top",
+            "id": "a61170c3"
+          },
+          {
+            "group": "right",
+            "id": "821f59c0"
+          },
+          {
+            "group": "bottom",
+            "id": "17360bc4"
+          },
+          {
+            "group": "left",
+            "id": "15d1b217"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -369,
+      "x": -290,
       "y": -170,
       "zIndex": 10
     },
@@ -52,15 +76,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "4b4d9fa6" },
-          { "group": "right", "id": "ce88d7e2" },
-          { "group": "bottom", "id": "e69d8709" },
-          { "group": "left", "id": "c29d7b43" }
+          {
+            "group": "top",
+            "id": "4b4d9fa6"
+          },
+          {
+            "group": "right",
+            "id": "ce88d7e2"
+          },
+          {
+            "group": "bottom",
+            "id": "e69d8709"
+          },
+          {
+            "group": "left",
+            "id": "c29d7b43"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -162,
+      "x": -138,
       "y": -150,
       "zIndex": 10
     },
@@ -73,10 +109,22 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "331cd291" },
-          { "group": "right", "id": "ff6724ee" },
-          { "group": "bottom", "id": "16b4df46" },
-          { "group": "left", "id": "34c9dbc6" }
+          {
+            "group": "top",
+            "id": "331cd291"
+          },
+          {
+            "group": "right",
+            "id": "ff6724ee"
+          },
+          {
+            "group": "bottom",
+            "id": "16b4df46"
+          },
+          {
+            "group": "left",
+            "id": "34c9dbc6"
+          }
         ]
       },
       "isCustom": true,
@@ -94,10 +142,22 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "f71ce55b" },
-          { "group": "right", "id": "e67dc19c" },
-          { "group": "bottom", "id": "a06aba2c" },
-          { "group": "left", "id": "b578cc26" }
+          {
+            "group": "top",
+            "id": "f71ce55b"
+          },
+          {
+            "group": "right",
+            "id": "e67dc19c"
+          },
+          {
+            "group": "bottom",
+            "id": "a06aba2c"
+          },
+          {
+            "group": "left",
+            "id": "b578cc26"
+          }
         ]
       },
       "isCustom": true,
@@ -115,10 +175,22 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "0fc44196" },
-          { "group": "right", "id": "d2030f1b" },
-          { "group": "bottom", "id": "188c9b68" },
-          { "group": "left", "id": "4e9ce7ad" }
+          {
+            "group": "top",
+            "id": "0fc44196"
+          },
+          {
+            "group": "right",
+            "id": "d2030f1b"
+          },
+          {
+            "group": "bottom",
+            "id": "188c9b68"
+          },
+          {
+            "group": "left",
+            "id": "4e9ce7ad"
+          }
         ]
       },
       "isCustom": true,
@@ -136,15 +208,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "b58731c5" },
-          { "group": "right", "id": "b3dfbc16" },
-          { "group": "bottom", "id": "89c0bc16" },
-          { "group": "left", "id": "a3adcac9" }
+          {
+            "group": "top",
+            "id": "b58731c5"
+          },
+          {
+            "group": "right",
+            "id": "b3dfbc16"
+          },
+          {
+            "group": "bottom",
+            "id": "89c0bc16"
+          },
+          {
+            "group": "left",
+            "id": "a3adcac9"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -384,
+      "x": -305,
       "y": -304,
       "zIndex": 10
     },
@@ -157,15 +241,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "7f8dc65b" },
-          { "group": "right", "id": "9a699e3f" },
-          { "group": "bottom", "id": "d348b56a" },
-          { "group": "left", "id": "47317157" }
+          {
+            "group": "top",
+            "id": "7f8dc65b"
+          },
+          {
+            "group": "right",
+            "id": "9a699e3f"
+          },
+          {
+            "group": "bottom",
+            "id": "d348b56a"
+          },
+          {
+            "group": "left",
+            "id": "47317157"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -162,
+      "x": -138,
       "y": -304,
       "zIndex": 10
     },
@@ -178,15 +274,27 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "cf1c4df0" },
-          { "group": "right", "id": "1eb352b0" },
-          { "group": "bottom", "id": "83b59198" },
-          { "group": "left", "id": "94f485b5" }
+          {
+            "group": "top",
+            "id": "cf1c4df0"
+          },
+          {
+            "group": "right",
+            "id": "1eb352b0"
+          },
+          {
+            "group": "bottom",
+            "id": "83b59198"
+          },
+          {
+            "group": "left",
+            "id": "94f485b5"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 213,
+      "x": 356,
       "y": -324,
       "zIndex": 10
     },
@@ -199,15 +307,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "3ca1320c" },
-          { "group": "right", "id": "4dee75d9" },
-          { "group": "bottom", "id": "0f72f2ba" },
-          { "group": "left", "id": "bac7962b" }
+          {
+            "group": "top",
+            "id": "3ca1320c"
+          },
+          {
+            "group": "right",
+            "id": "4dee75d9"
+          },
+          {
+            "group": "bottom",
+            "id": "0f72f2ba"
+          },
+          {
+            "group": "left",
+            "id": "bac7962b"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 198,
+      "x": 446,
       "y": -150,
       "zIndex": 10
     },
@@ -220,15 +340,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "04c81e99" },
-          { "group": "right", "id": "0d594eef" },
-          { "group": "bottom", "id": "17ff5fe6" },
-          { "group": "left", "id": "73307680" }
+          {
+            "group": "top",
+            "id": "04c81e99"
+          },
+          {
+            "group": "right",
+            "id": "0d594eef"
+          },
+          {
+            "group": "bottom",
+            "id": "17ff5fe6"
+          },
+          {
+            "group": "left",
+            "id": "73307680"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 386,
+      "x": 621,
       "y": -150,
       "zIndex": 10
     },
@@ -241,15 +373,27 @@
       "height": 50,
       "ports": {
         "items": [
-          { "group": "top", "id": "2aae2a71" },
-          { "group": "right", "id": "e3a42bda" },
-          { "group": "bottom", "id": "0f06668a" },
-          { "group": "left", "id": "8e0bff55" }
+          {
+            "group": "top",
+            "id": "2aae2a71"
+          },
+          {
+            "group": "right",
+            "id": "e3a42bda"
+          },
+          {
+            "group": "bottom",
+            "id": "0f06668a"
+          },
+          {
+            "group": "left",
+            "id": "8e0bff55"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 198,
+      "x": 446,
       "y": 26,
       "zIndex": 10
     },
@@ -262,15 +406,27 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "8ab6c3f6" },
-          { "group": "right", "id": "205f1437" },
-          { "group": "bottom", "id": "761ad2b5" },
-          { "group": "left", "id": "22d16375" }
+          {
+            "group": "top",
+            "id": "8ab6c3f6"
+          },
+          {
+            "group": "right",
+            "id": "205f1437"
+          },
+          {
+            "group": "bottom",
+            "id": "761ad2b5"
+          },
+          {
+            "group": "left",
+            "id": "22d16375"
+          }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 42,
+      "x": 308,
       "y": -170,
       "zIndex": 10
     },
@@ -283,10 +439,22 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "99f69f24" },
-          { "group": "right", "id": "0bccd839" },
-          { "group": "bottom", "id": "42c0d925" },
-          { "group": "left", "id": "58f52f2c" }
+          {
+            "group": "top",
+            "id": "99f69f24"
+          },
+          {
+            "group": "right",
+            "id": "0bccd839"
+          },
+          {
+            "group": "bottom",
+            "id": "42c0d925"
+          },
+          {
+            "group": "left",
+            "id": "58f52f2c"
+          }
         ]
       },
       "isCustom": true,
@@ -294,98 +462,437 @@
       "x": 42,
       "y": 6,
       "zIndex": 10
-    }
-  ],
-  "edges": [
+    },
     {
-      "id": "41561012:92334433-975bf288:15d1b217",
-      "source": { "cell": "41561012", "port": "92334433" },
-      "target": { "cell": "975bf288", "port": "15d1b217" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "id": "2427bf29",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "三级审批1",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          {
+            "group": "top",
+            "id": "e5a149c4"
+          },
+          {
+            "group": "right",
+            "id": "e1a1ecea"
+          },
+          {
+            "group": "bottom",
+            "id": "6e131e6a"
+          },
+          {
+            "group": "left",
+            "id": "6bbf9ae4"
+          }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "1",
+      "x": -425,
+      "y": -224,
+      "zIndex": 10
     },
     {
-      "id": "975bf288:821f59c0-5764f3ce:c29d7b43",
-      "source": { "cell": "975bf288", "port": "821f59c0" },
-      "target": { "cell": "5764f3ce", "port": "c29d7b43" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "id": "be25fe75",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "三级审批2",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          {
+            "group": "top",
+            "id": "13e4b9ea"
+          },
+          {
+            "group": "right",
+            "id": "ce651308"
+          },
+          {
+            "group": "bottom",
+            "id": "9a0b8942"
+          },
+          {
+            "group": "left",
+            "id": "a705e7ed"
+          }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "1",
+      "x": -425,
+      "y": -115,
+      "zIndex": 10
     },
+    {
+      "id": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "审批节点",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          {
+            "group": "top",
+            "id": "c6ec15a8-2db4-4ca8-ad81-fd1783b4ca0f"
+          },
+          {
+            "group": "right",
+            "id": "e134d65d-a197-4116-ad74-f47dbbb727d1"
+          },
+          {
+            "group": "bottom",
+            "id": "2c633cdf-7bb5-49ea-a4dc-e3d8c837e513"
+          },
+          {
+            "group": "left",
+            "id": "6d880b9d-7d7e-4357-94dd-caf7d73b5f80"
+          }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": 27,
+      "y": -224,
+      "zIndex": 10
+    },
+    {
+      "id": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "审批节点",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          {
+            "group": "top",
+            "id": "7b9fcd52-4fca-47c7-aaae-e3b117c0c234"
+          },
+          {
+            "group": "right",
+            "id": "6316d87e-2eb3-4ff6-bd8e-0cfd11bff4ce"
+          },
+          {
+            "group": "bottom",
+            "id": "38113945-040f-4374-aca8-38e2e81d71a8"
+          },
+          {
+            "group": "left",
+            "id": "8637b869-7924-416a-b938-30a7ca932901"
+          }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": 27,
+      "y": -115,
+      "zIndex": 10
+    },
+    {
+      "id": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "审批节点",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          {
+            "group": "top",
+            "id": "d9b27b16-08ab-4e0d-84dc-fdec64c0a129"
+          },
+          {
+            "group": "right",
+            "id": "1ab6b2a4-dccd-41e9-83c6-d1642c9ad844"
+          },
+          {
+            "group": "bottom",
+            "id": "b763caac-37c1-4659-ae0e-c7b7c760fec1"
+          },
+          {
+            "group": "left",
+            "id": "2408c946-a670-48b5-a676-d882946b8e36"
+          }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": 173,
+      "y": -170,
+      "zIndex": 10
+    }
+  ],
+  "edges": [
     {
       "id": "975bf288:a61170c3-8c1f18d0:89c0bc16",
-      "source": { "cell": "975bf288", "port": "a61170c3" },
-      "target": { "cell": "8c1f18d0", "port": "89c0bc16" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "975bf288",
+        "port": "a61170c3"
+      },
+      "target": {
+        "cell": "8c1f18d0",
+        "port": "89c0bc16"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "8c1f18d0:a3adcac9-41561012:293a90b5",
-      "source": { "cell": "8c1f18d0", "port": "a3adcac9" },
-      "target": { "cell": "41561012", "port": "293a90b5" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "8c1f18d0",
+        "port": "a3adcac9"
+      },
+      "target": {
+        "cell": "41561012",
+        "port": "293a90b5"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "5764f3ce:4b4d9fa6-1aed14d1:d348b56a",
-      "source": { "cell": "5764f3ce", "port": "4b4d9fa6" },
-      "target": { "cell": "1aed14d1", "port": "d348b56a" },
+      "source": {
+        "cell": "5764f3ce",
+        "port": "4b4d9fa6"
+      },
+      "target": {
+        "cell": "1aed14d1",
+        "port": "d348b56a"
+      },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "1aed14d1:9a699e3f-4651130e:94f485b5",
-      "source": { "cell": "1aed14d1", "port": "9a699e3f" },
-      "target": { "cell": "4651130e", "port": "94f485b5" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
-    },
-    {
-      "id": "5764f3ce:ce88d7e2-3fb8d302:22d16375",
-      "source": { "cell": "5764f3ce", "port": "ce88d7e2" },
-      "target": { "cell": "3fb8d302", "port": "22d16375" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "1aed14d1",
+        "port": "9a699e3f"
+      },
+      "target": {
+        "cell": "4651130e",
+        "port": "94f485b5"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "3fb8d302:205f1437-a48131e0:bac7962b",
-      "source": { "cell": "3fb8d302", "port": "205f1437" },
-      "target": { "cell": "a48131e0", "port": "bac7962b" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "3fb8d302",
+        "port": "205f1437"
+      },
+      "target": {
+        "cell": "a48131e0",
+        "port": "bac7962b"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "a48131e0:4dee75d9-b57b57c8:73307680",
-      "source": { "cell": "a48131e0", "port": "4dee75d9" },
-      "target": { "cell": "b57b57c8", "port": "73307680" },
+      "source": {
+        "cell": "a48131e0",
+        "port": "4dee75d9"
+      },
+      "target": {
+        "cell": "b57b57c8",
+        "port": "73307680"
+      },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "a48131e0:0f72f2ba-3631eae9:2aae2a71",
-      "source": { "cell": "a48131e0", "port": "0f72f2ba" },
-      "target": { "cell": "3631eae9", "port": "2aae2a71" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "a48131e0",
+        "port": "0f72f2ba"
+      },
+      "target": {
+        "cell": "3631eae9",
+        "port": "2aae2a71"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "3631eae9:8e0bff55-399bddb7:0bccd839",
-      "source": { "cell": "3631eae9", "port": "8e0bff55" },
-      "target": { "cell": "399bddb7", "port": "0bccd839" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "3631eae9",
+        "port": "8e0bff55"
+      },
+      "target": {
+        "cell": "399bddb7",
+        "port": "0bccd839"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "399bddb7:58f52f2c-c28a18d3:e67dc19c",
-      "source": { "cell": "399bddb7", "port": "58f52f2c" },
-      "target": { "cell": "c28a18d3", "port": "e67dc19c" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "399bddb7",
+        "port": "58f52f2c"
+      },
+      "target": {
+        "cell": "c28a18d3",
+        "port": "e67dc19c"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "c28a18d3:b578cc26-5359e23c:ff6724ee",
-      "source": { "cell": "c28a18d3", "port": "b578cc26" },
-      "target": { "cell": "5359e23c", "port": "ff6724ee" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "c28a18d3",
+        "port": "b578cc26"
+      },
+      "target": {
+        "cell": "5359e23c",
+        "port": "ff6724ee"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "5359e23c:34c9dbc6-5216c5dc:d2030f1b",
-      "source": { "cell": "5359e23c", "port": "34c9dbc6" },
-      "target": { "cell": "5216c5dc", "port": "d2030f1b" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "5359e23c",
+        "port": "34c9dbc6"
+      },
+      "target": {
+        "cell": "5216c5dc",
+        "port": "d2030f1b"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     },
     {
       "id": "b57b57c8:04c81e99-4651130e:1eb352b0",
-      "source": { "cell": "b57b57c8", "port": "04c81e99" },
-      "target": { "cell": "4651130e", "port": "1eb352b0" },
-      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+      "source": {
+        "cell": "b57b57c8",
+        "port": "04c81e99"
+      },
+      "target": {
+        "cell": "4651130e",
+        "port": "1eb352b0"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "41561012:92334433-2427bf29:6bbf9ae4",
+      "source": {
+        "cell": "41561012",
+        "port": "92334433"
+      },
+      "target": {
+        "cell": "2427bf29",
+        "port": "6bbf9ae4"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "41561012:92334433-be25fe75:a705e7ed",
+      "source": {
+        "cell": "41561012",
+        "port": "92334433"
+      },
+      "target": {
+        "cell": "be25fe75",
+        "port": "a705e7ed"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "2427bf29:e1a1ecea-975bf288:15d1b217",
+      "source": {
+        "cell": "2427bf29",
+        "port": "e1a1ecea"
+      },
+      "target": {
+        "cell": "975bf288",
+        "port": "15d1b217"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "be25fe75:ce651308-975bf288:15d1b217",
+      "source": {
+        "cell": "be25fe75",
+        "port": "ce651308"
+      },
+      "target": {
+        "cell": "975bf288",
+        "port": "15d1b217"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "975bf288:821f59c0-5764f3ce:c29d7b43",
+      "source": {
+        "cell": "975bf288",
+        "port": "821f59c0"
+      },
+      "target": {
+        "cell": "5764f3ce",
+        "port": "c29d7b43"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "5764f3ce:ce88d7e2-node-186a9d31-0bd3-4b36-b61f-6b5380c824db:6d880b9d-7d7e-4357-94dd-caf7d73b5f80",
+      "source": {
+        "cell": "5764f3ce",
+        "port": "ce88d7e2"
+      },
+      "target": {
+        "cell": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
+        "port": "6d880b9d-7d7e-4357-94dd-caf7d73b5f80"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "5764f3ce:ce88d7e2-node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8:8637b869-7924-416a-b938-30a7ca932901",
+      "source": {
+        "cell": "5764f3ce",
+        "port": "ce88d7e2"
+      },
+      "target": {
+        "cell": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
+        "port": "8637b869-7924-416a-b938-30a7ca932901"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db:e134d65d-a197-4116-ad74-f47dbbb727d1-node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862:2408c946-a670-48b5-a676-d882946b8e36",
+      "source": {
+        "cell": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
+        "port": "e134d65d-a197-4116-ad74-f47dbbb727d1"
+      },
+      "target": {
+        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
+        "port": "2408c946-a670-48b5-a676-d882946b8e36"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8:6316d87e-2eb3-4ff6-bd8e-0cfd11bff4ce-node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862:2408c946-a670-48b5-a676-d882946b8e36",
+      "source": {
+        "cell": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
+        "port": "6316d87e-2eb3-4ff6-bd8e-0cfd11bff4ce"
+      },
+      "target": {
+        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
+        "port": "2408c946-a670-48b5-a676-d882946b8e36"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862:1ab6b2a4-dccd-41e9-83c6-d1642c9ad844-3fb8d302:22d16375",
+      "source": {
+        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
+        "port": "1ab6b2a4-dccd-41e9-83c6-d1642c9ad844"
+      },
+      "target": {
+        "cell": "3fb8d302",
+        "port": "22d16375"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":\"5 5\",\"strokeWidth\":1}}"
     }
   ]
-}
+}

+ 3 - 0
src/pages/PurchaseAdmin/PurchaseList/Flow/List.js

@@ -47,6 +47,9 @@ function List(props) {
     dispatch({
       type: 'flow/queryProject',
     });
+    dispatch({
+      type: 'flow/getRoleList',
+    });
   }, []);
 
   return (

+ 0 - 2
src/pages/PurchaseAdmin/PurchaseList/Index.js

@@ -92,11 +92,9 @@ function LayoutDetail(props) {
                 </SubMenu>
               )}
 
-              {/* {isAdmin && (
               <Menu.Item key="/home">
                 <Link to="/home">采购清单</Link>
               </Menu.Item>
-              )} */}
               <Menu.Item key="/home/flow-list">
                 <Link to="/home/flow-list">流程图</Link>
               </Menu.Item>

+ 10 - 0
src/services/boom.js

@@ -1,4 +1,5 @@
 import request from '@/utils/request';
+import { async } from '@antv/x6/lib/registry/marker/async';
 import { stringify } from 'qs';
 
 /**
@@ -90,6 +91,15 @@ export async function queryHistoryList(params) {
 export async function queryBoomFlowList(params) {
   return request(`/purchase/bom/flows?${stringify(params)}`);
 }
+//请求历史版本
+export async function queryVersionsTree(params){
+  console.log("============================", stringify(params))
+  return request(`/api/v1/purchase/record/version/tree?${stringify(params)}`);
+}
+//查询业务节点的审核记录
+export async function queryAuditExcel(params){
+  return request(`/api/v1/purchase/audit/excel?${stringify(params)}`);
+}
 /**
  * 查看项目流程列表
  * project_id