Explorar o código

Squashed commit of the following:
psr
commit 540139dc66b648e1b3c1c3ec817a5d83526b4776
Merge: 61f1174 530a80e
Author: Renxy <18510891294@163.com>
Date: Fri Jun 30 19:36:25 2023 +0800

Merge branch 'develop' of http://120.55.44.4:10080/xujunjie/BomWeb into develop

commit 61f117463d50a4ef29e388a2ddbe4f9d2227c5bc
Author: Renxy <18510891294@163.com>
Date: Fri Jun 30 19:36:15 2023 +0800

Squashed commit of the following:
psr
commit 6ff0c77abc4b668bfe2ae2ba83f6be4315cf1939
Author: Renxy <18510891294@163.com>
Date: Fri Jun 30 19:28:18 2023 +0800

删除id

commit 93b5fe74c0ca3a51976b470c3d4a9e0e976981c6
Author: Renxy <18510891294@163.com>
Date: Thu Jun 29 18:07:20 2023 +0800

修改提交流转时自动填充审批节点逻辑

commit 879efcf1ec56141a1351089b8c0aa15c5cd8bcab
Author: xjj <645007605@qq.com>
Date: Thu Jun 29 09:34:14 2023 +0800

psr提交

commit b1687c3877cf9871a22278a02acdf5679f88054d
Author: hanxin <32479996@qq.com>
Date: Mon Jun 26 15:20:23 2023 +0800

类型新增投标、合同测算

commit e512204d76d7672fde83d8149bedf70fe50d7ede
Author: hanxin <32479996@qq.com>
Date: Mon Jun 26 10:21:53 2023 +0800

审批流新增模板json修改

commit a4722b891154c780c97696db39b69d0786f4b633
Author: hanxin <32479996@qq.com>
Date: Tue Jun 20 15:54:04 2023 +0800

审批报错

commit 2977ea6a881a6e9f07941f17bd7d3c767e48c6da
Author: hanxin <32479996@qq.com>
Date: Tue Jun 20 15:53:54 2023 +0800

单节点多线修改

commit b83df3c3f47a75acdb61262b954eecd95a4ea81c
Author: hanxin <32479996@qq.com>
Date: Tue Jun 20 13:44:12 2023 +0800

节点添加节点类型

commit 99f98118f031d6ebcc433c886a923d20a7d466c3
Author: Renxy <18510891294@163.com>
Date: Thu Jun 15 16:03:00 2023 +0800

渲染后增加刷新

commit 8bcb4328319aabdbd4ce399cb67f91fe8e260f15
Author: xjj <645007605@qq.com>
Date: Thu Jun 15 10:49:59 2023 +0800

temp

commit a7b919389733c5a1c0a536683820c4ac71a76478
Author: xjj <645007605@qq.com>
Date: Mon Jun 5 11:32:59 2023 +0800

修复无法关闭同步和比对的问题

commit 8ded6998e2dea10e25ac4e10bff79b5fbf73883a
Author: xjj <645007605@qq.com>
Date: Wed May 31 17:09:24 2023 +0800

修复筛选不生效的问题

commit b74dec84cbe02338ccd36f5d4a4f0ae632260926
Author: xjj <645007605@qq.com>
Date: Wed May 31 10:29:06 2023 +0800

修复筛选

commit 34be0e261ecf0c848d3e4924ae40f04624d55d7d
Author: xjj <645007605@qq.com>
Date: Wed May 31 10:28:07 2023 +0800

修复特殊情况会报错

commit f39cdde8a6d7157fb4eddfb6d2e5cae165f046ad
Author: xjj <645007605@qq.com>
Date: Thu May 25 14:54:36 2023 +0800

修复复制失效

commit 8e283e60217a8e22c8fd5e81de17df2042df6df6
Author: xjj <645007605@qq.com>
Date: Thu May 18 15:05:44 2023 +0800

自动查询时间延长

commit 530a80e739ac642598627e851119b6f1aee9602b
Author: ZhaoJun <jun.zhao@greentech.com.cn>
Date: Thu Jun 29 16:52:50 2023 +0800

feat(流程管理): 表单设计新增日历控件

commit 76346e440b40181834cde9c0e6653cc20358aabf
Author: ZhaoJun <jun.zhao@greentech.com.cn>
Date: Thu Jun 29 09:53:43 2023 +0800

style(Detail): 调整时间轴位置,限制最大高度

commit eb63dd6258333b650e240d0443019054bae05829
Author: ZhaoJun <jun.zhao@greentech.com.cn>
Date: Wed Jun 28 20:09:06 2023 +0800

refactor(Detail Page): 修改审批时间轴为垂直

Renxy hai 1 ano
pai
achega
36189c54b0

+ 4 - 0
config/router.config.js

@@ -53,6 +53,10 @@ export default [
         path: '/mobile/detail/:templateId/:versionId',
         component: './Detail/Mobile',
       },
+      {
+        path: '/temp',
+        component: './Temp/Index',
+      },
 
       // {
       //   path: '/dd-login/:dingUserId',

+ 140 - 55
src/components/AuditForm/ItemAttribute.js

@@ -7,17 +7,19 @@ function ItemAttribute(props) {
   const renderForm = () => {
     let FormContent;
     const formProps = {
-      btns: <Form.Item>
-        <Button type="primary" htmlType="submit" style={{ marginRight: 20 }}>
-          保存
-        </Button>
-      </Form.Item>,
+      btns: (
+        <Form.Item>
+          <Button type="primary" htmlType="submit" style={{ marginRight: 20 }}>
+            保存
+          </Button>
+        </Form.Item>
+      ),
       item,
       onFinish: values => {
         console.log(values);
         onChange?.(values);
-      }
-    }
+      },
+    };
     switch (item.componentName) {
       case 'InnerContactField':
         FormContent = <InnerContactField {...formProps} />;
@@ -40,6 +42,9 @@ function ItemAttribute(props) {
       case 'NumberField':
         FormContent = <NumberField {...formProps} />;
         break;
+      case 'DDDateField':
+        FormContent = <DDDateField {...formProps} />;
+        break;
     }
 
     return FormContent;
@@ -69,10 +74,17 @@ function InnerContactField(props) {
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const onSwitchChange = checked => {
-    form.setFieldValue("choice", checked ? 1 : 0);
-  }
+    form.setFieldValue('choice', checked ? 1 : 0);
+  };
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={onFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>
@@ -98,7 +110,14 @@ function DepartmentField(props) {
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={onFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>
@@ -153,7 +172,14 @@ function TextareaField(props) {
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={onFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>
@@ -175,17 +201,24 @@ function DDSelectField(props) {
     let arr = [];
     tempValue.options.map(item => {
       arr.push(item.value);
-    })
+    });
     if (arr) {
-      arr = arr.filter(item => item)
+      arr = arr.filter(item => item);
       arr = [...new Set(arr)];
-      tempValue.options = arr
+      tempValue.options = arr;
     }
     onFinish?.(tempValue);
-  }
+  };
 
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={handleFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={handleFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>
@@ -210,16 +243,23 @@ function DDMultiSelectField(props) {
     let arr = [];
     tempValue.options.map(item => {
       arr.push(item.value);
-    })
+    });
     if (arr) {
-      arr = arr.filter(item => item)
+      arr = arr.filter(item => item);
       arr = [...new Set(arr)];
-      tempValue.options = arr
+      tempValue.options = arr;
     }
     onFinish?.(tempValue);
-  }
+  };
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={handleFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={handleFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>
@@ -237,30 +277,57 @@ function DDMultiSelectField(props) {
   );
 }
 
+function DDDateField(props) {
+  const { item, btns, onFinish } = props;
+  const [form] = Form.useForm();
+
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      onFinish={onFinish}
+      autoComplete="off"
+      initialValues={item.props}
+    >
+      <Form.Item label="标题" name="label">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字" name="placeholder">
+        <Input />
+      </Form.Item>
+      {btns}
+    </Form>
+  );
+}
+
 function SelectItem(props) {
   const { value, onChange } = props;
   const [localValue, setLocalValue] = useState([]);
   const pushItem = item => {
-    let tempValue = [...localValue, {
-      id: +new Date(),
-      value: item
-    }];
+    let tempValue = [
+      ...localValue,
+      {
+        id: +new Date(),
+        value: item,
+      },
+    ];
     setLocalValue(tempValue);
     onChange(tempValue);
-  }
+  };
 
   const handleDelete = index => {
     let tempValue = [...localValue];
     tempValue.splice(index, 1);
     setLocalValue(tempValue);
     onChange(tempValue);
-  }
+  };
   const handleInputOnChange = (targetValue, index) => {
     let tempValue = [...localValue];
     tempValue[index].value = targetValue;
     setLocalValue(tempValue);
     onChange(tempValue);
-  }
+  };
   useEffect(() => {
     let tempValue = value.map(item => ({ id: +new Date(), value: item }));
     setLocalValue(tempValue);
@@ -268,46 +335,64 @@ function SelectItem(props) {
   }, []);
 
   return (
-    <div style={{
-      minHeight: 40,
-      display: 'flex',
-      flexDirection: 'column'
-    }}>
+    <div
+      style={{
+        minHeight: 40,
+        display: 'flex',
+        flexDirection: 'column',
+      }}
+    >
       <div>
-        <div style={{
-          fontSize: 4,
-          color: '#40a9ff',
-          cursor: 'pointer',
-          lineHeight: '32px'
-        }} onClick={() => { pushItem('') }}>添加选项</div>
+        <div
+          style={{
+            fontSize: 4,
+            color: '#40a9ff',
+            cursor: 'pointer',
+            lineHeight: '32px',
+          }}
+          onClick={() => {
+            pushItem('');
+          }}
+        >
+          添加选项
+        </div>
       </div>
       <div style={{ minHeight: 20 }}>
-        {
-          localValue.map((item, index) =>
-            <div style={{
+        {localValue.map((item, index) => (
+          <div
+            style={{
               display: 'flex',
               justifyContent: 'center',
               alignItems: 'center',
-              marginBottom: 5
+              marginBottom: 5,
             }}
-              key={item.id}
-            >
-              <Input style={{ marginRight: 10 }} value={item.value} onChange={e => handleInputOnChange(e.target.value, index)} />
-              <DeleteOutlined
-                onClick={() => handleDelete(index)}
-              />
-            </div>)
-        }
+            key={item.id}
+          >
+            <Input
+              style={{ marginRight: 10 }}
+              value={item.value}
+              onChange={e => handleInputOnChange(e.target.value, index)}
+            />
+            <DeleteOutlined onClick={() => handleDelete(index)} />
+          </div>
+        ))}
       </div>
-    </div >
-  )
+    </div>
+  );
 }
 
 function NumberField(props) {
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   return (
-    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off" initialValues={item.props} onFinish={onFinish}>
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
       <Form.Item label="标题" name="label">
         <Input />
       </Form.Item>

+ 14 - 3
src/components/AuditForm/constant.js

@@ -6,6 +6,7 @@ import {
   BorderOutlined,
   BlockOutlined,
   FieldNumberOutlined,
+  InsertRowAboveOutlined,
 } from '@ant-design/icons';
 
 export const COMPONENT_LIST = [
@@ -16,7 +17,7 @@ export const COMPONENT_LIST = [
       label: '联系人',
       placeholder: '请选择联系人',
       required: false,
-      choice: '0'
+      choice: '0',
     },
   },
   {
@@ -26,7 +27,7 @@ export const COMPONENT_LIST = [
       label: '选择部门',
       placeholder: '请选择部门',
       required: false,
-      choice: '0'
+      choice: '0',
     },
   },
   {
@@ -74,7 +75,17 @@ export const COMPONENT_LIST = [
       label: '数字输入框',
       placeholder: '请输入',
       required: false,
-      unit: ''
+      unit: '',
+    },
+  },
+  {
+    componentName: 'DDDateField',
+    icon: <InsertRowAboveOutlined />,
+    props: {
+      label: '日历控件',
+      placeholder: '请选择日期',
+      required: false,
+      unit: '',
     },
   },
 ];

+ 8 - 2
src/components/DDComponents/DDDateField/index.js

@@ -2,12 +2,18 @@ import React from 'react';
 import { DatePicker } from 'antd';
 
 function DDDateField(props) {
-  const { format, disabled, onChange } = props;
+  const { format = '', disabled, onChange } = props;
 
   const handleChange = date => {
     onChange?.(date.format('YYYY-MM-DD'));
   };
-  return <DatePicker disabled={disabled} format={format.replace("yyyy","YYYY").replace("dd","DD")} onChange={handleChange} />;
+  return (
+    <DatePicker
+      disabled={disabled}
+      format={format.replace('yyyy', 'YYYY').replace('dd', 'DD')}
+      onChange={handleChange}
+    />
+  );
 }
 
 export default DDDateField;

+ 17 - 0
src/components/Flow/node/rect/mapServe.tsx

@@ -10,6 +10,7 @@ import {
   InputFiled,
   UploadFiled,
   RadioField,
+  SelectField
 } from '../fields';
 import { PREFIX } from '../constants';
 import { UnityAction } from '@/utils/utils';
@@ -41,12 +42,14 @@ export interface IConfig {
   excel_info?: ExcelInfo;
   role_list?: string;
   is_seal?: string | number;
+  node_type_psr?: number | string;
 }
 
 const defaultConfig: IConfig = {
   muti_version: 1,
   is_start_node: 0,
   is_seal: 0,
+  node_type_psr: 0,
   excel_info: { file_name: '' },
 };
 
@@ -225,6 +228,20 @@ const Component = (props: any) => {
             { label: '否', value: 0 },
           ]}
         />
+        <SelectField
+          label="节点类型"
+          value={nodeConfig.node_type_psr}
+          onChange={value => {
+            onNodeConfigChange('node_type_psr', value);
+          }}
+          options={[
+            { label: '默认', value: 0 },
+            { label: '投标版', value: 1 },
+            { label: '签字版', value: 2 },
+            { label: '投标测算', value: 3 },
+            { label: '合同测算', value: 4 },
+          ]}
+        />
         {nodeConfig.is_start_node == 1 && (
           <>
             <InputFiled

+ 2 - 2
src/pages/Detail/AuditModal.js

@@ -5,7 +5,7 @@ import { Modal, Input } from 'antd';
 
 // 审批意见
 function AuditModal(props) {
-  const { flow, version, flowDetail, visible, onClose, onOk, form, sheetRef, loading } = props;
+  const { flow, version, flowDetail, visible, onClose, onOk, form, sheetRef, loading, versionList } = props;
 
   const handleOk = () => {
     form.validateFields((err, fieldsValue) => {
@@ -75,7 +75,7 @@ function AuditModal(props) {
           str += `单元格${col}${item.r}:${item.value}\n`;
         });
         form.setFieldsValue({ audit_comment: str });
-      } catch (error) {}
+      } catch (error) { }
     }
   }, [visible]);
 

+ 113 - 53
src/pages/Detail/CommitAuditModal.js

@@ -40,6 +40,8 @@ import ApprovalProcess from './ApprovalProcess';
 import { uuidv4 } from '@antv/xflow';
 import AliyunOSSUpload from '@/components/OssUpload/AliyunOssUploader';
 import AttachmentTable from '@/components/AttachmentTable';
+import { getToken } from '@/utils/utils';
+import LuckyExcel from 'luckyexcel';
 
 const { TextArea } = Input;
 const { Option } = Select;
@@ -52,7 +54,7 @@ function CommitAuditModal(props) {
     dispatch,
     visible,
     onClose,
-    loading,
+    // loading,
     version,
     versionList,
     flowDetail,
@@ -75,6 +77,7 @@ function CommitAuditModal(props) {
   const [curNodeIdx, setCurNodeIdx] = useState(-1);
 
   const [dataSource, setDataSource] = useState([]);
+  const [loading, setLoading] = useState(false);
   const uploadList = useRef([]);
 
   useEffect(() => {
@@ -85,7 +88,8 @@ function CommitAuditModal(props) {
     const currentId = flowDetail.nodes.find?.(item => item.Id == Id)?.node_id;
     const data = treeData(currentId);
     console.log('===============审批节点======', data);
-    if (data.length <= 0) {
+    const nextNodes = getNextNodes(currentId, 'custom-rect');
+    if (data.length <= 0 || nextNodes.length > 0) {
       setAuditId(currentId);
     } else {
       let defaultValues = {};
@@ -210,6 +214,10 @@ function CommitAuditModal(props) {
     //     return edge.source.cell == currentId && line && line[0] == '0';
     //   })
     //   .map(item => item.target.cell);
+    console.log(
+      '---------',
+      edges.filter(edge => edge.source.cell == currentId)
+    );
     let targetIds = edges
       .filter(edge => edge.source.cell == currentId)
       .map(item => item.target.cell);
@@ -484,63 +492,74 @@ function CommitAuditModal(props) {
     }
 
     const flowPath = result.map(item => getFlowPath(item));
-    const formList = await getFromData(result);
-    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]; // 将要流转的节点审批节点
-      params.form_list = formList; //创建钉钉表单所需数据
-      if (approvalNode?.Id) {
-        if (!approvalNode?.flow_id) {
-          hasFlowId = false;
+    setLoading(true);
+    try {
+      const formList = await getFromData(result);
+      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 (serviceNode.node_type_psr == 3 || serviceNode.node_type_psr == 4) {
+        params.data = await uploadExcelByUrl(serviceNode.node_type_psr, version.id);
+      }
+      // params.data = await uploadExcelByUrl(3, version.id);
+      console.log(params);
+
+      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]; // 将要流转的节点审批节点
+        params.form_list = formList; //创建钉钉表单所需数据
+        if (approvalNode?.Id) {
+          if (!approvalNode?.flow_id) {
+            hasFlowId = false;
+          }
         }
+      } else {
+        //多节点审批
+        params.template_node_id = result[0][0]; // 将要流转的节点审批节点
+        params.flow_path = flowPath;
+        params.form_list = formList; //创建钉钉表单所需数据
       }
-    } else {
-      //多节点审批
-      params.template_node_id = result[0][0]; // 将要流转的节点审批节点
-      params.flow_path = flowPath;
-      params.form_list = formList; //创建钉钉表单所需数据
-    }
-    if (!hasFlowId) {
-      message.error('当前存在审批节点未绑定审批流程!请联系管理员。');
-      return;
+      if (!hasFlowId) {
+        message.error('当前存在审批节点未绑定审批流程!请联系管理员。');
+        return;
+      }
+      await querySaveBomForm({
+        project_id: version.project_id,
+        node_id: version.template_node_id,
+        json: JSON.stringify({ approvalProcess }),
+      });
+      params.audit_series = uuidv4();
+      params.files = uploadList.current.join(',');
+      onSubmitNextNode(params);
+    } catch (error) {
+      console.error(error);
     }
-    await querySaveBomForm({
-      project_id: version.project_id,
-      node_id: version.template_node_id,
-      json: JSON.stringify({ approvalProcess }),
-    });
-    params.audit_series = uuidv4();
-    params.files = uploadList.current.join(',');
-    console.log(params);
-    onSubmitNextNode(params);
   };
   const onSubmitNextNode = values => {
     dispatch({
       type: 'detail/submitNextNode',
       payload: values,
       callback: newVersion => {
+        setLoading(false);
         onClose();
         // 更新flow流程图
         dispatch({
@@ -609,7 +628,7 @@ function CommitAuditModal(props) {
 
   return (
     <Modal
-      confirmLoading={loading.global}
+      confirmLoading={loading}
       destroyOnClose
       title="提交流转目标"
       width={1000}
@@ -680,12 +699,53 @@ function getDataValue(item) {
   }
   return arr;
 }
+const uploadExcelByUrl = (nodeType, versionId) => {
+  const TEMPLATE_URL =
+    'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/doc/contract/2023-06-29/ed0d5dcd-6ce0-40df-9d17-a1f69245dbb9.xlsx';
+  const TEMPLATE_URL2 =
+    'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/doc/contract/2023-06-29/431733cd-0abc-4a68-a439-d24c466e9845.xlsx';
+
+  return new Promise((reslove, reject) => {
+    LuckyExcel.transformExcelToLuckyByUrl(
+      nodeType == 3 ? TEMPLATE_URL : TEMPLATE_URL2,
+      '模板.xlsx',
+      async (exportJson, luckysheetfile) => {
+        let [record] = await getExcel(versionId);
+
+        let len = exportJson.sheets.length;
+        const excelData = exportJson.sheets?.map(item => {
+          return { ...item, order: Number(item.order) };
+        });
+        delete record.id;
+        record.order = len;
+        record.index = String(len);
+        record.status = '0';
+        record.name = '投标成本';
+        var res = [...excelData, record];
+        console.log(res);
+        reslove(JSON.stringify(res));
+      }
+    );
+  });
+};
+
+async function getExcel(gridKey) {
+  var formData = new FormData();
+  formData.append('gridKey', gridKey);
+  let res = await fetch(
+    `/api/v1/purchase/record/sheet?gridKey=${gridKey}&JWT-TOKEN=${getToken()}`,
+    {
+      method: 'POST',
+      body: formData,
+    }
+  ).then(response => response.text());
+  return JSON.parse(JSON.parse(res));
+}
 
-export default connect(({ xflow, detail, user, loading }) => ({
+export default connect(({ xflow, detail, user }) => ({
   flowDetail: xflow.flowDetail,
   versionList: detail.versionList,
   currentUser: user.currentUser,
   userList: user.list,
   OSSData: detail.OSSData,
-  loading,
 }))(CommitAuditModal);

+ 36 - 25
src/pages/Detail/FlowModal.js

@@ -385,19 +385,16 @@ function FlowModal(props) {
 
   const getDescription = node => {
     let str = `审批人:${node.AuditorUser?.CName || '-'}`;
-    if (node.desc) {
-      return (
+    return (
+      <div>
+        审批人:{node.AuditorUser?.CName || '-'}
         <div>
-          {str}
-          <div>
-            <Tooltip title={node.desc}>
-              <span style={{ color: '#1A73E8', textDecoration: 'undeline' }}>审批意见</span>
-            </Tooltip>
-          </div>
+          <span style={{ color: '#1A73E8', textDecoration: 'undeline' }}>
+            审批意见:{node.desc || '-'}
+          </span>
         </div>
-      );
-    }
-    return str;
+      </div>
+    );
   };
 
   const filterState = () => {
@@ -548,20 +545,34 @@ function FlowModal(props) {
               />
             </div>
             {/* <Spin spinning={loading.global}> */}
-            {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={getDescription(node)}
-                    />
-                  ))}
-                </Steps>
-              </div>
-            ))}
+            <div
+              style={{
+                display: 'flex',
+                justifyContent: 'space-around',
+                maxHeight: '300px',
+                overflow: 'auto',
+              }}
+            >
+              {stepsData.map((item, idx) => (
+                <div key={`${item.name}_${idx}`} style={{ marginTop: '20px', display: 'inline' }}>
+                  <div style={{ marginBottom: '4px' }}>{item.name}</div>
+                  <Steps
+                    direction="vertical"
+                    size="small"
+                    current={item.current}
+                    status={item.status}
+                  >
+                    {item.list.map(node => (
+                      <Step
+                        key={`${node.id}_${node.node}`}
+                        title={node.node}
+                        description={getDescription(node)}
+                      />
+                    ))}
+                  </Steps>
+                </div>
+              ))}
+            </div>
             {/* </Spin> */}
           </Col>
         </Row>

+ 58 - 47
src/pages/Detail/Index.js

@@ -1,5 +1,5 @@
 import React, { useEffect, useState, useRef, useMemo } from 'react';
-import { UnorderedListOutlined, PlusOutlined } from '@ant-design/icons';
+import { UnorderedListOutlined, PlusOutlined, InfoOutlined } from '@ant-design/icons';
 import { Button, Modal, message, Alert, Avatar } from 'antd';
 import { connect } from 'dva';
 import styles from './Index.less';
@@ -512,7 +512,7 @@ function Detail(props) {
   }, [versionList]);
 
   return (
-    <div>
+    <>
       <div className={styles.top}>
         <div>
           <Button type="primary" style={{ marginRight: 20 }} onClick={() => setFlowVisible(true)}>
@@ -573,54 +573,64 @@ function Detail(props) {
           onChange={e => exportExcl(e.target.files)}
         />
       </div>
-      <TimeNode
-        flow={flow}
-        flowDetail={flowDetail}
-        isAuditor={isAuditor}
-        version={version}
-        templateId={templateId}
-        projectId={projectId}
-        setAuditVisible={setAuditVisible}
-      ></TimeNode>
-      <div
-        className={styles.content}
-        style={{
-          // 合同清单先显示附件再显示清单详情
-          flexDirection: version?.TemplateNodeInfo?.flow_id == 9 ? 'column-reverse' : 'column',
-        }}
-      >
-        {/* 判断是否为比对模式 */}
-        {compareList.length == 2 ? (
-          <>
-            <Alert
-              message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
-              type="info"
-            />
-            <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
-          </>
-        ) : (
-          <div className={styles.sheetBox}>
-            {version.id && (
-              <LuckySheet
-                className={styles.sheet}
-                ref={sheetRef}
-                onClickCell={onClickCell}
-                version={version}
-                templateId={templateId}
-                getUser={getUser}
-                onUpdate={onUpdate}
-                onDelSheet={onDelSheet}
+      <div style={{ display: 'flex' }}>
+        <div
+          className={styles.content}
+          style={{
+            width: '100%',
+            // 合同清单先显示附件再显示清单详情
+            flexDirection: version?.TemplateNodeInfo?.flow_id == 9 ? 'column-reverse' : 'column',
+          }}
+        >
+          {/* 判断是否为比对模式 */}
+          {compareList.length == 2 ? (
+            <>
+              <Alert
+                message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
+                type="info"
               />
-            )}
-          </div>
-        )}
+              <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
+            </>
+          ) : (
+            <div className={styles.sheetBox}>
+              {version.id && (
+                <LuckySheet
+                  className={styles.sheet}
+                  ref={sheetRef}
+                  onClickCell={onClickCell}
+                  version={version}
+                  templateId={templateId}
+                  getUser={getUser}
+                  onUpdate={onUpdate}
+                  onDelSheet={onDelSheet}
+                />
+              )}
+            </div>
+          )}
 
-        <FormAndFilesNode
-          formData={version?.ding_schema}
-          excelFileList={excelFileList}
+          <FormAndFilesNode
+            formData={version?.ding_schema}
+            excelFileList={excelFileList}
+            version={version}
+          />
+        </div>
+        <TimeNode
+          flow={flow}
+          flowDetail={flowDetail}
+          isAuditor={isAuditor}
           version={version}
-        />
+          templateId={templateId}
+          projectId={projectId}
+          setAuditVisible={setAuditVisible}
+          stepDirection="vertical"
+          style={{
+            maxWidth: '20%',
+            display: 'inline',
+            marginLeft: '20px',
+          }}
+        ></TimeNode>
       </div>
+
       <CommentContent
         title="单元格沟通记录"
         comment={comment}
@@ -676,6 +686,7 @@ function Detail(props) {
         flow={flow}
         flowDetail={flowDetail}
         version={version}
+        versionList={versionList}
       />
       <VersionModal
         typeOptions={typeOptions}
@@ -694,7 +705,7 @@ function Detail(props) {
         luckysheet={sheetRef}
         templateId={templateId}
       />
-    </div>
+    </>
   );
 }
 

+ 20 - 16
src/pages/Detail/TimeNode.js

@@ -12,7 +12,7 @@ function TimeNode(props) {
   const {
     isAuditor,
     flowDetail,
-
+    style,
     flow,
     versionList,
     version,
@@ -20,7 +20,7 @@ function TimeNode(props) {
     setAuditVisible,
     projectId,
     dispatch,
-
+    stepDirection,
     currentUser,
   } = props;
   const { current, list, active } = flow;
@@ -29,25 +29,29 @@ function TimeNode(props) {
     let str = node?.AuditRoleInfo
       ? `审批人:${node?.AuditRoleInfo.Name || '-'}`
       : `审批人:${node?.AuditorUser.CName || '-'}`;
-    if (node.desc) {
-      return (
+
+    return (
+      <div>
+        {str}
         <div>
-          {str}
-          <div>
-            <Tooltip title={node.desc}>
-              <span style={{ color: '#1A73E8', textDecoration: 'undeline' }}>审批意见</span>
-            </Tooltip>
-          </div>
+          <span style={{ color: '#1A73E8', textDecoration: 'undeline' }}>
+            审批意见:{node.desc || '-'}
+          </span>
         </div>
-      );
-    }
-    return str;
+      </div>
+    );
+
+    // return str;
   };
 
   if (!list || list.FlowNodes?.length != 0) {
     return (
-      <>
-        <Steps current={current} status={active == 0 ? 'error' : 'process'}>
+      <div style={style}>
+        <Steps
+          direction={stepDirection || 'horizontal'}
+          current={current}
+          status={active == 0 ? 'error' : 'process'}
+        >
           {list.FlowNodes.map(item => (
             <Step key={item.id} title={item.node} description={getDescription(item)} />
           ))}
@@ -62,7 +66,7 @@ function TimeNode(props) {
             </Button>
           </div>
         )}
-      </>
+      </div>
     );
   }
   // else {

+ 378 - 240
src/pages/Flow/FlowDetail.json

@@ -18,38 +18,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -580,
+      "x": -789,
       "y": -150,
-      "zIndex": 0,
-      "muti_version": 1,
       "flow_id": 0,
-      "node_type": 0,
-      "count": 0,
-      "role_list": "139"
-    },
-    {
-      "id": "975bf288",
-      "renderKey": "custom-circle",
-      "name": "custom-circle",
-      "label": "方案总审",
-      "width": 90,
-      "height": 90,
-      "ports": {
-        "items": [
-          { "group": "top", "id": "a61170c3" },
-          { "group": "right", "id": "821f59c0" },
-          { "group": "bottom", "id": "17360bc4" },
-          { "group": "left", "id": "15d1b217" }
-        ]
-      },
-      "isCustom": true,
-      "parentKey": "1",
-      "x": -290,
-      "y": -170,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 5,
-      "node_type": 1,
+      "node_type_psr": 0,
       "count": 0,
       "role_list": ""
     },
@@ -70,14 +42,12 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -138,
+      "x": -78,
       "y": -150,
-      "zIndex": 0,
-      "muti_version": 1,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
-      "role_list": "139"
+      "role_list": ""
     },
     {
       "id": "5359e23c",
@@ -96,12 +66,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -335,
+      "x": -578,
       "y": 6,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 9,
-      "node_type": 1,
+      "flow_id": 1,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
@@ -112,7 +80,6 @@
       "label": "采购执行",
       "width": 120,
       "height": 50,
-      "is_seal": 1,
       "ports": {
         "items": [
           { "group": "top", "id": "f71ce55b" },
@@ -123,12 +90,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -138,
+      "x": -264,
       "y": 26,
-      "zIndex": 0,
-      "muti_version": 1,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
       "role_list": ""
     },
@@ -149,14 +114,12 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -580,
+      "x": -789,
       "y": 26,
-      "zIndex": 0,
-      "muti_version": 1,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
-      "role_list": "147"
+      "role_list": ""
     },
     {
       "id": "8c1f18d0",
@@ -175,20 +138,18 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -305,
-      "y": -304,
-      "zIndex": 0,
-      "muti_version": 1,
+      "x": -552,
+      "y": -345,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
-      "role_list": "148"
+      "role_list": ""
     },
     {
       "id": "1aed14d1",
       "renderKey": "custom-rect",
       "name": "custom-rect",
-      "label": "初版PSR",
+      "label": "投标毛利测算",
       "width": 120,
       "height": 50,
       "ports": {
@@ -201,38 +162,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -138,
-      "y": -304,
-      "zIndex": 0,
-      "muti_version": 1,
+      "x": -78,
+      "y": -254,
       "flow_id": 0,
-      "node_type": 0,
-      "count": 0,
-      "role_list": ""
-    },
-    {
-      "id": "4651130e",
-      "renderKey": "custom-circle",
-      "name": "custom-circle",
-      "label": "PSR审批",
-      "width": 90,
-      "height": 90,
-      "ports": {
-        "items": [
-          { "group": "top", "id": "cf1c4df0" },
-          { "group": "right", "id": "1eb352b0" },
-          { "group": "bottom", "id": "83b59198" },
-          { "group": "left", "id": "94f485b5" }
-        ]
-      },
-      "isCustom": true,
-      "parentKey": "1",
-      "x": 356,
-      "y": -324,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 2,
-      "node_type": 1,
+      "node_type_psr": 4,
       "count": 0,
       "role_list": ""
     },
@@ -253,12 +186,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 446,
+      "x": 616,
       "y": -150,
-      "zIndex": 0,
-      "muti_version": 0,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
       "role_list": ""
     },
@@ -279,12 +210,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 621,
-      "y": -150,
-      "zIndex": 0,
-      "muti_version": 1,
+      "x": 616,
+      "y": -556,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
       "role_list": ""
     },
@@ -305,12 +234,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 446,
+      "x": 616,
       "y": 26,
-      "zIndex": 0,
-      "muti_version": 1,
       "flow_id": 0,
-      "node_type": 0,
+      "node_type_psr": 0,
       "count": 0,
       "role_list": ""
     },
@@ -318,7 +245,7 @@
       "id": "3fb8d302",
       "renderKey": "custom-circle",
       "name": "custom-circle",
-      "label": "事业部",
+      "label": "方案总审",
       "width": 90,
       "height": 90,
       "ports": {
@@ -331,12 +258,10 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 308,
+      "x": 325,
       "y": -170,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 7,
-      "node_type": 1,
+      "flow_id": 1,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
@@ -357,43 +282,87 @@
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 173,
+      "x": 111,
       "y": 6,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 8,
-      "node_type": 1,
+      "flow_id": 1,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
     {
-      "id": "2427bf29",
+      "id": "node-1c030340-1f9e-43c1-8499-c588c9b91d9d",
       "renderKey": "custom-circle",
       "name": "custom-circle",
-      "label": "工艺分部经理",
+      "label": "投标毛利测算审批",
       "width": 90,
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "e5a149c4" },
-          { "group": "right", "id": "e1a1ecea" },
-          { "group": "bottom", "id": "6e131e6a" },
-          { "group": "left", "id": "6bbf9ae4" }
+          { "group": "top", "id": "b13bb61c-c1b7-48c1-adc5-7c8faaa148e4" },
+          { "group": "right", "id": "7340a213-4694-46a8-abdb-5dd44d4abbaf" },
+          { "group": "bottom", "id": "197efb3d-74bf-48f9-9881-2611b35ab9ab" },
+          { "group": "left", "id": "0ddbee0a-0814-4a87-a976-601cb6a3f7c4" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "1",
+      "x": -63,
+      "y": -435,
+      "flow_id": 10,
+      "node_type_psr": 1,
+      "count": 0,
+      "role_list": ""
+    },
+    {
+      "id": "node-6a336a93-76a6-42e6-87dc-68e3da1c8c41",
+      "renderKey": "custom-rect",
+      "name": "custom-rect",
+      "label": "投标版PSR",
+      "width": 120,
+      "height": 50,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "0d7185aa-498d-4d8f-8edf-9bdcbec011ad" },
+          { "group": "right", "id": "15c55ebe-d085-4e00-8f2e-c2049ca694cf" },
+          { "group": "bottom", "id": "ca8cab66-e7e3-4381-872f-6dd2b5ae8ea8" },
+          { "group": "left", "id": "978347ae-fed3-4765-bc75-ffd0e22399f4" }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": -425,
-      "y": -224,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 3,
-      "node_type": 1,
+      "x": -78,
+      "y": -556,
+      "flow_id": 0,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
     {
-      "id": "be25fe75",
+      "id": "node-f2a8ea49-52c2-45af-aaf4-80344b36e794",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "工艺分部经理",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "fbfc57f0-2975-419c-a3c1-3a50550035c7" },
+          { "group": "right", "id": "148b50b4-6252-4cb6-b515-27ed224cc360" },
+          { "group": "bottom", "id": "9bc730f5-97ba-4f23-abe7-1d0105d04d89" },
+          { "group": "left", "id": "7eb6eb33-6474-4053-909a-72dabc531cbd" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": -537,
+      "y": -240,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 1,
+      "count": 0
+    },
+    {
+      "id": "node-1d99da2f-3481-476e-92a2-da4a16c6b6e7",
       "renderKey": "custom-circle",
       "name": "custom-circle",
       "label": "电气分部经理",
@@ -401,77 +370,71 @@
       "height": 90,
       "ports": {
         "items": [
-          { "group": "top", "id": "13e4b9ea" },
-          { "group": "right", "id": "ce651308" },
-          { "group": "bottom", "id": "9a0b8942" },
-          { "group": "left", "id": "a705e7ed" }
+          { "group": "top", "id": "bae85e23-7b27-4137-8f08-1b5e68eaf20e" },
+          { "group": "right", "id": "4648f47d-12a5-46a8-a4b1-9f2df6cb56de" },
+          { "group": "bottom", "id": "683748bf-fba2-4849-85eb-42bcb91ce50b" },
+          { "group": "left", "id": "ea341271-cc2f-4c6d-8dfe-68dbb96b54ed" }
         ]
       },
       "isCustom": true,
-      "parentKey": "1",
-      "x": -425,
-      "y": -115,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 4,
-      "node_type": 1,
-      "count": 0,
-      "role_list": ""
+      "parentKey": "custom",
+      "x": -537,
+      "y": -117,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 1,
+      "count": 0
     },
     {
-      "id": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
+      "id": "b5a78b40",
       "renderKey": "custom-circle",
       "name": "custom-circle",
-      "label": "工艺分部经理",
+      "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" }
+          { "group": "top", "id": "8ab6c3f6" },
+          { "group": "right", "id": "205f1437" },
+          { "group": "bottom", "id": "761ad2b5" },
+          { "group": "left", "id": "22d16375" }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 27,
-      "y": -224,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 3,
-      "node_type": 1,
+      "x": 168,
+      "y": -117,
+      "flow_id": 1,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
     {
-      "id": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
+      "id": "5f071153",
       "renderKey": "custom-circle",
       "name": "custom-circle",
-      "label": "电气分部经理",
+      "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" }
+          { "group": "top", "id": "8ab6c3f6" },
+          { "group": "right", "id": "205f1437" },
+          { "group": "bottom", "id": "761ad2b5" },
+          { "group": "left", "id": "22d16375" }
         ]
       },
       "isCustom": true,
       "parentKey": "1",
-      "x": 27,
-      "y": -115,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 4,
-      "node_type": 1,
+      "x": 168,
+      "y": -240,
+      "flow_id": 1,
+      "node_type_psr": 1,
       "count": 0,
       "role_list": ""
     },
     {
-      "id": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
+      "id": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b",
       "renderKey": "custom-circle",
       "name": "custom-circle",
       "label": "方案总审",
@@ -479,60 +442,148 @@
       "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" }
+          { "group": "top", "id": "e5973271-7719-4f5f-87c2-8f8c195e3de4" },
+          { "group": "right", "id": "bb020273-11e3-435b-bb22-86eb68aaffba" },
+          { "group": "bottom", "id": "800f850f-7e47-4deb-8f8f-5d869371507a" },
+          { "group": "left", "id": "8ac4bd2d-e4af-442d-b175-bd0711567bfa" }
         ]
       },
       "isCustom": true,
-      "parentKey": "1",
-      "x": 173,
+      "parentKey": "custom",
+      "x": -264,
       "y": -170,
-      "zIndex": 0,
-      "muti_version": 1,
-      "flow_id": 5,
-      "node_type": 1,
-      "count": 0,
-      "role_list": ""
-    }
-  ],
-  "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}}"
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 1,
+      "count": 0
     },
     {
-      "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}}"
+      "id": "node-4ac6948b-b549-4dc7-ab45-987fcbc35844",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "事业部",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "3fc3d78a-9a63-4a82-b3c7-ddc0dcf0f767" },
+          { "group": "right", "id": "fc6e076d-e6d4-470f-adc1-30162839efe2" },
+          { "group": "bottom", "id": "99adc585-48cf-459e-ba8a-053790ccac86" },
+          { "group": "left", "id": "75c90ab9-9f7c-419d-9608-46607db1a265" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": 471,
+      "y": -170,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 1,
+      "count": 0
     },
     {
-      "id": "5764f3ce:4b4d9fa6-1aed14d1: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": "0322b7c6",
+      "renderKey": "custom-rect",
+      "name": "custom-rect",
+      "label": "合同毛利测算",
+      "width": 120,
+      "height": 50,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "7f8dc65b" },
+          { "group": "right", "id": "9a699e3f" },
+          { "group": "bottom", "id": "d348b56a" },
+          { "group": "left", "id": "47317157" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "1",
+      "x": 616,
+      "y": -277,
+      "flow_id": 0,
+      "node_type_psr": 3, 
+      "count": 0,
+      "role_list": ""
     },
     {
-      "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": "node-19ab31fd-8c23-41a3-bdcb-186751815e1d",
+      "renderKey": "custom-circle",
+      "name": "custom-circle",
+      "label": "签字版PSR审批",
+      "width": 90,
+      "height": 90,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "8846e2ad-8d81-459b-8fcd-001b31073cac" },
+          { "group": "right", "id": "fa1aa4ab-5096-49b8-9ec2-c70f824dd746" },
+          { "group": "bottom", "id": "10e09e8a-b49b-476c-986c-33841b533bc2" },
+          { "group": "left", "id": "d24cfc22-605a-451e-b197-8597cb5b5ed7" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": 631,
+      "y": -435,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 2,
+      "count": 0
     },
     {
-      "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}}"
+      "id": "node-d825c5a0-6077-4d64-a63c-5b3cde59211b",
+      "renderKey": "custom-rect",
+      "name": "custom-rect",
+      "label": "现金流",
+      "width": 120,
+      "height": 50,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "3816dfce-c9a4-4655-9ecb-ecdc6f05fe53" },
+          { "group": "right", "id": "eab92693-4051-449f-b76c-b90587d47f70" },
+          { "group": "bottom", "id": "bb9edb5b-212e-491f-ac79-2bd9096739aa" },
+          { "group": "left", "id": "f65c9954-8273-4f77-9cae-a37cbafe147e" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": -789,
+      "y": 129,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 0,
+      "count": 0
     },
     {
-      "id": "a48131e0:4dee75d9-b57b57c8: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": "node-050b15a7-5bc8-4091-bcc3-d48013eacadd",
+      "renderKey": "custom-rect",
+      "name": "custom-rect",
+      "label": "过程/终版PSR",
+      "width": 120,
+      "height": 50,
+      "ports": {
+        "items": [
+          { "group": "top", "id": "c52f65b7-3fb9-4e68-b039-05ab37414983" },
+          { "group": "right", "id": "fbba2fdc-f26d-488f-aaaf-f7ead51460a9" },
+          { "group": "bottom", "id": "37d3ccbf-3b3d-4e65-bd5a-cdafc81685b8" },
+          { "group": "left", "id": "8751b4b6-25ff-4843-9db0-a6ae4b7258e4" }
+        ]
+      },
+      "isCustom": true,
+      "parentKey": "custom",
+      "x": -789,
+      "y": 232,
+      "zIndex": 10,
+      "flow_id": 0,
+      "node_type_psr": 0,
+      "count": 0
+    }
+  ],
+  "edges": [
+    {
+      "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}}"
     },
     {
       "id": "a48131e0:0f72f2ba-3631eae9:2aae2a71",
@@ -565,90 +616,177 @@
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "b57b57c8:04c81e99-4651130e:1eb352b0",
-      "source": { "cell": "b57b57c8", "port": "04c81e99" },
-      "target": { "cell": "4651130e", "port": "1eb352b0" },
+      "id": "5764f3ce:4b4d9fa6-1aed14d1:d348b56a",
+      "source": { "cell": "5764f3ce", "port": "4b4d9fa6" },
+      "target": { "cell": "1aed14d1", "port": "d348b56a" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "1aed14d1:7f8dc65b-node-1c030340-1f9e-43c1-8499-c588c9b91d9d:197efb3d-74bf-48f9-9881-2611b35ab9ab",
+      "source": { "cell": "1aed14d1", "port": "7f8dc65b" },
+      "target": {
+        "cell": "node-1c030340-1f9e-43c1-8499-c588c9b91d9d",
+        "port": "197efb3d-74bf-48f9-9881-2611b35ab9ab"
+      },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "41561012:92334433-2427bf29:6bbf9ae4",
+      "id": "41561012:92334433-node-f2a8ea49-52c2-45af-aaf4-80344b36e794:7eb6eb33-6474-4053-909a-72dabc531cbd",
       "source": { "cell": "41561012", "port": "92334433" },
-      "target": { "cell": "2427bf29", "port": "6bbf9ae4" },
+      "target": {
+        "cell": "node-f2a8ea49-52c2-45af-aaf4-80344b36e794",
+        "port": "7eb6eb33-6474-4053-909a-72dabc531cbd"
+      },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "41561012:92334433-be25fe75:a705e7ed",
+      "id": "41561012:92334433-node-1d99da2f-3481-476e-92a2-da4a16c6b6e7:ea341271-cc2f-4c6d-8dfe-68dbb96b54ed",
       "source": { "cell": "41561012", "port": "92334433" },
-      "target": { "cell": "be25fe75", "port": "a705e7ed" },
+      "target": {
+        "cell": "node-1d99da2f-3481-476e-92a2-da4a16c6b6e7",
+        "port": "ea341271-cc2f-4c6d-8dfe-68dbb96b54ed"
+      },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "2427bf29:e1a1ecea-975bf288:15d1b217",
-      "source": { "cell": "2427bf29", "port": "e1a1ecea" },
-      "target": { "cell": "975bf288", "port": "15d1b217" },
+      "id": "5764f3ce:ce88d7e2-5f071153:22d16375",
+      "source": { "cell": "5764f3ce", "port": "ce88d7e2" },
+      "target": { "cell": "5f071153", "port": "22d16375" },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "be25fe75:ce651308-975bf288:15d1b217",
-      "source": { "cell": "be25fe75", "port": "ce651308" },
-      "target": { "cell": "975bf288", "port": "15d1b217" },
+      "id": "5764f3ce:ce88d7e2-b5a78b40:22d16375",
+      "source": { "cell": "5764f3ce", "port": "ce88d7e2" },
+      "target": { "cell": "b5a78b40", "port": "22d16375" },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "975bf288:821f59c0-5764f3ce:c29d7b43",
-      "source": { "cell": "975bf288", "port": "821f59c0" },
+      "id": "5f071153:205f1437-3fb8d302:22d16375",
+      "source": { "cell": "5f071153", "port": "205f1437" },
+      "target": { "cell": "3fb8d302", "port": "22d16375" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "b5a78b40:205f1437-3fb8d302:22d16375",
+      "source": { "cell": "b5a78b40", "port": "205f1437" },
+      "target": { "cell": "3fb8d302", "port": "22d16375" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-f2a8ea49-52c2-45af-aaf4-80344b36e794:148b50b4-6252-4cb6-b515-27ed224cc360-node-9e654259-45f9-4e28-b39a-cf3934fa4f5b:8ac4bd2d-e4af-442d-b175-bd0711567bfa",
+      "source": {
+        "cell": "node-f2a8ea49-52c2-45af-aaf4-80344b36e794",
+        "port": "148b50b4-6252-4cb6-b515-27ed224cc360"
+      },
+      "target": {
+        "cell": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b",
+        "port": "8ac4bd2d-e4af-442d-b175-bd0711567bfa"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-1d99da2f-3481-476e-92a2-da4a16c6b6e7:4648f47d-12a5-46a8-a4b1-9f2df6cb56de-node-9e654259-45f9-4e28-b39a-cf3934fa4f5b:8ac4bd2d-e4af-442d-b175-bd0711567bfa",
+      "source": {
+        "cell": "node-1d99da2f-3481-476e-92a2-da4a16c6b6e7",
+        "port": "4648f47d-12a5-46a8-a4b1-9f2df6cb56de"
+      },
+      "target": {
+        "cell": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b",
+        "port": "8ac4bd2d-e4af-442d-b175-bd0711567bfa"
+      },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b:bb020273-11e3-435b-bb22-86eb68aaffba-5764f3ce:c29d7b43",
+      "source": {
+        "cell": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b",
+        "port": "bb020273-11e3-435b-bb22-86eb68aaffba"
+      },
       "target": { "cell": "5764f3ce", "port": "c29d7b43" },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "5764f3ce:ce88d7e2-node-186a9d31-0bd3-4b36-b61f-6b5380c824db:6d880b9d-7d7e-4357-94dd-caf7d73b5f80",
-      "source": { "cell": "5764f3ce", "port": "ce88d7e2" },
+      "id": "node-1c030340-1f9e-43c1-8499-c588c9b91d9d:b13bb61c-c1b7-48c1-adc5-7c8faaa148e4-node-6a336a93-76a6-42e6-87dc-68e3da1c8c41:ca8cab66-e7e3-4381-872f-6dd2b5ae8ea8",
+      "source": {
+        "cell": "node-1c030340-1f9e-43c1-8499-c588c9b91d9d",
+        "port": "b13bb61c-c1b7-48c1-adc5-7c8faaa148e4"
+      },
       "target": {
-        "cell": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
-        "port": "6d880b9d-7d7e-4357-94dd-caf7d73b5f80"
+        "cell": "node-6a336a93-76a6-42e6-87dc-68e3da1c8c41",
+        "port": "ca8cab66-e7e3-4381-872f-6dd2b5ae8ea8"
       },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "5764f3ce:ce88d7e2-node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8:8637b869-7924-416a-b938-30a7ca932901",
-      "source": { "cell": "5764f3ce", "port": "ce88d7e2" },
+      "id": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b:e5973271-7719-4f5f-87c2-8f8c195e3de4-8c1f18d0:b3dfbc16",
+      "source": {
+        "cell": "node-9e654259-45f9-4e28-b39a-cf3934fa4f5b",
+        "port": "e5973271-7719-4f5f-87c2-8f8c195e3de4"
+      },
+      "target": { "cell": "8c1f18d0", "port": "b3dfbc16" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "3fb8d302:205f1437-node-4ac6948b-b549-4dc7-ab45-987fcbc35844:75c90ab9-9f7c-419d-9608-46607db1a265",
+      "source": { "cell": "3fb8d302", "port": "205f1437" },
       "target": {
-        "cell": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
-        "port": "8637b869-7924-416a-b938-30a7ca932901"
+        "cell": "node-4ac6948b-b549-4dc7-ab45-987fcbc35844",
+        "port": "75c90ab9-9f7c-419d-9608-46607db1a265"
       },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"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",
+      "id": "node-4ac6948b-b549-4dc7-ab45-987fcbc35844:fc6e076d-e6d4-470f-adc1-30162839efe2-a48131e0:bac7962b",
       "source": {
-        "cell": "node-186a9d31-0bd3-4b36-b61f-6b5380c824db",
-        "port": "e134d65d-a197-4116-ad74-f47dbbb727d1"
+        "cell": "node-4ac6948b-b549-4dc7-ab45-987fcbc35844",
+        "port": "fc6e076d-e6d4-470f-adc1-30162839efe2"
       },
+      "target": { "cell": "a48131e0", "port": "bac7962b" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "a48131e0:3ca1320c-0322b7c6:d348b56a",
+      "source": { "cell": "a48131e0", "port": "3ca1320c" },
+      "target": { "cell": "0322b7c6", "port": "d348b56a" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "0322b7c6:7f8dc65b-node-19ab31fd-8c23-41a3-bdcb-186751815e1d:10e09e8a-b49b-476c-986c-33841b533bc2",
+      "source": { "cell": "0322b7c6", "port": "7f8dc65b" },
       "target": {
-        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
-        "port": "2408c946-a670-48b5-a676-d882946b8e36"
+        "cell": "node-19ab31fd-8c23-41a3-bdcb-186751815e1d",
+        "port": "10e09e8a-b49b-476c-986c-33841b533bc2"
       },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"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",
+      "id": "node-19ab31fd-8c23-41a3-bdcb-186751815e1d:8846e2ad-8d81-459b-8fcd-001b31073cac-b57b57c8:17ff5fe6",
       "source": {
-        "cell": "node-c5171e2d-1cd8-4019-83dc-9f2ed0cab6e8",
-        "port": "6316d87e-2eb3-4ff6-bd8e-0cfd11bff4ce"
+        "cell": "node-19ab31fd-8c23-41a3-bdcb-186751815e1d",
+        "port": "8846e2ad-8d81-459b-8fcd-001b31073cac"
       },
+      "target": { "cell": "b57b57c8", "port": "17ff5fe6" },
+      "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
+    },
+    {
+      "id": "5216c5dc:188c9b68-node-d825c5a0-6077-4d64-a63c-5b3cde59211b:3816dfce-c9a4-4655-9ecb-ecdc6f05fe53",
+      "source": { "cell": "5216c5dc", "port": "188c9b68" },
       "target": {
-        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
-        "port": "2408c946-a670-48b5-a676-d882946b8e36"
+        "cell": "node-d825c5a0-6077-4d64-a63c-5b3cde59211b",
+        "port": "3816dfce-c9a4-4655-9ecb-ecdc6f05fe53"
       },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {
-      "id": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862:1ab6b2a4-dccd-41e9-83c6-d1642c9ad844-3fb8d302:22d16375",
+      "id": "node-d825c5a0-6077-4d64-a63c-5b3cde59211b:bb9edb5b-212e-491f-ac79-2bd9096739aa-node-050b15a7-5bc8-4091-bcc3-d48013eacadd:c52f65b7-3fb9-4e68-b039-05ab37414983",
       "source": {
-        "cell": "node-2b3fc359-de49-4f9d-adb5-4eb70b6ba862",
-        "port": "1ab6b2a4-dccd-41e9-83c6-d1642c9ad844"
+        "cell": "node-d825c5a0-6077-4d64-a63c-5b3cde59211b",
+        "port": "bb9edb5b-212e-491f-ac79-2bd9096739aa"
+      },
+      "target": {
+        "cell": "node-050b15a7-5bc8-4091-bcc3-d48013eacadd",
+        "port": "c52f65b7-3fb9-4e68-b039-05ab37414983"
       },
-      "target": { "cell": "3fb8d302", "port": "22d16375" },
       "attr": "{\"line\":{\"stroke\":\"#A2B1C3\",\"targetMarker\":{\"name\":\"block\",\"width\":12,\"height\":8},\"strokeDasharray\":[0,0],\"strokeWidth\":1}}"
     },
     {

+ 85 - 0
src/pages/Psr/index.js

@@ -0,0 +1,85 @@
+import { queryRecordSheet } from '@/services/boom';
+import LuckySheet from '../Detail/LuckySheet';
+import react, { useRef } from 'react';
+import LuckyExcel from 'luckyexcel';
+import { Button, message } from 'antd';
+
+const TEMPLATE_URL =
+  'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/bom/635/%E5%90%88%E5%90%8C%E6%96%87%E4%BB%B6/%E6%8A%95%E6%A0%87%E6%A8%A1%E6%9D%BF.xlsx';
+const TEMPLATE_URL2 = 'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/public/bom/psr.xlsx';
+
+function Index(props) {
+  const { versionId = 2418 } = props;
+
+  const sheetRef = useRef();
+  const luckysheetRef = useRef();
+
+  const uploadExcelByUrl = type => {
+    LuckyExcel.transformExcelToLuckyByUrl(
+      type == 1 ? TEMPLATE_URL : TEMPLATE_URL2,
+      '模板.xlsx',
+      async (exportJson, luckysheetfile) => {
+        let record = await getExcel(versionId);
+        console.log(record);
+
+        luckysheetRef.current.destroy();
+
+        luckysheetRef.current.create({
+          lang: 'zh',
+          showinfobar: false,
+          showstatisticBar: false,
+          data: [...exportJson.sheets, ...record],
+          hook: {
+            cellMousedown: (cell, position, sheet) => {
+              console.log(cell, position, sheet);
+            },
+            cellUpdated: () => {
+              luckysheetRef.current.refreshFormula();
+            },
+          },
+        });
+      }
+    );
+  };
+
+  const handleLoad = () => {
+    let contentWindow = sheetRef.current.contentWindow;
+    luckysheetRef.current = contentWindow.luckysheet;
+  };
+
+  return (
+    <div>
+      <Button type="primary" onClick={() => uploadExcelByUrl(1)}>
+        导入投标投标
+      </Button>
+      <Button type="primary" onClick={() => uploadExcelByUrl(2)}>
+        导入合同模板
+      </Button>
+
+      <iframe
+        style={{
+          width: '100%',
+          height: '80vh',
+        }}
+        ref={sheetRef}
+        onLoad={handleLoad}
+        src="/luckysheet.html"
+      ></iframe>
+    </div>
+  );
+}
+
+async function getExcel(gridKey) {
+  var formData = new FormData();
+  formData.append('gridKey', gridKey);
+  let res = await fetch(
+    `/api/v1/purchase/record/sheet?gridKey=${gridKey}&JWT-TOKEN=${getToken()}`,
+    {
+      method: 'POST',
+      body: formData,
+    }
+  ).then(response => response.text());
+  return JSON.parse(JSON.parse(res));
+}
+
+export default Index;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/pages/Temp/excel_json.json


+ 109 - 0
src/pages/Temp/index.js

@@ -0,0 +1,109 @@
+import { queryRecordSheet } from '@/services/boom';
+import LuckySheet from '../Detail/LuckySheet';
+import react, { useRef } from 'react';
+import LuckyExcel from 'luckyexcel';
+import { Button, message } from 'antd';
+import { getToken } from '@/utils/utils';
+import moment from 'moment';
+
+const TEMPLATE_URL =
+  'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/bom/635/%E5%90%88%E5%90%8C%E6%96%87%E4%BB%B6/%E6%8A%95%E6%A0%87%E6%A8%A1%E6%9D%BF.xlsx';
+
+const TEMPLATE_URL2 = 'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/public/bom/psr.xlsx';
+
+function Index(props) {
+  const { versionId = 2376 } = props;
+
+  const sheetRef = useRef();
+  const luckysheetRef = useRef();
+
+  const uploadExcelByUrl = type => {
+    LuckyExcel.transformExcelToLuckyByUrl(
+      type == 1 ? TEMPLATE_URL : TEMPLATE_URL2,
+      '模板.xlsx',
+      async (exportJson, luckysheetfile) => {
+        // if (type == 2) initData(exportJson.sheets);
+        let [record] = await getExcel(versionId);
+
+        let len = exportJson.sheets.length;
+        record.order = len - 1;
+        record.index = len;
+        record.status = '0';
+
+        const data = [...exportJson.sheets, record];
+        console.log(data);
+
+        luckysheetRef.current.destroy();
+
+        luckysheetRef.current.create({
+          data,
+          lang: 'zh',
+          showinfobar: false,
+          showstatisticBar: false,
+          hook: {
+            cellMousedown: (cell, position, sheet) => {
+              console.log(cell, position, sheet);
+            },
+            cellUpdated: () => {
+              luckysheetRef.current.refreshFormula();
+            },
+          },
+        });
+      }
+    );
+  };
+
+  const handleLoad = () => {
+    let contentWindow = sheetRef.current.contentWindow;
+    luckysheetRef.current = contentWindow.luckysheet;
+  };
+
+  const initData = sheets => {
+    let r = 5,
+      c = 12;
+    // let dateCell = sheets[3].celldata.find(item => item.r == 1 && item.c == 3);
+    let timer = sheets[3].celldata.filter(item => item.r == r && item.c >= c);
+    timer.forEach((item, index) => {
+      const cell = item.v;
+      
+      cell.f = `=EDATE(D2,${index})`;
+    });
+    console.log(timer);
+  };
+
+  return (
+    <div>
+      <Button type="primary" style={{ marginRight: 20 }} onClick={() => uploadExcelByUrl(1)}>
+        导入投标投标
+      </Button>
+      <Button type="primary" onClick={() => uploadExcelByUrl(2)}>
+        导入合同模板
+      </Button>
+
+      <iframe
+        style={{
+          width: '100%',
+          height: '80vh',
+        }}
+        ref={sheetRef}
+        onLoad={handleLoad}
+        src="/luckysheet.html"
+      ></iframe>
+    </div>
+  );
+}
+
+async function getExcel(gridKey) {
+  var formData = new FormData();
+  formData.append('gridKey', gridKey);
+  let res = await fetch(
+    `/api/v1/purchase/record/sheet?gridKey=${gridKey}&JWT-TOKEN=${getToken()}`,
+    {
+      method: 'POST',
+      body: formData,
+    }
+  ).then(response => response.text());
+  return JSON.parse(JSON.parse(res));
+}
+
+export default Index;

+ 2 - 1
src/services/boom.js

@@ -241,7 +241,7 @@ export async function queryBoomFlowDetail(params) {
       ...item,
       id: item.node_id,
       renderKey: item.render_key,
-      zIndex: item.z_index,
+      zIndex: 1,
       isCustom: !!item.is_custom,
       ports: JSON.parse(item.ports || '{}'),
     };
@@ -261,6 +261,7 @@ export async function queryBoomFlowDetail(params) {
         cell: item.target_cell,
         port: item.target_port,
       },
+      zIndex:0
     };
     try {
       edge.attrs = item.attr ? JSON.parse(item.attr) : attrs;

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio