Pārlūkot izejas kodu

Squashed commit of the following:
merge develop
commit 297c9b753fb568c590b1ef078b80b27121f177af
Author: Renxy <18510891294@163.com>
Date: Thu Jun 15 13:55:39 2023 +0800

修改合同管理点击加号查看子合同导致页码不对

commit 95d8668c565b7ace271a657f56189a44398a738b
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 18:01:41 2023 +0800

修改测试cc_list报错问题

commit 0afedb446622c1e1ece45ef7a18ef54ce17a67fb
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 17:37:34 2023 +0800

修改审批流配置时一个审批节点多选人审批

commit 07d9ec5badf6402f6ec309f3e18e234143af1565
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 17:28:14 2023 +0800

Squashed commit of the following:
合并Oa审批相关修改
commit 5ebec549350be80379fa3a62b9e84436fddce9f9
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 17:27:17 2023 +0800

删除log

commit f4dc257905af71235bba619ed4d80820e07efb5b
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 17:24:50 2023 +0800

审批节点支持选择多人依次审批

commit f87dbf6acfc4f5feff9c913272a2d381bdb4f080
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 13:44:42 2023 +0800

Squashed commit of the following:
合并develop
commit bc3dfed8bc8dfbe4e5b45676fe92b01b6de35b43
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 13:41:02 2023 +0800

合同管理兼容旧审批流程

commit ea7c41df6b110fef53edc8e5cea0001f5cb3be1e
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 11:14:22 2023 +0800

抄送人修改

commit bc3dfed8bc8dfbe4e5b45676fe92b01b6de35b43
Author: Renxy <18510891294@163.com>
Date: Tue Jun 13 13:41:02 2023 +0800

合同管理兼容旧审批流程

commit 70e9acd8616204ad9e0a48ce2bf28723acd2c0f7
Author: Renxy <18510891294@163.com>
Date: Mon Jun 12 11:38:29 2023 +0800

修改合同管理撤回/添加修改密码

commit 14c5daaa89549fa24d0503fec213a6adccb3839c
Author: Renxy <18510891294@163.com>
Date: Tue Jun 6 18:28:10 2023 +0800

修改合同走OA审批流程

commit f7a9b85def9165c9d3c73009b8426e0d12dcb755
Author: Renxy <18510891294@163.com>
Date: Mon Jun 5 17:05:21 2023 +0800

修改供应商管理

commit 384b2efc8b51a13875180a12edecb67ba9a79c29
Author: Renxy <18510891294@163.com>
Date: Fri Jun 2 18:00:54 2023 +0800

update

commit 538958cebfb957ab52b95ed4e9e3627ea4e1e6ff
Author: Renxy <18510891294@163.com>
Date: Fri Jun 2 17:59:48 2023 +0800

修改合同预览/修改合同相关

commit e9fe47ccd098e11b5cf026f0b9a8a151a9863850
Merge: a9c0fb8 e14b706
Author: xjj <645007605@qq.com>
Date: Wed May 31 18:26:59 2023 +0800

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

commit a9c0fb85e00f662fc0371ce18329e9b75f217683
Author: xjj <645007605@qq.com>
Date: Wed May 31 18:26:54 2023 +0800

加签

commit e14b706d41c53066ab6c694d3e1fc86ab1ed4e45
Merge: 1f42e19 e3c5635
Author: Renxy <18510891294@163.com>
Date: Wed May 31 11:22:43 2023 +0800

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

commit 1f42e196c5703cc4d4ee9a6ea676c0925547e1e9
Author: Renxy <18510891294@163.com>
Date: Wed May 31 11:22:34 2023 +0800

update

commit 46cb4fe1081fa498603abf808e83adafa1606959
Author: Renxy <18510891294@163.com>
Date: Wed May 31 11:22:01 2023 +0800

合同详情里面添加预览按钮

commit e3c563564c937c19c06bada3620c6eb92c1ef361
Merge: b920297 4eba9cf
Author: xjj <645007605@qq.com>
Date: Tue May 30 15:08:41 2023 +0800

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

commit b9202974083f2f6c59b0c422ef41f15e9b70ff09
Author: xjj <645007605@qq.com>
Date: Tue May 30 15:08:29 2023 +0800

增加或条件

commit 4eba9cf99126d93ee283dfb69b1ec78a323246df
Merge: 3a93b15 0860bbd
Author: Renxy <18510891294@163.com>
Date: Thu May 18 13:45:47 2023 +0800

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

commit 3a93b15457311d57c8a9f22b7403a4a1c52f3827
Author: Renxy <18510891294@163.com>
Date: Thu May 18 13:45:38 2023 +0800

修改合同审核

commit 0860bbd4fd51b4897df483facf318df5638bca9b
Author: XuZinan <tony.xu121508b2@yahoo.com>
Date: Sat May 13 18:00:45 2023 +0800

审批流类型 合同审批改为合同归档审批

# Conflicts:
# src/pages/ContractManager/component/Modal.jsx
# src/pages/ContractManager/index.jsx
# src/pages/Profile/approve.js

Renxy 2 gadi atpakaļ
vecāks
revīzija
f73606ab9c

+ 8 - 7
.umirc.ts

@@ -17,8 +17,8 @@ export default defineConfig({
   proxy: {
     '/api': {
       // target: 'http://47.96.12.136:8888/',
-      // target: 'http://47.96.12.136:8895/',
-      target: 'http://120.55.44.4:8902/',
+      target: 'http://47.96.12.136:8895/',
+      // target: 'http://120.55.44.4:8902/',
       changeOrigin: true,
     },
   },
@@ -89,11 +89,12 @@ export default defineConfig({
     //   path: '/access',
     //   component: './Access',
     // },
-    // {
-    //   name: 'CRUD 示例',
-    //   path: '/table',
-    //   component: './Table',
-    // },
+    {
+      name: '修改密码',
+      path: '/safety',
+      component: './UserCenter',
+      hideInMenu: true,
+    },
     {
       name: '登录',
       path: '/login',

+ 3 - 3
src/components/DDComponents/NumberField/index.js

@@ -8,9 +8,9 @@ function NumberField(props) {
     <InputNumber
       style={{ width: '100%' }}
       disabled={disabled}
-      formatter={value => `${value}${unit || ''}`}
-      onChange={e => {
-        onChange?.(String(e));
+      formatter={(value) => `${value}${unit || ''}`}
+      onChange={(e) => {
+        onChange?.(e ? String(e) : 0);
       }}
     />
   );

+ 4 - 0
src/components/FileViewerNew/index.js

@@ -2,6 +2,9 @@ import React, { useState, useEffect } from 'react';
 import FileViewer from 'react-file-viewer';
 import { Modal, Table } from 'antd';
 
+//data 为数组传 [{name:'', type:'传文件类型(jpg/png/xlsx等)' url:''}]
+// data 为单个文件传 [{name:'', type:'传描述信息', url:''}]
+
 const FileViewerModal = ({ data, visible, onCancel, downloadFile }) => {
   const [img, setImg] = useState();
   useEffect(() => {
@@ -39,6 +42,7 @@ const FileViewerModal = ({ data, visible, onCancel, downloadFile }) => {
   const renderListContent = () => {
     const columns = [
       { title: '文档名称', dataIndex: 'name' },
+      { title: '文件类型', dataIndex: 'type' },
       {
         title: '操作',
         render: (_, record) => (

+ 2 - 1
src/components/Flow/components/judgeComponent/index.tsx

@@ -175,6 +175,7 @@ const RenderJudge = (props: any) => {
             <Select
               options={JudgeOptions}
               defaultValue={judge?.values[0]}
+              style={{ width: '100%' }}
               onChange={(value: number) => {
                 let newCondition: Condition = null;
                 if (judge && judge.values && judge.values.length > 0) {
@@ -271,7 +272,7 @@ const RenderJudge = (props: any) => {
         );
         break;
     }
-    return component;
+    return <div style={{ margin: "10px 0" }}>{component}</div>;
   };
 
   return <>{formData.map((item) => RenderComp(item))}</>;

+ 3 - 5
src/components/Flow/index.tsx

@@ -95,16 +95,14 @@ export const Demo: React.FC<IProps> = (props) => {
               const node = {
                 id: curNode.id,
                 type: curNode.type,
+                formItems: '',
                 //条件节点
-                formItems:
-                  curNode.type == TYPE.JUDGE && !curNode.formItems
-                    ? '[]'
-                    : curNode.formItems,
+                formItemsOr: curNode.formItemsOr || [],
                 priority: curNode.priority,
                 //审批节点
                 initiator:
                   curNode.type == TYPE.INITIATOR ? curNode.initiator : null,
-                audits: curNode.type == TYPE.AUDIT ? curNode.audits : null,
+                audits: curNode.audits,
                 children: children,
               };
               return node;

+ 1 - 1
src/components/Flow/node/FlowFormPanel.tsx

@@ -8,7 +8,7 @@ const CustomFlowchartFormPanel = () => {
   return (
     <FlowchartFormPanel
       show={true}
-      position={{ width: 240, top: 40, bottom: 0, right: 0 }}
+      position={{ width: 320, top: 40, bottom: 0, right: 0 }}
       controlMapService={controlMapService}
       formSchemaService={formSchemaService}
     ></FlowchartFormPanel>

+ 10 - 8
src/components/Flow/node/auditNode/index.tsx

@@ -50,7 +50,7 @@ const CustomRect = (props: any) => {
       }
       return name;
     };
-    if (type != TYPE.AUDIT) {
+    if (type == TYPE.INITIATOR) {
       if (initiator?.length > 0) {
         const list = initiator
           .map((item: any) => {
@@ -68,8 +68,10 @@ const CustomRect = (props: any) => {
             return roleList.find((item: any) => item.ID == audits[0].value)
               ?.Name;
           case IDTYPE.USER:
-            return userList.find((item: any) => item.ID == audits[0].value)
-              ?.CName;
+            const nameList = audits.map((item: any) => {
+              return userList.find((user: any) => user.ID == item.value)?.CName;
+            });
+            return nameList.join('、');
           case IDTYPE.LEADER:
             return '部门主管';
         }
@@ -82,26 +84,26 @@ const CustomRect = (props: any) => {
   // const type: TYPE = 0;
   const titleDom = () => {
     let color = COLOR.AUDIT;
-    let text = label == '动作节点' ? TITLETEXT.AUDIT : label;
+    let text = label;
     switch (type) {
       case TYPE.AUDIT:
         color = COLOR.AUDIT;
-        text = TITLETEXT.AUDIT;
+        text = label !== '动作节点' ? label : TITLETEXT.AUDIT;
         break;
       case TYPE.INITIATOR:
         color = COLOR.INITIATOR;
-        text = TITLETEXT.INITIATOR;
+        text = label !== '动作节点' ? label : TITLETEXT.INITIATOR;
         break;
       case TYPE.COPYMAN:
         color = COLOR.COPYMAN;
-        text = TITLETEXT.COPYMAN;
+        text = label !== '动作节点' ? label : TITLETEXT.COPYMAN;
         break;
     }
     return (
       <div
         style={{
           width: '100%',
-          height: `${fontSize + 16}px`,
+          height: '22px',
           paddingLeft: '6px',
           backgroundColor: color,
           color: 'white',

+ 75 - 13
src/components/Flow/node/auditNode/mapServe.tsx

@@ -51,6 +51,7 @@ export interface IConfig {
   process_code?: string;
   type: TYPE;
   initiator: {
+    label: string; //描述
     type: string;
     value: number;
     origin?: string | number;
@@ -58,10 +59,12 @@ export interface IConfig {
   }[];
   //审批人目前只支持单选角色或者单选人
   audits: {
+    label: string; //描述
     type: string;
     value: number;
     origin?: string | number;
     name?: string;
+    is_cc: number;
   }[];
 }
 
@@ -123,7 +126,6 @@ const Component = (props: any) => {
     console.log(bool);
     setIsRole(bool);
   }, []);
-  console.log('===================', nodeConfig);
 
   const handleTreeChange = (values: (string | number)[]) => {
     const newValues = values.map((cur) => {
@@ -134,7 +136,7 @@ const Component = (props: any) => {
           origin: cur,
         };
       } else {
-        return { type: IDTYPE.DEP, value: cur, origin: cur };
+        return { type: IDTYPE.DEP, value: cur, origin: cur, is_cc: 1 };
       }
     });
     onNodeConfigChange('initiator', newValues);
@@ -159,12 +161,21 @@ const Component = (props: any) => {
             <label>审批人</label>
             <Select
               showSearch
+              mode="multiple"
               style={{ width: '100%' }}
               value={nodeConfig.audits?.map((item) => item.value)}
               onChange={(value) => {
-                onNodeConfigChange('audits', [
-                  { type: IDTYPE.USER, value: Number(value) },
-                ]);
+                const list = value.map((id) => {
+                  return {
+                    type: IDTYPE.USER,
+                    label:
+                      nodeConfig.label == '动作节点'
+                        ? '抄送人'
+                        : nodeConfig.label,
+                    value: Number(id),
+                  };
+                });
+                onNodeConfigChange('audits', list);
               }}
               filterOption={(input, option) =>
                 option.props.children.indexOf(input) >= 0
@@ -191,7 +202,14 @@ const Component = (props: any) => {
               }
               onChange={(value) => {
                 onNodeConfigChange('audits', [
-                  { type: IDTYPE.ROLE, value: Number(value) },
+                  {
+                    type: IDTYPE.ROLE,
+                    label:
+                      nodeConfig.label == '动作节点'
+                        ? '审批人'
+                        : nodeConfig.label,
+                    value: Number(value),
+                  },
                 ]);
               }}
             >
@@ -215,7 +233,14 @@ const Component = (props: any) => {
               }
               onChange={(value) => {
                 onNodeConfigChange('audits', [
-                  { type: IDTYPE.LEADER, value: Number(value) },
+                  {
+                    type: IDTYPE.LEADER,
+                    label:
+                      nodeConfig.label == '动作节点'
+                        ? '审批人'
+                        : nodeConfig.label,
+                    value: Number(value),
+                  },
                 ]);
               }}
             />
@@ -232,7 +257,13 @@ const Component = (props: any) => {
           label="标题"
           value={nodeConfig.label}
           onChange={(value) => {
-            onNodeConfigChange('label', value);
+            onNodeConfigChange('', {
+              label: value,
+              audits:
+                nodeConfig?.audits?.length > 0
+                  ? [{ ...(nodeConfig?.audits[0] || []), label: value }]
+                  : [],
+            });
           }}
         />
         <SelectField
@@ -297,12 +328,9 @@ const Component = (props: any) => {
             }}
           />
         </div>
-        {nodeConfig.type != TYPE.AUDIT && (
+        {nodeConfig.type == TYPE.INITIATOR && (
           <div className="group">
-            <label>
-              {typeOption.find((item) => item.value == nodeConfig.type)
-                ?.label || '-'}
-            </label>
+            <label>发起人</label>
             <TreeSelect
               showSearch
               multiple
@@ -337,6 +365,40 @@ const Component = (props: any) => {
           </div>
         )}
       </div>
+      {nodeConfig.type == TYPE.COPYMAN && (
+        <div className="group">
+          <label>抄送人:</label>
+          <Select
+            showSearch
+            mode="multiple"
+            style={{ width: '80%' }}
+            value={nodeConfig.audits?.map((item) => item.value)}
+            onChange={(value) => {
+              const list = value.map((id) => {
+                return {
+                  type: IDTYPE.USER,
+                  label:
+                    nodeConfig.label == '动作节点'
+                      ? '抄送人'
+                      : nodeConfig.label,
+                  value: Number(id),
+                  is_cc: 1,
+                };
+              });
+              onNodeConfigChange('audits', list);
+            }}
+            filterOption={(input, option) =>
+              option?.props?.children.indexOf(input) >= 0
+            }
+          >
+            {(userList || []).map((item) => (
+              <Option key={item.ID} value={item.ID}>
+                {item.CName}
+              </Option>
+            ))}
+          </Select>
+        </div>
+      )}
 
       {/* <Button style={{ marginTop: 20 }} type="primary" onClick={onSave}>
         保存

+ 78 - 62
src/components/Flow/node/judgeNode/index.tsx

@@ -8,16 +8,25 @@ import {
   SiginSmallOptions,
 } from '../../components/judgeComponent';
 import { connect } from 'umi';
+import { Card } from 'antd';
 export { judgeServe };
 
 const JudgeRect = (props: any) => {
   const { size = { width: 130, height: 50 }, data, depUserTree } = props;
   const { width, height } = size;
-  const { label, stroke, fill, fontFill, fontSize, type, priority, formItems } =
-    data;
+  const {
+    label,
+    stroke,
+    fill,
+    fontFill,
+    fontSize,
+    type,
+    priority,
+    formItemsOr,
+  } = data;
 
   const contentText = useMemo(() => {
-    let text = [];
+    let allText: any[] = [];
     const getName = (id: any, data: any) => {
       let name = '';
       for (let i = 0; i < data.length; i++) {
@@ -32,56 +41,74 @@ const JudgeRect = (props: any) => {
       return name;
     };
 
-    if (formItems) {
-      let data: FormItem[] = JSON.parse(formItems);
-      data.forEach((item: FormItem) => {
-        let judge = item.judge;
-        const label: String = item.props.label;
-        switch (judge?.type) {
-          case ComponentName.Inner:
-            const list = judge?.values
-              ?.map((item) => {
-                return getName(item.origin, depUserTree);
-              })
-              .filter((item) => item);
-            text.push('发起人属于:' + list?.join('或'));
-            break;
-          case ComponentName.Number:
-            const type: Number = judge?.values?.[0];
-            const condition = judge.condition;
-            if (!condition) break;
-            if (type != 6) {
-              let JudgeLabel = JudgeOptions.find(
-                (item) => item.value == type,
-              )?.label;
+    if (formItemsOr?.length > 0) {
+      formItemsOr.forEach((formItems: string, index: number) => {
+        let text: any[] = [];
+        let data: FormItem[] = JSON.parse(formItems);
+        data.forEach((item: FormItem) => {
+          let judge = item.judge;
+          const label: String = item.props.label;
+          switch (judge?.type) {
+            case ComponentName.Inner:
+              const list = judge?.values
+                ?.map((item) => {
+                  return getName(item.origin, depUserTree);
+                })
+                .filter((item) => item);
+              text.push('发起人属于:' + list?.join('或'));
+              break;
+            case ComponentName.Number:
+              const type: Number = judge?.values?.[0];
+              const condition = judge.condition;
+              if (!condition) break;
+              if (type != 6) {
+                let JudgeLabel = JudgeOptions.find(
+                  (item) => item.value == type,
+                )?.label;
 
-              text.push(`${label} ${JudgeLabel} ${condition.smallValue}`);
-            } else {
-              const { smallSign, smallValue, bigSign, bigValue } = condition;
-              if (!smallSign || !smallValue || !bigSign || !bigValue) break;
-              const getSigin = (sigin: Number) =>
-                SiginOptions.find((item) => item.value == sigin)?.label;
-              const getSmallSigin = (sigin: Number) =>
-                SiginSmallOptions.find((item) => item.value == sigin)?.label;
+                text.push(`${label} ${JudgeLabel} ${condition.smallValue}`);
+              } else {
+                const { smallSign, smallValue, bigSign, bigValue } = condition;
+                if (!smallSign || !smallValue || !bigSign || !bigValue) break;
+                const getSigin = (sigin: Number) =>
+                  SiginOptions.find((item) => item.value == sigin)?.label;
+                const getSmallSigin = (sigin: Number) =>
+                  SiginSmallOptions.find((item) => item.value == sigin)?.label;
 
-              text.push(
-                `${smallValue} ${getSmallSigin(smallSign)} ${label} ${getSigin(
-                  bigSign,
-                )} ${bigValue} `,
-              );
-            }
-            break;
-          case ComponentName.Select:
-          case ComponentName.MultiSelect:
-            const values = judge.values;
-            text.push(`${label} ${values?.join(' 且 ')}`);
-            break;
+                text.push(
+                  `${smallValue} ${getSmallSigin(
+                    smallSign,
+                  )} ${label} ${getSigin(bigSign)} ${bigValue} `,
+                );
+              }
+              break;
+            case ComponentName.Select:
+            case ComponentName.MultiSelect:
+              const values = judge.values;
+              text.push(`${label} ${values?.join(' 且 ')}`);
+              break;
+          }
+        });
+        let content = (text || []).map((text, index) => (
+          <div key={index}>
+            {index != 0 && <div>并且</div>}
+            {text}
+          </div>
+        ));
+        if (formItemsOr.length == 1) {
+          allText.push(content);
+        } else {
+          allText.push(
+            <Card size="small" title={`条件组${index + 1}`}>
+              {content}
+            </Card>,
+          );
         }
       });
     }
-    if (text.length <= 0) text.push('其他条件进入此流程');
-    return text;
-  }, [formItems, depUserTree]);
+    if (allText.length == 0) allText.push('其他条件进入此流程');
+    return allText;
+  }, [formItemsOr, depUserTree]);
 
   return (
     <div
@@ -89,6 +116,7 @@ const JudgeRect = (props: any) => {
         width,
         height,
         padding: '6px',
+        overflowY: 'auto',
         boxShadow:
           '0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)',
       }}
@@ -99,26 +127,14 @@ const JudgeRect = (props: any) => {
       <div style={{ color: '#15BC83' }}>{label}</div>
       <div
         style={{
-          height: `${height - 32}px`,
+          height: `${height - 36}px`,
           // overflow: 'hidden',
           // textOverflow: 'ellipsis',
           // whiteSpace: 'nowrap',
           fontSize,
         }}
       >
-        {(contentText || []).map((text, index) => (
-          <span key={index}>
-            {index != 0 && (
-              <>
-                <br />
-                并且
-                <br />
-              </>
-            )}
-
-            {text}
-          </span>
-        ))}
+        {contentText}
       </div>
     </div>
   );

+ 100 - 39
src/components/Flow/node/judgeNode/mapServe.tsx

@@ -1,13 +1,21 @@
 import React, { useState, useEffect, useMemo } from 'react';
 import { FlowchartFormWrapper } from '@antv/xflow';
-import { Position, Size, ColorPicker, InputNumberField, InputField, SelectField } from '../fields';
+import {
+  Position,
+  Size,
+  ColorPicker,
+  InputNumberField,
+  InputField,
+  SelectField,
+} from '../fields';
 import { PREFIX } from '../constants';
-import { connect } from "umi";
+import { connect } from 'umi';
 import { UnityAction } from '@/utils/utils';
-import { Button } from 'antd';
+import { Button, Card } from 'antd';
 import AddCondition from '../../components/judgeModal';
 import RenderJudge, { JudgeType } from '../../components/judgeComponent';
 import { TYPE } from '../auditNode/mapServe';
+import { CloseOutlined, PlusOutlined } from '@ant-design/icons';
 
 // export const enum TYPE {
 //   AUDIT,
@@ -39,7 +47,10 @@ export interface IConfig {
   flow_node_id?: string;
   process_code?: string;
   type: TYPE;
+  // 条件  【此字段存在是为了兼容旧格式】
   formItems: string;
+  // 条件组 【新版用此字段】 formItems和formItemsOr同时只能存在一个
+  formItemsOr: string[];
   priority?: number; //优先级
 }
 
@@ -56,7 +67,7 @@ export interface FormItem {
 }
 
 const Component = (props: any) => {
-  const { config, plugin = {}, formItems } = props;
+  const { config, plugin = {}, formData } = props;
   const { updateNode } = plugin;
 
   // const formData: FormItem[] = [
@@ -114,6 +125,8 @@ const Component = (props: any) => {
   const [nodeConfig, setNodeConfig] = useState<IConfig>({
     ...config,
   });
+  const formItemsGroup = nodeConfig.formItemsOr || [];
+
   const onNodeConfigChange = (key: string, value: number | string | object) => {
     if (key) {
       setNodeConfig({
@@ -140,6 +153,72 @@ const Component = (props: any) => {
     UnityAction.emit('NODE_SAVE', nodeConfig);
   };
 
+  const onAddConditionGroup = () => {
+    onNodeConfigChange('formItemsOr', [...formItemsGroup, '[]']);
+  };
+  const onRemoveConditionGroup = (index: number) => {
+    let tempGroup = [...formItemsGroup];
+    tempGroup.splice(index, 1);
+    onNodeConfigChange('formItemsOr', [...tempGroup]);
+  };
+
+  const onAddCondition = (values: FormItem[], index: number) => {
+    const getFormItemsStr = (formItems: string) => {
+      let newFormItems: FormItem[] = [];
+      let oldFormItems = JSON.parse(formItems || '[]');
+      values.forEach((item) => {
+        let id = item.props.id;
+        // 判断是否含有旧的item
+        let oldItem = oldFormItems.find(
+          (formItem: FormItem) => formItem.props.id == id,
+        );
+        if (oldItem) {
+          newFormItems.push(oldItem);
+        } else {
+          newFormItems.push(item);
+        }
+      });
+      return JSON.stringify(newFormItems);
+    };
+    let tempGroup = [...formItemsGroup];
+    // 更新条件组
+    tempGroup[index] = getFormItemsStr(tempGroup[index]);
+    onNodeConfigChange('formItemsOr', tempGroup);
+  };
+
+  const renderCondition = () => {
+    let Cards: any = [];
+    formItemsGroup.forEach((formItems: string, index: number) => {
+      Cards.push(
+        <Card
+          key={index}
+          title={`条件组${index + 1}`}
+          extra={
+            <CloseOutlined onClick={() => onRemoveConditionGroup(index)} />
+          }
+        >
+          <AddCondition
+            items={formData}
+            formItems={formItems}
+            onOk={(values: FormItem[]) => onAddCondition(values, index)}
+          />
+          <RenderJudge
+            formItems={formItems}
+            onChange={(values: FormItem[]) => {
+              let tempGroup = [...formItemsGroup];
+              tempGroup[index] = JSON.stringify(values);
+              onNodeConfigChange('formItemsOr', tempGroup);
+            }}
+          />
+        </Card>,
+      );
+      if (index != formItemsGroup.length - 1) {
+        Cards.push(<div>或</div>);
+      }
+    });
+    return Cards;
+  };
+
   useEffect(() => {
     setNodeConfig({
       ...config,
@@ -153,7 +232,7 @@ const Component = (props: any) => {
         <InputField
           label="标题"
           value={nodeConfig.label}
-          onChange={value => {
+          onChange={(value) => {
             onNodeConfigChange('label', value);
           }}
         />
@@ -191,7 +270,7 @@ const Component = (props: any) => {
         <InputNumberField
           label="消息数量"
           value={nodeConfig.count}
-          onChange={value => {
+          onChange={(value) => {
             onNodeConfigChange('count', value);
           }}
         />
@@ -200,7 +279,7 @@ const Component = (props: any) => {
             label="字号"
             value={nodeConfig.fontSize}
             width={68}
-            onChange={value => {
+            onChange={(value) => {
               onNodeConfigChange('fontSize', value);
             }}
           />
@@ -215,37 +294,16 @@ const Component = (props: any) => {
           label="优先级"
           value={nodeConfig.priority}
           width={68}
-          onChange={value => {
+          onChange={(value) => {
             onNodeConfigChange('priority', value);
           }}
         />
-        <AddCondition
-          items={formItems}
-          formItems={nodeConfig.formItems}
-          onOk={(values: FormItem[]) => {
-            console.log('===formItems===', values);
-            let newFormItems = [];
-            let oldFormItems = JSON.parse(nodeConfig.formItems || '[]');
-            values.forEach(item => {
-              let id = item.props.id;
-              // 判断是否含有旧的item
-              let oldItem = oldFormItems.find(formItem => formItem.props.id == id);
-              if (oldItem) {
-                newFormItems.push(oldItem);
-              } else {
-                newFormItems.push(item);
-              }
-            });
-            onNodeConfigChange('formItems', JSON.stringify(newFormItems));
-          }}
-        />
-        <RenderJudge
-          formItems={nodeConfig.formItems}
-          onChange={(values: FormItem[]) => {
-            console.log('===formItems===', values);
-            onNodeConfigChange('formItems', JSON.stringify(values));
-          }}
-        />
+
+        <Button icon={<PlusOutlined />} onClick={() => onAddConditionGroup()}>
+          新增条件组
+        </Button>
+
+        {renderCondition()}
       </div>
 
       <Button style={{ marginTop: 20 }} type="primary" onClick={onSave}>
@@ -258,11 +316,14 @@ const Component = (props: any) => {
 function RecthServe(props: any) {
   return (
     <FlowchartFormWrapper {...props}>
-      {(config, plugin) => <Component {...props} plugin={plugin} config={config} />}
+      {(config, plugin) => (
+        <Component {...props} plugin={plugin} config={config} />
+      )}
     </FlowchartFormWrapper>
   );
 }
 
-export default connect(({ xflow }) => ({ auditList: xflow.auditList, formItems: xflow.formData }))(
-  RecthServe
-);
+export default connect(({ xflow }: any) => ({
+  auditList: xflow.auditList,
+  formData: xflow.formData,
+}))(RecthServe);

+ 14 - 10
src/components/UserDropdown/index.tsx

@@ -8,19 +8,23 @@ import { useModel } from '@umijs/max';
 
 const RenderDropDown = (menu: any) => {
   console.log(menu);
-  return <div className={styles.dropdown}>
-    <a key='1'>
-      修改密码
-    </a>
+  return (
+    <div className={styles.dropdown}>
+      <a key="1" href="/safety">
+        修改密码
+      </a>
 
-    <a key='2' href='/login'>
-      退出登录
-    </a>
-  </div>
-}
+      <a key="2" href="/login">
+        退出登录
+      </a>
+    </div>
+  );
+};
 
 export default function UserDropdown(props: any) {
-  const { initialState: { user } } = useModel('@@initialState');
+  const {
+    initialState: { user },
+  } = useModel('@@initialState');
   return (
     <div className={styles.root}>
       <Dropdown placement="top" dropdownRender={(menu) => RenderDropDown(menu)}>

+ 1 - 0
src/models/userList.js

@@ -5,6 +5,7 @@ export default () => {
   const { data, loading, run } = useRequest(query, {
     manual: true,
     cacheKey: 'queryUserList',
+    cacheTime: -1
   });
 
   return { userList: data?.list, loading, run };

+ 54 - 0
src/pages/ContractManager/component/AuditSteps.jsx

@@ -0,0 +1,54 @@
+import { Steps } from 'antd';
+const AuditSteps = (props) => {
+  // const data =
+  //   '[{"id":13,"desc":"","auditor":7,"AuditorUser":{"UserName":"admin","CName":"管理员","Title":"","Mobile":"13426370450","Email":"123123@qq.com","Status":1,"IsSuper":true,"DepId":"undefined","Dep":null,"Password":"4297f44b13955235245b2497399d7a93","QyWxUserId":"HanTangHeYing","DingUserId":"","Role":null,"RoleNames":"","ID":7,"CreatedBy":0,"CreatedOn":"2019-10-04T16:48:04+08:00","UpdatedBy":0,"UpdatedOn":"2022-06-17T14:23:15+08:00","DeletedBy":0,"DeletedOn":null,"DeletedFlag":0,"DefaultProject":"","ForbiddenModule":0,"IsDepLeader":0,"UserType":0,"Permission":null,"Permissions":null,"is_leader":0,"is_accountant":0,"is_opt_mgr":0,"is_wty_mgr":0},"seq":1,"oa_id":7,"seq_name":"审批1","audit_time":"1970-01-01T08:00:00+08:00"},{"id":14,"desc":"","auditor":7,"AuditorUser":{"UserName":"admin","CName":"管理员","Title":"","Mobile":"13426370450","Email":"123123@qq.com","Status":1,"IsSuper":true,"DepId":"undefined","Dep":null,"Password":"4297f44b13955235245b2497399d7a93","QyWxUserId":"HanTangHeYing","DingUserId":"","Role":null,"RoleNames":"","ID":7,"CreatedBy":0,"CreatedOn":"2019-10-04T16:48:04+08:00","UpdatedBy":0,"UpdatedOn":"2022-06-17T14:23:15+08:00","DeletedBy":0,"DeletedOn":null,"DeletedFlag":0,"DefaultProject":"","ForbiddenModule":0,"IsDepLeader":0,"UserType":0,"Permission":null,"Permissions":null,"is_leader":0,"is_accountant":0,"is_opt_mgr":0,"is_wty_mgr":0},"seq":2,"oa_id":7,"seq_name":"审批2","audit_time":"1970-01-01T08:00:00+08:00"}]';
+  // const OaAuditList1 = JSON.parse(data);
+  // const audit_status1 = 0;
+  // const current_seq1 = 1;
+
+  const { OaAuditList, audit_status, current_seq, statusText } = props;
+
+  const getDescription = (node) => {
+    let str = node?.AuditRoleInfo
+      ? `审批人:${node?.AuditRoleInfo.Name || '-'}`
+      : `审批人:${node?.AuditorUser.CName || '-'}`;
+    if (node.desc) {
+      return (
+        <div>
+          {str}
+          <div>
+            <Tooltip title={node.desc}>
+              <span style={{ color: '#1A73E8', textDecoration: 'undeline' }}>
+                审批意见
+              </span>
+            </Tooltip>
+          </div>
+        </div>
+      );
+    }
+    return str;
+  };
+
+  return (
+    <div style={{ display: 'flex' }}>
+      <Steps
+        style={{ marginBottom: 20 }}
+        current={audit_status == 3 ? OaAuditList?.length : current_seq - 1}
+        status={audit_status == 2 ? 'error' : 'process'}
+        items={OaAuditList?.map((item) => ({
+          title: item.seq_name,
+          description: getDescription(item),
+        }))}
+      />
+      {audit_status == 3 && (
+        <div
+          style={{ marginLeft: '40px', fontSize: '28px', whiteSpace: 'nowrap' }}
+        >
+          {statusText}
+        </div>
+      )}
+    </div>
+  );
+};
+
+export default AuditSteps;

+ 973 - 822
src/pages/ContractManager/component/Modal.jsx

@@ -15,19 +15,24 @@ import {
   Upload,
   Space,
   Radio,
+  message,
 } from 'antd';
 import ModuleTitle from '../../../components/ModuleTitle/moduleTitle';
 import { useEffect, useMemo, useState } from 'react';
 import {
+  queryAuditByCode,
   queryCompany,
-  queryDepList,
+  queryContractCode,
+  queryOAReCall,
   querySupplierList,
 } from '@/services/contract';
 import { useModel, useRequest } from '@umijs/max';
 import { CloudUploadOutlined } from '@ant-design/icons';
 import styles from '../index.less';
 import dayjs from 'dayjs';
-import InputSelect from '../../../components/InputSelect';
+import { advanceSubmitNextNode, audit } from '@/services/boom';
+import AuditSteps from './AuditSteps';
+import FileViewerModal from '@/components/FileViewerNew';
 export const Type = {
   add: 0, //新增
   detail: 1, //详情
@@ -45,6 +50,7 @@ export const StatusText = [
   '已作废',
 ];
 export const Status = {
+  ReCall: -1,
   None: 0,
   Checking: 1,
   CheckReject: 2,
@@ -61,6 +67,9 @@ const ContractModal = (props) => {
   } = useModel('@@initialState');
   const { userList, run: userListRun } = useModel('userList');
   const { depList, run: depListRun } = useModel('depList');
+  const [auditList, setAuditList] = useState([]);
+  const [fileViewerVisible, setFileViewerVisible] = useState(false);
+  const [fileViewerData, setFileViewerData] = useState();
   const FORMAT = 'YYYY-MM-DD';
   const {
     detail: data,
@@ -70,38 +79,142 @@ const ContractModal = (props) => {
     handleOk,
     handleCancel,
     parent_id,
+    handlerReCall,
   } = props;
   const title =
-    type == Type.add ? '新增' : type == Type.detail ? '详情' : '作废';
-  //所属公司为总部时才能选择部门,为子公司时,部门不能操作  所属部门为子公司的需要填经办人
-  const company = Form.useWatch('company_id', form);
-  const [depDisable, setDepDisable] = useState(false);
+    type == Type.add ? '新增' : type == Type.cancel ? '作废' : '详情';
+  const archivesOptions = [
+    {
+      Name: '财务部',
+      ID: '财务部',
+    },
+    {
+      Name: '行政部',
+      ID: '行政部',
+    },
+  ];
+
+  const [isPass, setIsPass] = useState(1);
+  const [companyDepList, setCompanyDepList] = useState(depList || []);
+  const [archivesDepList, setArchivesDepList] = useState(archivesOptions);
   const [dealDisable, setDealDisable] = useState(false);
-  //项目名称选择后,自动填入对应的项目编号
+  const [attachData, setAttachData] = useState({
+    attach: [],
+    attach_extend: [],
+  });
+  const company = Form.useWatch('company_id', form);
   const project_name = Form.useWatch('project_name', form);
+  const archives_dep = Form.useWatch('archives_dep', form);
 
   //是否补充协议,是的话需要填合同编号
   const is_supplement = Form.useWatch('is_supplement', form);
 
-  const [isPass, setIsPass] = useState(1);
-
-  const [fileList, setFileList] = useState([]);
-  const [fileExtendList, setFileExtendList] = useState([]);
+  //请求合同编号用
+  const dep_id = Form.useWatch('dep_id', form);
+  const parent_code = Form.useWatch('parent_code', form);
 
-  const { data: companyData, run: runCompany } = useRequest(queryCompany);
+  //审批流拼接
+  const formData = [
+    {
+      name: '是否本部',
+      id: 'DDSelectField_4fbddb04-9b4f-4281-991b-5047f835fb9d',
+      type: 'DDSelectField',
+      value: ['是'],
+    },
+    {
+      name: '合同归档部门',
+      id: 'DDSelectField_1235c6b9-9d74-4856-a62d-6ca1bb9716a6',
+      type: 'DDSelectField',
+      value: ['财务部'],
+    },
+    {
+      name: '合同编码',
+      id: 'TextField_1a01000b-4458-4dfb-bd13-74a74e7a33e5',
+      type: 'TextField',
+      value: ['1'],
+    },
+    {
+      name: '提审类型',
+      id: 'DDSelectField_c79e124c-c933-4ea1-b799-faceaf830a9b',
+      type: 'DDSelectField',
+      value: ['1'],
+    },
+  ];
 
-  console.log(user, data, depList);
+  //计算审批流数据
+  const advance = {
+    flow_id: 40,
+    form_list: null,
+    // node_level_id:0,
+    // id:0,
+    // project_id:0,
+    // cur_template_node_id:0,
+    // next_template_node_id:0,
+    // template_node_id:0,
+    // flow_path:null,
+    // template_id:0,
+    // cur_template_id:0,
+    // next_template_id:0,
+    formComponentValues: '',
+    // audit_list:[],
+  };
 
-  useEffect(() => {
-    userListRun();
-    depListRun();
-    runCompany();
-  }, []);
+  //旧审批流兼容
+  const oldAuditList = {
+    OaAuditList: [
+      {
+        id: 14,
+        auditor: 7,
+        AuditorUser: {
+          UserName: 'admin',
+          CName: '管理员',
+          IsSuper: true,
+          ID: 7,
+        },
+        seq: 1,
+        oa_id: 7,
+        seq_name: '审批1',
+      },
+    ],
+    audit_status: 3,
+    current_seq: 1,
+  };
 
-  useEffect(() => {
-    form.resetFields();
-  }, [data]);
+  const { data: companyData, run: runCompany } = useRequest(queryCompany);
 
+  //填写表单时计算审批流接口
+  const { run: runAuditList } = useRequest(
+    (data) => advanceSubmitNextNode(data),
+    {
+      debounceInterval: 500,
+      manual: true,
+      formatResult(res) {
+        const list = res.data[0]?.map((item) => {
+          const name = userList?.find(
+            (user) => user.ID == item[0].value,
+          )?.CName;
+          return { ...item[0], name };
+        });
+        setAuditList(
+          res.data[0]?.map((item) => {
+            const name = userList?.find(
+              (user) => user.ID == item[0].value,
+            )?.CName;
+            return { ...item[0], name };
+          }),
+        );
+      },
+    },
+  );
+  //计算合同编号接口
+  const { run: runCode } = useRequest((data) => queryContractCode(data), {
+    manual: true,
+    onSuccess: (data) => {
+      form.setFieldsValue({
+        code: data?.code,
+      });
+    },
+  });
   //供应商列表
   const { data: supplierList = [], loading } = useRequest(querySupplierList, {
     defaultParams: [
@@ -120,38 +233,159 @@ const ContractModal = (props) => {
         : [];
     },
   });
+  //获取OA 归档审批列表
+  const { data: auditData, run: runAudit } = useRequest(
+    (data) => queryAuditByCode({ ...data, extend_type: 0 }),
+    {
+      manual: true,
+      formatResult: (res) => {
+        if (res?.data) {
+          return res.data;
+        } else {
+          if (data?.status == Status.CheckReject) {
+            return { ...oldAuditList, audit_status: 2 };
+          }
+          return oldAuditList;
+        }
+      },
+    },
+  );
+  //获取OA 作废审批列表
+  const { data: auditCelData, run: runCalAudit } = useRequest(
+    (data) => queryAuditByCode({ ...data, extend_type: 1 }),
+    {
+      manual: true,
+      formatResult: (res) => {
+        if (res?.data) {
+          return res.data;
+        } else {
+          if (data?.status == Status.CalCheckReject) {
+            return { ...oldAuditList, audit_status: 2 };
+          }
+          return oldAuditList;
+        }
+      },
+    },
+  );
+
+  useEffect(() => {
+    if (!visible) {
+      setIsPass(1);
+      setDealDisable(false);
+      setAuditList([]);
+      setCompanyDepList([]);
+      setArchivesDepList([]);
+    } else {
+      userListRun();
+      depListRun();
+      runCompany();
+    }
+  }, [visible]);
+
+  useEffect(() => {
+    form.resetFields();
+    if (data?.status >= Status.Checking) runAudit({ extend_code: data.code });
+    if (data?.status >= Status.CalChecking)
+      runCalAudit({ extend_code: data.code });
+    let result = { attach: [], attach_extend: [] };
+    if (data?.attach) {
+      let att = JSON.parse(data.attach);
+      result.attach = att.map((item, idx) => {
+        return { ...item, uid: idx, status: 'done' };
+      });
+    }
+    if (data?.attach_extend) {
+      let att = JSON.parse(data.attach_extend);
+      result.attach_extend = att.map((item, idx) => {
+        return { ...item, uid: idx, status: 'done' };
+      });
+    }
+    setAttachData(result);
+  }, [data]);
 
   const isSuper = useMemo(() => {
-    if (user?.Permission['menu-001-audit']) return true;
+    if (
+      type == Type.add ||
+      type == Type.cancel ||
+      data?.status == Status.ReCall
+    )
+      return true;
+    let currentAuditUserID;
+    if (data?.status == Status.Checking && auditData) {
+      const { OaAuditList, audit_status } = auditData;
+      currentAuditUserID = OaAuditList[audit_status]?.auditor;
+    } else if (data?.status == Status.CalChecking && auditCelData) {
+      const { OaAuditList, audit_status } = auditCelData;
+      currentAuditUserID = OaAuditList[audit_status]?.auditor;
+    }
+    if (user.ID == currentAuditUserID) return true;
     return false;
-  }, [user]);
+  }, [user, data, auditData, auditCelData]);
 
   useEffect(() => {
-    if (type !== Type.add) return;
-    const item = companyData?.find((item) => item.ID == company);
+    if (type !== Type.add && data?.status !== Status.ReCall) return;
+    const newCompony = company || data?.company_id; //recall状态时compony是空, 需要用data?.company_id
+    if (!newCompony) {
+      setCompanyDepList([]);
+      setArchivesDepList([]);
+      return;
+    }
+    const deps = getDepItemById(newCompony)?.children;
+    if (deps) setCompanyDepList(deps);
+    const item = companyData?.find((item) => item.ID == newCompony);
     if (item?.Flag == 1) {
-      //公司为本部
-      setDepDisable(false);
-      form.setFieldsValue({
-        dep_id: '',
-        archives_dep: '',
-        created_dep: '',
-        deal_by: user?.CName,
-      });
-      // setDealDisable(false);
+      //公司为本部 经办人为自己并不可编辑 合同存档部门从财务和行政部选
+      setDealDisable(false);
+      setArchivesDepList(archivesOptions);
+      form.setFieldsValue({ deal_by: user?.CName });
     } else {
-      setDepDisable(true);
-      form.setFieldsValue({
-        dep_id: '综合管理部',
-        archives_dep: '综合管理部',
-        created_dep: '综合管理部',
-        deal_by: '',
-      });
-      // setDealDisable(true);
-      // form.setFieldsValue({ deal_by: user?.CName });
+      //公司为分子公司 经办人为手动输入 合同存档部门从所选分子公司的子部门选择
+      setDealDisable(true);
+      setArchivesDepList(deps);
+      form.setFieldsValue({ deal_by: '' });
     }
-  }, [company]);
+  }, [company, data]);
+
+  //获取合同编号逻辑 只有新增才请求
   useEffect(() => {
+    if (
+      //&& data?.status !== Status.ReCall
+      type !== Type.add ||
+      !company ||
+      !dep_id
+    )
+      return;
+    const item = companyData?.find((item) => item.ID == company);
+    const dep_code = getDepItemById(dep_id)?.Code;
+    if (item) {
+      let params = {
+        company_id: item.ID,
+        company_code: item.Code,
+        dep_code,
+        parent_code,
+      };
+      runCode(params);
+    }
+  }, [dep_id, parent_code]);
+
+  //获取审批流逻辑
+  useEffect(() => {
+    if (type !== Type.add && data?.status !== Status.ReCall) return;
+    const param = { ...advance };
+    let formValues = [];
+    const item = companyData?.find((item) => item.ID == company);
+    formValues.push({
+      ...formData[0],
+      value: item?.Flag == 1 ? ['是'] : ['否'],
+    });
+    if (archives_dep)
+      formValues.push({ ...formData[1], value: [archives_dep] });
+    param.formComponentValues = formValues;
+    runAuditList(param);
+  }, [company, archives_dep]);
+
+  useEffect(() => {
+    if (type !== Type.add && data?.status !== Status.ReCall) return;
     const project_code = projectList?.find(
       (item) => item.project_name == project_name,
     )?.project_full_code;
@@ -161,44 +395,26 @@ const ContractModal = (props) => {
       form.setFieldsValue({ project_code: '' });
     }
   }, [project_name]);
-
-  // useEffect(() => {
-  //   console.log('==================', is_supplement);
-  // }, [is_supplement]);
-
   const supplyList = useMemo(() => {
     return companyData ? [...companyData, ...supplierList] : supplierList;
   }, [companyData, supplierList]);
 
   const disableds = useMemo(() => {
-    if (!visible) {
-      setFileList([]);
-      setFileExtendList([]);
-      setIsPass(1);
-      setDepDisable(false);
-      setDealDisable(false);
-    }
-    if (type == Type.add) {
-      return { contract: false, check: true };
-    } else if (type == Type.detail) {
-      return { contract: true, check: true };
-    } else if (type == Type.cancel) {
-      return { contract: true, check: true };
-    }
-    return { contract: true, check: false };
-  }, [type, visible]);
+    if (data?.status == Status.ReCall) return { contract: false, recall: true };
+    if (data?.status > Status.None) return { contract: true, recall: true };
+    return { contract: false, recall: false };
+  }, [visible]);
 
   const UploadProps = {
     action: `/api/contract/v1/attach`,
     headers: {
       'JWT-TOKEN': localStorage.getItem('JWT-TOKEN'),
     },
+    defaultFileList: attachData?.attach,
     onChange({ file, fileList }) {
       if (file.status !== 'uploading') {
-        console.log(file, fileList);
         const list = fileList.map((item) => item.response?.data?.attach);
         form.setFieldsValue({ attach: list });
-        setFileList(fileList.map((item) => item.response?.data?.attach));
       }
     },
   };
@@ -207,74 +423,99 @@ const ContractModal = (props) => {
     headers: {
       'JWT-TOKEN': localStorage.getItem('JWT-TOKEN'),
     },
+    defaultFileList: attachData?.attach_extend,
     onChange({ file, fileList }) {
       if (file.status !== 'uploading') {
-        console.log(file, fileList);
-        setFileExtendList(fileList.map((item) => item.response?.data?.attach));
+        const list = fileList.map((item) => item.response?.data?.attach);
+        form.setFieldsValue({ attach_extend: list });
       }
     },
   };
 
+  //获取提交审批流所需form字段
+  const getAuditData = (values, type) => {
+    // 合同类型type "1" 归档 “2”作废
+    const flag =
+      companyData?.find((item) => item.ID == values.company)?.Flag == 1
+        ? '是'
+        : '否';
+    const newValues = [[flag], [values.archives_dep], [values.code], [type]];
+    const form = formData.map((item, index) => {
+      return { ...item, value: newValues[index] };
+    });
+    return form;
+  };
+
   const handleSubmit = () => {
     form.validateFields().then((values) => {
       if (type == Type.add) {
+        const form = getAuditData(values, '1');
+        const audit_list = auditList.map((item) => item.value);
         values.effect_on = dayjs(values.effect_on).format(FORMAT);
         values.created_on = values.created_on || dayjs().format(FORMAT);
         if (parent_id) values.parent_id = parent_id;
         if (values.amount || values.amount == 0)
           values.amount = values.amount + '';
         if (values.attach) values.attach = JSON.stringify(values.attach);
-        if (fileExtendList.length > 0)
-          values.attach_extend = JSON.stringify(fileList);
-
-        // if (values.party_c && values.party_c.length > 0)
+        if (values.attach_extend)
+          values.attach_extend = JSON.stringify(values.attach_extend);
         values.party_c = values.party_c?.join(',');
 
         const companyItem = companyData?.find(
           (item) => item.ID == values.company_id,
         );
-        //所属公司为本部
-        if (companyItem.Flag == 1) {
-          const item = getDepItemById(values.dep_id);
-          if (item) {
-            values.dep_name = item.Name;
-            values.dep_code = item.Code;
-          }
-          values.company_name = companyItem.Name;
-        } else {
-          //为分子公司
-          values.company_name = companyItem.Name;
-          values.company_code = companyItem.Code;
-          values.dep_name = '综合管理部';
-          values.dep_code = '综合管理部';
-          values.dep_id = 0;
-        }
+        values.company_name = companyItem.Name;
+        values.company_code = companyItem.Code;
+        const depItem = getDepItemById(values.dep_id);
+        values.dep_name = depItem?.Name;
+        values.dep_code = depItem?.Code;
         values.created_by = user?.ID;
-        handleOk(values, Type.add);
+        handleOk(values, Type.add, form, audit_list);
       } else if (type == Type.cancel) {
+        const form = getAuditData(values, '2');
+        const audit_list = auditData?.OaAuditList?.map((item) => item?.auditor);
         let result = {
           id: data?.id,
           cancel_desc: values.cancel_desc,
+          code: data?.code,
         };
-        handleOk(result, Type.cancel);
+        handleOk(result, Type.cancel, form, audit_list);
+      } else if (data?.status == Status.ReCall) {
+        const form = getAuditData(values, '1');
+        const audit_list = auditList.map((item) => item.value);
+        values.effect_on = dayjs(values.effect_on).format(FORMAT);
+        values.created_on = values.created_on || dayjs().format(FORMAT);
+        if (values.amount || values.amount == 0)
+          values.amount = values.amount + '';
+        if (values.attach) values.attach = JSON.stringify(values.attach);
+        if (values.attach_extend)
+          values.attach_extend = JSON.stringify(values.attach_extend);
+        values.party_c = values.party_c?.join(',');
+        const companyItem = companyData?.find(
+          (item) => item.ID == values.company_id,
+        );
+        values.company_name = companyItem.Name;
+        values.company_code = companyItem.Code;
+        const depItem = getDepItemById(values.dep_id);
+        values.dep_name = depItem?.Name;
+        values.dep_code = depItem?.Code;
+        values.created_by = user?.ID;
+        values.id = data?.id;
+        handleOk(values, Type.add, form, audit_list);
       } else if (data?.status == Status.Checking) {
         let result = {
-          id: data?.id,
-          check_by: user?.CName,
-          check_result: values.check_result,
-          is_pass: values.is_pass,
-          check_desc: values?.check_desc,
+          id: auditData?.id,
+          status: values.is_pass,
+          desc: '',
         };
-        handleOk(result, data?.status);
+        handleOk(result, Type.check, data?.status);
       } else if (data?.status == Status.CalChecking) {
         let result = {
-          id: data?.id,
-          cancel_check_by: user?.CName,
-          cancel_check_result: values.cancel_check_result,
-          is_pass: values.is_pass,
-          // check_desc: values?.check_desc,
+          id: auditCelData?.id,
+          status: values.is_pass,
+          desc: '',
         };
-        handleOk(result, data?.status);
+        handleOk(result, Type.check, data?.status);
       }
     });
   };
@@ -294,765 +535,675 @@ const ContractModal = (props) => {
     return fun(depList);
   };
 
-  const projectNameList = useMemo(() => {
-    let arr =
-      projectList?.map((item) => {
-        return {
-          value: item.project_name,
-          label: item.project_name,
-        };
-      }) || [];
-    return [
-      {
-        label: '日常项目',
-        value: '日常项目',
-      },
-      ...arr,
-    ];
-  }, [projectList]);
+  const handlePreViewSingle = (data) => {
+    if (!data) return;
+    const arr = data.name.split('.');
+    const type = arr[arr.length - 1];
+    const dataItem = { url: data.url, name: data.name, type };
+    setFileViewerData(dataItem);
+    setFileViewerVisible(true);
+  };
 
+  const renderFooter = () => {
+    return (
+      <Space>
+        {data?.status == Status.Checking && type !== Type.check && (
+          <Button onClick={() => handlerReCall(auditData?.id)}>撤回</Button>
+        )}
+        <Button onClick={handleCancel}>取消</Button>
+        <Button type="primary" onClick={handleSubmit} disabled={!isSuper}>
+          提交
+        </Button>
+      </Space>
+    );
+  };
   return (
-    <Modal
-      width={'85%'}
-      title={title}
-      open={visible}
-      okText="提交"
-      cancelText="返回"
-      onOk={handleSubmit}
-      onCancel={handleCancel}
-      // okButtonProps={type == Type.detail ? { disabled: true } : null}
-      destroyOnClose
-    >
-      <Divider />
-      <Form
-        form={form}
-        // initialValues={data}
-        labelCol={{ span: 7 }}
-        wrapperCol={{ span: 17 }}
+    <>
+      <Modal
+        width={'85%'}
+        title={title}
+        open={visible}
+        footer={renderFooter()}
+        onCancel={handleCancel}
+        destroyOnClose
       >
-        <ModuleTitle title="存档人信息" />
-        <Row>
-          <Col span={10} offset={1}>
-            <Form.Item
-              name="created_name"
-              initialValue={data?.created_name || user?.CName}
-              label="存档人:"
-            >
-              <Input disabled />
-            </Form.Item>
-            <Form.Item
-              name="company_id"
-              label="所属公司:"
-              tooltip="请选择该存档合同所属公司"
-              initialValue={data?.company_id}
-              rules={[
-                {
-                  required: true,
-                  message: '请填写所属公司',
-                },
-              ]}
-            >
-              <Select
-                showSearch
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                disabled={disableds.contract}
-                filterOption={(input, option) =>
-                  (option?.label ?? '')
-                    .toLowerCase()
-                    .includes(input.toLowerCase())
-                }
-                options={companyData?.map((item) => {
-                  return {
-                    value: item.ID,
-                    label: item.Name,
-                  };
-                })}
-              />
-            </Form.Item>
-          </Col>
-          <Col span={10}>
-            <Form.Item
-              name="created_on"
-              initialValue={data?.created_on || dayjs().format(FORMAT)}
-              label="存档时间:"
-            >
-              <Input disabled />
-            </Form.Item>
-            <Form.Item
-              name="dep_id"
-              label="所属部门:"
-              initialValue={data?.dep_id}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择所属部门',
-                },
-              ]}
-            >
-              <TreeSelect
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                showSearch
-                allowClear
-                fieldNames={{
-                  label: 'Name',
-                  value: 'ID',
-                  children: 'children',
-                }}
-                disabled={disableds.contract || depDisable}
-                dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
-                treeData={depList?.find((item) => item.Code == 'GT')?.children}
-              />
-            </Form.Item>
-          </Col>
-        </Row>
-        <ModuleTitle title="经办人信息" />
-        <Row>
-          <Col span={10} offset={1}>
-            <Form.Item
-              name="deal_by"
-              label="经办人:"
-              tooltip="经办人应负责合同审批流程、签字盖章、合同原件存档和电子档案存档。母公司的经办人为OA审批提交人,也是存档人。子公司经办人由子公司合同专员填写,一般是合同审批时的提交人或者是合同实际执行的负责人"
-              initialValue={data?.deal_by}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择经办人',
-                },
-              ]}
-            >
-              <Input disabled={!depDisable} />
-              {/* <Select
-                showSearch
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                disabled={!depDisable}
-                filterOption={(input, option) =>
-                  (option?.label ?? '')
-                    .toLowerCase()
-                    .includes(input.toLowerCase())
-                }
-                options={userList?.map((item) => {
-                  return {
-                    value: item.CName,
-                    label: item.CName,
-                  };
-                })}
-              /> */}
-            </Form.Item>
-          </Col>
-          <Col span={10}>
-            <Form.Item
-              name="created_dep"
-              label="签约承办部门:"
-              tooltip="请选择该存档合同的实际履行部门,一般为经办人所在部门"
-              initialValue={data?.created_dep}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择签约承办部门',
-                },
-              ]}
-            >
-              <TreeSelect
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                showSearch
-                allowClear
-                disabled={disableds.contract || depDisable}
-                fieldNames={{
-                  label: 'Name',
-                  value: 'Name',
-                  children: 'children',
-                }}
-                dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
-                treeData={depList?.find((item) => item.Code == 'GT')?.children}
-              />
-            </Form.Item>
-          </Col>
-        </Row>
-        <ModuleTitle title="合同信息" />
-
-        <Row>
-          <Col span={10} offset={1}>
-            <Form.Item
-              name="is_supplement"
-              label="是否补充协议:"
-              tooltip="合同名称"
-              initialValue={0}
-              rules={[
-                {
-                  required: true,
-                  message: '请填写合同名称',
-                },
-              ]}
-            >
-              <Radio.Group>
-                <Radio value={1}>是</Radio>
-                <Radio value={0}>否</Radio>
-              </Radio.Group>
-            </Form.Item>
-            <Form.Item
-              name="name"
-              label="合同名称:"
-              tooltip="请与OA审批时填写的合同名称一致"
-              initialValue={data?.name}
-              rules={[
-                {
-                  required: true,
-                  message: '请填写合同名称',
-                },
-              ]}
-            >
-              <Input disabled={disableds.contract} />
-            </Form.Item>
-            <Form.Item
-              name="effect_on"
-              label="合同签订日期:"
-              initialValue={data?.effect_on}
-              tooltip="合同主体各方签字盖章完成之日,以最后签字盖章的为准"
-              rules={[
-                {
-                  required: true,
-                  message: '请填写合同名称',
-                },
-              ]}
-            >
-              {type == Type.add ? (
-                <DatePicker
+        <Divider />
+        <Form
+          form={form}
+          // initialValues={data}
+          labelCol={{ span: 7 }}
+          wrapperCol={{ span: 17 }}
+        >
+          <ModuleTitle title="存档人信息" />
+          <Row>
+            <Col span={10} offset={1}>
+              <Form.Item
+                name="created_name"
+                initialValue={data?.created_name || user?.CName}
+                label="存档人:"
+              >
+                <Input disabled />
+              </Form.Item>
+              <Form.Item
+                name="company_id"
+                label="所属公司:"
+                tooltip="请选择该存档合同所属公司"
+                initialValue={data?.company_id}
+                rules={[
+                  {
+                    required: true,
+                    message: '请填写所属公司',
+                  },
+                ]}
+              >
+                <Select
+                  showSearch
                   style={{ width: '100%' }}
-                  disabled={disableds.contract}
+                  placeholder="请选择"
+                  disabled={disableds.contract || disableds.recall}
+                  filterOption={(input, option) =>
+                    (option?.label ?? '')
+                      .toLowerCase()
+                      .includes(input.toLowerCase())
+                  }
+                  options={companyData?.map((item) => {
+                    return {
+                      value: item.ID,
+                      label: item.Name,
+                    };
+                  })}
                 />
-              ) : (
-                <Input disabled={disableds.contract} />
-              )}
-            </Form.Item>
-            <Form.Item
-              name="project_name"
-              label="项目名称:"
-              tooltip="不涉及项目请选“日常项目”"
-              initialValue={data?.project_name}
-              rules={[
-                {
-                  required: true,
-                  message: '请填写项目名称',
-                },
-              ]}
-            >
-              {/* <InputSelect
-                list={projectList?.map((item) => {
-                  return {
-                    key: item.id,
-                    value: item.project_name,
-                  };
-                })}
-              /> */}
-              <Select
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                showSearch
-                options={projectList?.map((item) => {
-                  return {
-                    value: item.project_name,
-                    label: item.project_name,
-                  };
-                })}
-                disabled={disableds.contract}
-              />
-            </Form.Item>
-            <Form.Item
-              name="party_a"
-              label="甲方:"
-              tooltip="合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
-              initialValue={data?.party_a}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择甲方',
-                },
-              ]}
-            >
-              <TreeSelect
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                showSearch
-                allowClear
-                fieldNames={{
-                  label: 'Name',
-                  value: 'Name',
-                  children: 'children',
-                }}
-                dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
-                treeData={supplyList}
-                disabled={disableds.contract}
-              />
-            </Form.Item>
-          </Col>
-          <Col span={10}>
-            <Form.Item
-              style={{ opacity: is_supplement ? 1 : 0 }}
-              name="parent_code"
-              tooltip="请先查询原合同编号,原合同未录入本系统的,需先录入存档。"
-              initialValue={data?.parent_code}
-              label="原合同编号:"
-              rules={
-                is_supplement
-                  ? [
-                      {
-                        required: true,
-                        message: '请填写原合同编号',
-                      },
-                    ]
-                  : []
-              }
-            >
-              <Input placeholder="请填写" />
-            </Form.Item>
-            <Form.Item
-              name="code"
-              tooltip="合同编号按《合同管理办法》的合同编码规则编号。"
-              initialValue={data?.code}
-              label="合同编号:"
-              // rules={[
-              //   {
-              //     required: true,
-              //     message: '请填写合同编号',
-              //   },
-              // ]}
-            >
-              <Input placeholder="提交后自动生成" disabled />
-            </Form.Item>
-            <Form.Item
-              label="合同总价款:"
-              name="amount"
-              tooltip="请与OA审批时填写的“合同金额”一致。不涉及金额填“0”"
-              initialValue={data?.amount}
-              rules={[
-                {
-                  required: true,
-                  message: '请输入合同总价款',
-                },
-              ]}
-            >
-              <InputNumber
-                style={{ width: '100%' }}
-                precision={2}
-                addonAfter="万元"
-                disabled={disableds.contract}
-              />
-            </Form.Item>
-
-            <Form.Item
-              name="project_code"
-              initialValue={data?.project_code}
-              label="项目编号:"
-            >
-              <Input disabled />
-            </Form.Item>
-            <Form.Item
-              name="party_b"
-              label="乙方:"
-              tooltip="合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
-              initialValue={data?.party_b}
-              rules={[
-                {
-                  required: true,
-                  message: '请选择乙方',
-                },
-              ]}
-            >
-              <TreeSelect
-                style={{ width: '100%' }}
-                placeholder="请选择"
-                showSearch
-                allowClear
-                disabled={disableds.contract}
-                fieldNames={{
-                  label: 'Name',
-                  value: 'Name',
-                  children: 'children',
-                }}
-                dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
-                treeData={supplyList}
-              />
-            </Form.Item>
-          </Col>
-        </Row>
-        <Form.Item
-          name="party_c"
-          label="丙方(及其他):"
-          tooltip="可多选。合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
-          initialValue={data?.party_c ? data?.party_c.split(',') : []}
-          labelCol={{ span: 4 }}
-        >
-          <TreeSelect
-            style={{ width: '100%' }}
-            placeholder="请选择"
-            showSearch
-            multiple
-            allowClear
-            fieldNames={{
-              label: 'Name',
-              value: 'Name',
-              children: 'children',
-            }}
-            dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
-            treeData={supplyList}
-            disabled={disableds.contract}
-          />
-        </Form.Item>
-        <Form.Item
-          name="perform"
-          initialValue={data?.perform}
-          label="合同履行情况:"
-          labelCol={{ span: 4 }}
-        >
-          <Input.TextArea disabled={disableds.contract} />
-        </Form.Item>
-        <Row>
-          <Col span={10} offset={1}>
-            <Form.Item
-              label="合同及合同附件上传:"
-              tooltip="请上传合同正式盖章文本的扫描件(含技术协议、质保承诺等附件),不得用照片、图片格式,不得遗漏附件"
-              name="attach"
-              rules={
-                disableds.contract
-                  ? []
-                  : [
-                      {
-                        required: true,
-                        message: '请上传合同及合同相关附件',
-                      },
-                    ]
-              }
-            >
-              {type == Type.add ? (
-                <Upload {...UploadProps}>
-                  <Button icon={<CloudUploadOutlined />}>Upload</Button>
-                </Upload>
-              ) : (
-                <ul>
-                  {data?.attach &&
-                    JSON.parse(data?.attach)?.map((item, idx) => (
-                      <li key={`${idx}_${item.name}`}>{item.name}</li>
-                    ))}
-                </ul>
-              )}
-            </Form.Item>
-            <Form.Item
-              name="archives_dep"
-              initialValue={data?.archives_dep}
-              label="合同原件存档部门:"
-              rules={[
-                {
-                  required: true,
-                  message: '请选择合同原件存档部门',
-                },
-              ]}
-              tooltip="母公司财务部和采购部门的合同请选择“财务部”,其他部门请选择“行政部”,子公司合同选择“综合管理部”"
-            >
-              <Select
-                style={{ width: '100%' }}
-                options={[
+              </Form.Item>
+            </Col>
+            <Col span={10}>
+              <Form.Item
+                name="created_on"
+                initialValue={data?.created_on || dayjs().format(FORMAT)}
+                label="存档时间:"
+              >
+                <Input disabled />
+              </Form.Item>
+              <Form.Item
+                name="dep_id"
+                label="所属部门:"
+                initialValue={data?.dep_id}
+              >
+                <TreeSelect
+                  style={{ width: '100%' }}
+                  placeholder="请选择"
+                  showSearch
+                  allowClear
+                  fieldNames={{
+                    label: 'Name',
+                    value: 'ID',
+                    children: 'children',
+                  }}
+                  disabled={disableds.contract || disableds.recall}
+                  dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+                  treeData={companyDepList}
+                />
+              </Form.Item>
+            </Col>
+          </Row>
+          <ModuleTitle title="经办人信息" />
+          <Row>
+            <Col span={10} offset={1}>
+              <Form.Item
+                name="deal_by"
+                label="经办人:"
+                tooltip="经办人应负责合同审批流程、签字盖章、合同原件存档和电子档案存档。母公司的经办人为OA审批提交人,也是存档人。子公司经办人由子公司合同专员填写,一般是合同审批时的提交人或者是合同实际执行的负责人"
+                initialValue={data?.deal_by}
+                rules={[
                   {
-                    value: '财务部',
-                    label: '财务部',
+                    required: true,
+                    message: '请选择经办人',
                   },
+                ]}
+              >
+                <Input disabled={!dealDisable} />
+              </Form.Item>
+            </Col>
+            <Col span={10}>
+              <Form.Item
+                name="created_dep"
+                label="签约承办部门:"
+                tooltip="请选择该存档合同的实际履行部门,一般为经办人所在部门"
+                initialValue={data?.created_dep}
+                rules={[
                   {
-                    value: '行政部',
-                    label: '行政部',
+                    required: true,
+                    message: '请选择签约承办部门',
                   },
                 ]}
-                disabled={disableds.contract || depDisable}
-              />
-            </Form.Item>
-          </Col>
-          <Col span={10}>
-            <Form.Item
-              label="合同相关资料上传:"
-              tooltip={
-                <div>
-                  依据《合同管理办法》,合同相关资料需要作为合同电子档案的一部分,包括:
-                  <br />
-                  1)合同会审纪要或投资决策通知书(如有);
-                  <br />
-                  2)合同相对方的营业执照等资质证的复印件(首次签约的须加盖公章)、个人身份证复印件(合同一方为自然人时提供);
-                  <br />
-                  3)合同相对方经办人员的授权委托书原件及其身份证复印件(如有);
-                  <br />
-                  4)
-                  涉及房屋或场地租赁的,还应提供房屋及场地的权属证明资料,但如果续签租赁合同,且房屋所有权人没有发生变更的,在附具相关说明后可不再提供上述资料;
-                  <br />
-                  5)其他资料。
-                </div>
-              }
-            >
-              {type == Type.add ? (
-                <Upload {...UploadPropsExtend}>
-                  <Button icon={<CloudUploadOutlined />}>Upload</Button>
-                </Upload>
-              ) : (
-                <ul>
-                  {data?.attach_extend &&
-                    JSON.parse(data?.attach_extend)?.map((item, idx) => (
-                      <li key={`${idx}_${item.name}`}>
-                        {/* <Space>
-                          {item.name} <span>预览</span>{' '}
-                          <a href={item.url}>下载</a>
-                        </Space> */}
-                      </li>
-                    ))}
-                </ul>
-              )}
-            </Form.Item>
-          </Col>
-        </Row>
+              >
+                <TreeSelect
+                  style={{ width: '100%' }}
+                  placeholder="请选择"
+                  showSearch
+                  allowClear
+                  disabled={disableds.contract}
+                  fieldNames={{
+                    label: 'Name',
+                    value: 'Name',
+                    children: 'children',
+                  }}
+                  dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+                  treeData={companyDepList}
+                />
+              </Form.Item>
+            </Col>
+          </Row>
+          <ModuleTitle title="合同信息" />
 
-        {type != Type.add && (
-          <>
-            <ModuleTitle title="归档流程" />
-            <div className={styles.modelItem}>
-              <Steps
-                current={data?.status == Status.Checking ? 1 : 2}
-                status={
-                  data?.status == Status.CheckReject ? 'error' : 'process'
-                }
-                items={[
+          <Row>
+            <Col span={10} offset={1}>
+              <Form.Item
+                name="is_supplement"
+                label="是否补充协议:"
+                tooltip="合同名称"
+                initialValue={0}
+                rules={[
                   {
-                    title: '发起',
-                    description: (
-                      <>
-                        <div className={styles.textNowarp}>
-                          发起人:{data?.created_name}
-                        </div>
-                        <div className={styles.textNowarp}>
-                          发起时间:{data?.created_on}
-                        </div>
-                      </>
-                    ),
+                    required: true,
+                    message: '请填写合同名称',
                   },
+                ]}
+              >
+                <Radio.Group disabled={disableds.contract || disableds.recall}>
+                  <Radio value={1}>是</Radio>
+                  <Radio value={0}>否</Radio>
+                </Radio.Group>
+              </Form.Item>
+              <Form.Item
+                name="name"
+                label="合同名称:"
+                tooltip="请与OA审批时填写的合同名称一致"
+                initialValue={data?.name}
+                rules={[
                   {
-                    title: '审核',
-                    description: (
-                      <>
-                        <div className={styles.textNowarp}>
-                          审核人:{data?.check_by}
-                        </div>
-                        <div className={styles.textNowarp}>
-                          审核时间:{data?.check_on}
-                        </div>
-                        {data?.check_desc && (
-                          <div
-                            className={styles.textNowarp}
-                            style={{ color: 'red' }}
-                          >
-                            拒绝原因:{data?.check_desc}
-                          </div>
-                        )}
-                      </>
-                    ),
+                    required: true,
+                    message: '请填写合同名称',
                   },
+                ]}
+              >
+                <Input disabled={disableds.contract} />
+              </Form.Item>
+              <Form.Item
+                name="effect_on"
+                label="合同签订日期:"
+                initialValue={data?.effect_on}
+                tooltip="合同主体各方签字盖章完成之日,以最后签字盖章的为准"
+                rules={[
                   {
-                    title:
-                      data?.status >= Status.CheckSuccess
-                        ? StatusText[Status.CheckSuccess]
-                        : StatusText[data?.status],
+                    required: true,
+                    message: '请填写合同名称',
                   },
                 ]}
-              />
-            </div>
-          </>
-        )}
-        {isSuper && data.status == Status.Checking && (
-          <>
-            <ModuleTitle title="审核情况" />
-            <Row>
-              <Col span={10} offset={1}>
-                <Form.Item
-                  name="check_by"
-                  initialValue={user?.CName}
-                  label="审核人:"
-                >
-                  <Input disabled />
-                </Form.Item>
-                <Form.Item name="is_pass" initialValue={1} label="审核意见:">
-                  <Select
-                    onChange={(e) => {
-                      setIsPass(e);
-                    }}
+              >
+                {type == Type.add ? (
+                  <DatePicker
                     style={{ width: '100%' }}
-                    options={[
-                      {
-                        value: 1,
-                        label: '同意',
-                      },
-                      {
-                        value: 0,
-                        label: '拒绝',
-                      },
-                    ]}
+                    disabled={disableds.contract}
                   />
-                </Form.Item>
-              </Col>
-              <Col span={10}>
-                <Form.Item
-                  name="check_date"
-                  initialValue={dayjs().format(FORMAT)}
-                  label="审核时间:"
-                >
-                  <Input disabled />
-                </Form.Item>
-              </Col>
-            </Row>
-            {!isPass && (
+                ) : (
+                  <Input disabled={disableds.contract} />
+                )}
+              </Form.Item>
               <Form.Item
-                name="check_desc"
-                label="拒绝原因:"
-                labelCol={{ span: 4 }}
+                name="project_name"
+                label="项目名称:"
+                tooltip="不涉及项目请选“日常项目”"
+                initialValue={data?.project_name}
+                rules={[
+                  {
+                    required: true,
+                    message: '请填写项目名称',
+                  },
+                ]}
               >
-                <Input.TextArea />
+                <Select
+                  style={{ width: '100%' }}
+                  placeholder="请选择"
+                  showSearch
+                  options={projectList?.map((item) => {
+                    return {
+                      value: item.project_name,
+                      label: item.project_name,
+                    };
+                  })}
+                  disabled={disableds.contract}
+                />
               </Form.Item>
-            )}
-          </>
-        )}
-        {(type == Type.cancel || data?.status >= Status.CalChecking) && (
-          <>
-            <ModuleTitle title="作废信息" />
-            <Form.Item
-              name="cancel_desc"
-              label="作废原因:"
-              initialValue={data?.cancel_desc}
-              labelCol={{ span: 4 }}
-              rules={[
-                {
-                  required: true,
-                  message: '请填写作废原因',
-                },
-              ]}
-            >
-              <Input disabled={type != Type.cancel} />
-            </Form.Item>
-          </>
-        )}
-        {type == Type.cancel && (
+              <Form.Item
+                name="party_a"
+                label="甲方:"
+                tooltip="合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
+                initialValue={data?.party_a}
+                rules={[
+                  {
+                    required: true,
+                    message: '请选择甲方',
+                  },
+                ]}
+              >
+                <TreeSelect
+                  style={{ width: '100%' }}
+                  placeholder="请选择"
+                  showSearch
+                  allowClear
+                  fieldNames={{
+                    label: 'Name',
+                    value: 'Name',
+                    children: 'children',
+                  }}
+                  dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+                  treeData={supplyList}
+                  disabled={disableds.contract}
+                />
+              </Form.Item>
+            </Col>
+            <Col span={10}>
+              <Form.Item
+                style={{ opacity: is_supplement ? 1 : 0 }}
+                name="parent_code"
+                tooltip="请先查询原合同编号,原合同未录入本系统的,需先录入存档。"
+                initialValue={data?.parent_code}
+                label="原合同编号:"
+                rules={
+                  is_supplement
+                    ? [
+                        {
+                          required: true,
+                          message: '请填写原合同编号',
+                        },
+                      ]
+                    : []
+                }
+              >
+                <Input
+                  placeholder="请填写"
+                  disabled={disableds.contract || disableds.recall}
+                />
+              </Form.Item>
+              <Form.Item
+                name="code"
+                tooltip="合同编号按《合同管理办法》的合同编码规则编号。"
+                initialValue={data?.code}
+                label="合同编号:"
+              >
+                <Input placeholder="提交后自动生成" disabled />
+              </Form.Item>
+              <Form.Item
+                label="合同总价款:"
+                name="amount"
+                tooltip="请与OA审批时填写的“合同金额”一致。不涉及金额填“0”"
+                initialValue={data?.amount}
+                rules={[
+                  {
+                    required: true,
+                    message: '请输入合同总价款',
+                  },
+                ]}
+              >
+                <InputNumber
+                  style={{ width: '100%' }}
+                  precision={2}
+                  addonAfter="万元"
+                  disabled={disableds.contract}
+                />
+              </Form.Item>
+
+              <Form.Item
+                name="project_code"
+                initialValue={data?.project_code}
+                label="项目编号:"
+              >
+                <Input disabled />
+              </Form.Item>
+              <Form.Item
+                name="party_b"
+                label="乙方:"
+                tooltip="合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
+                initialValue={data?.party_b}
+                rules={[
+                  {
+                    required: true,
+                    message: '请选择乙方',
+                  },
+                ]}
+              >
+                <TreeSelect
+                  style={{ width: '100%' }}
+                  placeholder="请选择"
+                  showSearch
+                  allowClear
+                  disabled={disableds.contract}
+                  fieldNames={{
+                    label: 'Name',
+                    value: 'Name',
+                    children: 'children',
+                  }}
+                  dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+                  treeData={supplyList}
+                />
+              </Form.Item>
+            </Col>
+          </Row>
           <Form.Item
-            name="cancel_on"
-            label="创建时间:"
-            initialValue={dayjs().format(FORMAT)}
+            name="party_c"
+            label="丙方(及其他):"
+            tooltip="可多选。合同主体可以下拉选择,可选项需要经办人在“主页--供应商管理”中创建。经办人可以维护和更新供应商信息。"
+            initialValue={data?.party_c ? data?.party_c.split(',') : []}
             labelCol={{ span: 4 }}
           >
-            <Input
-              style={{ width: '460px' }}
-              defaultValue={dayjs().format('YYYY-MM-DD')}
-              disabled
+            <TreeSelect
+              style={{ width: '100%' }}
+              placeholder="请选择"
+              showSearch
+              multiple
+              allowClear
+              fieldNames={{
+                label: 'Name',
+                value: 'Name',
+                children: 'children',
+              }}
+              dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
+              treeData={supplyList}
+              disabled={disableds.contract}
             />
-            <span
-              style={{ color: 'red', fontSize: '24px', marginLeft: '40px' }}
-            >
-              确认作废该合同,作废提交后无法撤回
-            </span>
           </Form.Item>
-        )}
-        {data?.status >= Status.CalChecking && (
-          <>
-            <ModuleTitle title="作废流程" />
-            <div className={styles.modelItem}>
-              <Steps
-                current={data?.status == Status.CalChecking ? 1 : 2}
-                status={
-                  data?.status == Status.CalCheckReject ? 'error' : 'process'
+          <Form.Item
+            name="perform"
+            initialValue={data?.perform}
+            label="合同履行情况:"
+            labelCol={{ span: 4 }}
+          >
+            <Input.TextArea disabled={disableds.contract} />
+          </Form.Item>
+          <Row>
+            <Col span={10} offset={1}>
+              <Form.Item
+                label="合同及合同附件上传:"
+                tooltip="请上传合同正式盖章文本的扫描件(含技术协议、质保承诺等附件),不得用照片、图片格式,不得遗漏附件"
+                name="attach"
+                rules={
+                  disableds.contract
+                    ? []
+                    : [
+                        {
+                          required: true,
+                          message: '请上传合同及合同相关附件',
+                        },
+                      ]
                 }
-                items={[
-                  {
-                    title: '发起',
-                    description: (
-                      <>
-                        <div className={styles.textNowarp}>
-                          发起人:{data?.created_name}
-                        </div>
-                        <div className={styles.textNowarp}>
-                          发起时间:{data?.created_on}
-                        </div>
-                      </>
-                    ),
-                  },
-                  {
-                    title: '审核',
-                    description: (
-                      <>
-                        <div className={styles.textNowarp}>
-                          审核人:{data?.cancel_check_by}
-                        </div>
-                        <div className={styles.textNowarp}>
-                          审核时间:{data?.cancel_check_on}
-                        </div>
-                      </>
-                    ),
-                  },
+                initialValue={attachData.attach}
+              >
+                {type == Type.add || data?.status == Status.ReCall ? (
+                  <Upload {...UploadProps}>
+                    <Button icon={<CloudUploadOutlined />}>Upload</Button>
+                  </Upload>
+                ) : (
+                  <ul>
+                    {data?.attach &&
+                      JSON.parse(data?.attach)?.map((item, idx) => (
+                        <li key={`${idx}_${item.name}`}>
+                          <a onClick={() => handlePreViewSingle(item)}>
+                            {item.name}
+                          </a>
+                        </li>
+                      ))}
+                  </ul>
+                )}
+              </Form.Item>
+              <Form.Item
+                name="archives_dep"
+                initialValue={data?.archives_dep}
+                label="合同原件存档部门:"
+                tooltip="母公司财务部和采购部门的合同请选择“财务部”,其他部门请选择“行政部”,子公司合同选择“综合管理部”"
+                rules={[
                   {
-                    title: StatusText[data?.status],
+                    required: true,
+                    message: '请选择合同原件存档部门',
                   },
                 ]}
-              />
-            </div>
-          </>
-        )}
-        {isSuper && data.status == Status.CalChecking && (
-          <>
-            <ModuleTitle title="审核情况" />
-            <Row>
-              <Col span={10} offset={1}>
-                <Form.Item
-                  name="cancel_check_by"
-                  initialValue={user?.CName}
-                  label="审核人:"
-                >
-                  <Input disabled />
-                </Form.Item>
-                <Form.Item name="is_pass" initialValue={1} label="审核意见:">
-                  <Select
-                    onChange={(e) => {
-                      setIsPass(e);
-                    }}
-                    style={{ width: '100%' }}
-                    options={[
-                      {
-                        value: 1,
-                        label: '同意',
-                      },
-                      {
-                        value: 0,
-                        label: '拒绝',
-                      },
-                    ]}
-                  />
-                </Form.Item>
-              </Col>
-              <Col span={10}>
+              >
+                <Select
+                  style={{ width: '100%' }}
+                  options={archivesDepList?.map((item) => {
+                    return { label: item.Name, value: item.ID };
+                  })}
+                  disabled={disableds.contract}
+                />
+              </Form.Item>
+            </Col>
+            <Col span={10}>
+              <Form.Item
+                name="attach_extend"
+                label="合同相关资料上传:"
+                initialValue={attachData.attach_extend}
+                tooltip={
+                  <div>
+                    依据《合同管理办法》,合同相关资料需要作为合同电子档案的一部分,包括:
+                    <br />
+                    1)合同会审纪要或投资决策通知书(如有);
+                    <br />
+                    2)合同相对方的营业执照等资质证的复印件(首次签约的须加盖公章)、个人身份证复印件(合同一方为自然人时提供);
+                    <br />
+                    3)合同相对方经办人员的授权委托书原件及其身份证复印件(如有);
+                    <br />
+                    4)
+                    涉及房屋或场地租赁的,还应提供房屋及场地的权属证明资料,但如果续签租赁合同,且房屋所有权人没有发生变更的,在附具相关说明后可不再提供上述资料;
+                    <br />
+                    5)其他资料。
+                  </div>
+                }
+              >
+                {type == Type.add ? (
+                  <Upload {...UploadPropsExtend}>
+                    <Button icon={<CloudUploadOutlined />}>Upload</Button>
+                  </Upload>
+                ) : (
+                  <ul>
+                    {data?.attach_extend &&
+                      JSON.parse(data?.attach_extend)?.map((item, idx) => (
+                        <li key={`${idx}_${item.name}`}>
+                          <a onClick={() => handlePreViewSingle(item)}>
+                            {item.name}
+                          </a>
+                        </li>
+                      ))}
+                  </ul>
+                )}
+              </Form.Item>
+            </Col>
+          </Row>
+
+          {data?.status >= Status.Checking && (
+            <>
+              <ModuleTitle title="归档流程" />
+              <div className={styles.modelItem}>
+                <AuditSteps {...auditData} statusText="已归档" />
+              </div>
+            </>
+          )}
+          {isSuper && data.status == Status.Checking && (
+            <>
+              <ModuleTitle title="审核情况" />
+              <Row>
+                <Col span={10} offset={1}>
+                  <Form.Item
+                    name="check_by"
+                    initialValue={user?.CName}
+                    label="审核人:"
+                  >
+                    <Input disabled />
+                  </Form.Item>
+                  <Form.Item name="is_pass" initialValue={1} label="审核意见:">
+                    <Select
+                      onChange={(e) => {
+                        setIsPass(e);
+                      }}
+                      style={{ width: '100%' }}
+                      options={[
+                        {
+                          value: 1,
+                          label: '同意',
+                        },
+                        {
+                          value: 2,
+                          label: '拒绝',
+                        },
+                      ]}
+                    />
+                  </Form.Item>
+                </Col>
+                <Col span={10}>
+                  <Form.Item
+                    name="check_date"
+                    initialValue={dayjs().format(FORMAT)}
+                    label="审核时间:"
+                  >
+                    <Input disabled />
+                  </Form.Item>
+                </Col>
+              </Row>
+              {isPass == 2 && (
                 <Form.Item
-                  name="check_date"
-                  initialValue={dayjs().format(FORMAT)}
-                  label="审核时间:"
+                  name="check_desc"
+                  label="拒绝原因:"
+                  labelCol={{ span: 4 }}
                 >
-                  <Input disabled />
+                  <Input.TextArea />
                 </Form.Item>
-              </Col>
-            </Row>
-            {!isPass && (
+              )}
+            </>
+          )}
+          {(type == Type.cancel || data?.status >= Status.CalChecking) && (
+            <>
+              <ModuleTitle title="作废信息" />
               <Form.Item
-                name="cancel_check_result"
-                label="拒绝原因:"
+                name="cancel_desc"
+                label="作废原因:"
+                initialValue={data?.cancel_desc}
                 labelCol={{ span: 4 }}
+                rules={[
+                  {
+                    required: true,
+                    message: '请填写作废原因',
+                  },
+                ]}
               >
-                <Input.TextArea />
+                <Input disabled={type != Type.cancel} />
               </Form.Item>
+            </>
+          )}
+          {type == Type.cancel && (
+            <Form.Item
+              name="cancel_on"
+              label="创建时间:"
+              initialValue={dayjs().format(FORMAT)}
+              labelCol={{ span: 4 }}
+            >
+              <Input
+                style={{ width: '460px' }}
+                defaultValue={dayjs().format('YYYY-MM-DD')}
+                disabled
+              />
+              <span
+                style={{ color: 'red', fontSize: '24px', marginLeft: '40px' }}
+              >
+                确认作废该合同,作废提交后无法撤回
+              </span>
+            </Form.Item>
+          )}
+          {data?.status >= Status.CalChecking && (
+            <>
+              <ModuleTitle title="作废流程" />
+              <div className={styles.modelItem}>
+                <AuditSteps {...auditCelData} statusText="已作废" />
+              </div>
+            </>
+          )}
+          {isSuper && data.status == Status.CalChecking && (
+            <>
+              <ModuleTitle title="审核情况" />
+              <Row>
+                <Col span={10} offset={1}>
+                  <Form.Item
+                    name="cancel_check_by"
+                    initialValue={user?.CName}
+                    label="审核人:"
+                  >
+                    <Input disabled />
+                  </Form.Item>
+                  <Form.Item name="is_pass" initialValue={1} label="审核意见:">
+                    <Select
+                      onChange={(e) => {
+                        setIsPass(e);
+                      }}
+                      style={{ width: '100%' }}
+                      options={[
+                        {
+                          value: 1,
+                          label: '同意',
+                        },
+                        {
+                          value: 0,
+                          label: '拒绝',
+                        },
+                      ]}
+                    />
+                  </Form.Item>
+                </Col>
+                <Col span={10}>
+                  <Form.Item
+                    name="check_date"
+                    initialValue={dayjs().format(FORMAT)}
+                    label="审核时间:"
+                  >
+                    <Input disabled />
+                  </Form.Item>
+                </Col>
+              </Row>
+              {!isPass && (
+                <Form.Item
+                  name="cancel_check_result"
+                  label="拒绝原因:"
+                  labelCol={{ span: 4 }}
+                >
+                  <Input.TextArea />
+                </Form.Item>
+              )}
+            </>
+          )}
+          {(type == Type.add || data?.status == Status.ReCall) &&
+            auditList.length > 0 && (
+              <>
+                <ModuleTitle title="审批流程" />
+                <div className={styles.modelItem}>
+                  <Steps
+                    current={1}
+                    items={auditList.map((item, index) => {
+                      return {
+                        title: `审批${index + 1}`,
+                        description: `审批人:${item.name}`,
+                      };
+                    })}
+                  />
+                </div>
+              </>
             )}
-          </>
-        )}
-      </Form>
-      <Divider />
-    </Modal>
+        </Form>
+        <Divider />
+      </Modal>
+      <FileViewerModal
+        data={fileViewerData}
+        visible={fileViewerVisible}
+        onCancel={() => {
+          setFileViewerVisible(false);
+        }}
+      />
+    </>
   );
 };
 export default ContractModal;

+ 152 - 44
src/pages/ContractManager/index.jsx

@@ -22,7 +22,9 @@ import {
   queryContractCancelCheck,
   queryContractCheck,
   queryContractDownload,
+  queryDelById,
   queryGetContractList,
+  queryOAReCall,
 } from '../../services/contract';
 import dayjs from 'dayjs';
 import FileViewerModal from '@/components/FileViewerNew';
@@ -30,6 +32,8 @@ import { getToken } from '@/utils/utils';
 import PageContent from '@/components/PageContent';
 import EllipsisText from './component/EllipsisText';
 import { stringify } from 'qs';
+import { audit, createAduit } from '@/services/boom';
+import { ExclamationCircleOutlined } from '@ant-design/icons';
 
 const ConteactManager = (props) => {
   const { dispatch } = props;
@@ -88,6 +92,7 @@ const ConteactManager = (props) => {
       dataIndex: 'name',
       key: 'name',
       align: 'center',
+      width: 100,
     },
     {
       title: '甲方',
@@ -152,27 +157,36 @@ const ConteactManager = (props) => {
       width: 100,
       render: (status) => {
         let str = '';
+        let color = 'black';
         switch (status) {
-          case 1:
+          case Status.ReCall:
+            str = '待提交';
+            break;
+          case Status.Checking:
             str = '待审核';
+            color = 'blue';
             break;
-          case 2:
+          case Status.CheckReject:
             str = '审核拒绝';
+            color = 'red';
             break;
-          case 3:
+          case Status.CheckSuccess:
             str = '已存档';
+            color = 'green';
             break;
-          case 4:
+          case Status.CalChecking:
             str = '作废待审核';
+            color = 'blue';
             break;
-          case 5:
+          case Status.CalCheckReject:
             str = '作废拒绝';
+            color = 'red';
             break;
-          case 6:
+          case Status.CalCheckSuccess:
             str = '已作废';
             break;
         }
-        return <div>{str}</div>;
+        return <div style={{ color }}>{str}</div>;
       },
     },
     {
@@ -196,19 +210,7 @@ const ConteactManager = (props) => {
             {showBtn(record, 'download') && (
               <a onClick={() => handleUpload(record)}>下载</a>
             )}
-            {/* {showBtn(record, 'addOrCal') && !record.parent_id && (
-              <a
-                onClick={() => {
-                  typeRef.current = Type.add;
-                  parentIdRef.current = record.id;
-                  setDetail({});
-                  setVisible(true);
-                }}
-              >
-                增补
-              </a>
-            )} */}
-            {record.status == 3 && (
+            {record.status == Status.CheckSuccess && (
               <a
                 onClick={() => {
                   typeRef.current = Type.cancel;
@@ -219,6 +221,10 @@ const ConteactManager = (props) => {
                 作废
               </a>
             )}
+            {(record.status == Status.ReCall ||
+              record.status == Status.CheckReject) && (
+              <a onClick={() => handleDelete(record.id)}>删除</a>
+            )}
           </Space>
         );
       },
@@ -279,21 +285,58 @@ const ConteactManager = (props) => {
     },
   });
 
-  //作废审核
-  const { run: calCheckRun } = useRequest(
-    (data) => queryContractCancelCheck(data),
-    {
-      manual: true,
-      onSuccess: () => {
-        message.success('审核成功');
-        setVisible(false);
+  // //作废审核
+  // const { run: calCheckRun } = useRequest(
+  //   (data) => queryContractCancelCheck(data),
+  //   {
+  //     manual: true,
+  //     onSuccess: () => {
+  //       message.success('审核成功');
+  //       setVisible(false);
+  //       run(searchData);
+  //     },
+  //     onError: () => {
+  //       message.success('审核失败');
+  //     },
+  //   },
+  // );
+
+  // //审核合同
+  // const { run: runCheck, loading: checkLoading } = useRequest(
+  //   (data) => queryContractCheck(data),
+  //   {
+  //     manual: true,
+  //     onSuccess: () => {
+  //       // conAuditRun({ multi_status: '1,4', currentPage: 1, page_size: 10 });
+  //       // conAuditedRun({ check_by: user.CName });
+  //       setVisible(false);
+  //       run(searchData);
+  //       message.success('审核成功');
+  //     },
+  //     onErroe: () => {
+  //       message.error('审核失败');
+  //     },
+  //   },
+  // );
+
+  //审核合同
+  const { run: runOACheck } = useRequest(audit, {
+    manual: true,
+    onSuccess: (data) => {
+      if (data?.Code) {
+        message.error(data?.Msg || '审核失败');
+        return;
+      }
+      setTimeout(() => {
         run(searchData);
-      },
-      onError: () => {
-        message.success('审核失败');
-      },
+      }, 1000);
+      setVisible(false);
+      message.success('审核成功');
     },
-  );
+    onErroe: () => {
+      message.error('审核失败');
+    },
+  });
 
   //审核合同
   const { run: runCheck, loading: checkLoading } = useRequest(
@@ -318,12 +361,49 @@ const ConteactManager = (props) => {
     defaultParams: [{ pageSize: 99999 }],
   });
 
-  const handlePreView = (record) => {
-    if (!record.attach) return;
-    const attach = JSON.parse(record.attach);
-    setFileViewerData(attach);
+  //发起OA审批
+  const { run: createRun } = useRequest(
+    (data) => createAduit({ ...data, flow_id: 40, cc_list: [], files: '' }),
+    {
+      manual: true,
+    },
+  );
+
+  const handleDelete = (id) => {
+    modal.confirm({
+      icon: <ExclamationCircleOutlined />,
+      title: '提示:',
+      content: <div>确定删除合同,删除后不可回复!</div>,
+      onOk: async () => {
+        const res = await queryDelById({ id });
+        if (res.code == 200) {
+          message.success('删除成功');
+          run(searchData);
+        } else {
+          message.success('删除失败,请重试');
+        }
+      },
+    });
+  };
+  const handlePreView = (data) => {
+    if (!data?.attach && !data?.attach_extend) return;
+    const result = [];
+    if (data?.attach) {
+      const attach = JSON.parse(data?.attach);
+      attach.forEach((item) => {
+        result.push({ ...item, type: '合同及合同附件' });
+      });
+    }
+    if (data?.attach_extend) {
+      const attach_extend = JSON.parse(data?.attach_extend);
+      attach_extend.forEach((item) => {
+        result.push({ ...item, type: '合同相关资料' });
+      });
+    }
+    setFileViewerData(result);
     setFileViewerVisible(true);
   };
+
   //单个合同下载
   const handleUpload = (record) => {
     const token = getToken();
@@ -357,23 +437,50 @@ const ConteactManager = (props) => {
       if (idx > -1) {
         resultData[idx].children = res?.data?.list;
         setData(resultData);
-        setPagination(res.data?.pagination);
-        // setData({ list: resultData, pagination: res.data?.pagination });
       }
     }
   };
 
-  const handleOk = (data, type) => {
+  const handleOk = (data, type, formData = [], audit_list = []) => {
     if (type == Type.add) {
       editRun(data);
+      createRun({
+        form: JSON.stringify(formData),
+        audit_list,
+        extend_code: data.code,
+        extend_type: 0, //归档提交
+      });
     } else if (type == Type.cancel) {
       calRun(data);
-    } else if (type == Status.Checking) {
-      runCheck(data);
-    } else if (type == Status.CalChecking) {
-      calCheckRun(data);
+      createRun({
+        form: JSON.stringify(formData),
+        audit_list,
+        extend_code: data.code,
+        extend_type: 1, //作废提交
+      });
+    } else if (type == Type.check) {
+      runOACheck(data);
     }
   };
+
+  const handlerReCall = async (id) => {
+    modal.confirm({
+      icon: <ExclamationCircleOutlined />,
+      title: '提示:',
+      content: <div>确定撤回合同存档审批!</div>,
+      onOk: async () => {
+        const res = await queryOAReCall(id);
+        if (res.code == 200) {
+          message.success('撤回成功');
+          setVisible(false);
+          run(searchData);
+        } else {
+          message.success('撤回失败,请重试');
+        }
+      },
+    });
+  };
+
   const onPageChange = (page) => {
     run({ ...searchData, current: page });
   };
@@ -491,6 +598,7 @@ const ConteactManager = (props) => {
         visible={visible}
         handleOk={handleOk}
         handleCancel={() => setVisible(false)}
+        handlerReCall={handlerReCall}
       />
       <FileViewerModal
         data={fileViewerData}

+ 2 - 1
src/pages/Flow/AuditModal.js

@@ -2,9 +2,10 @@ import React, { useEffect } from 'react';
 import { Modal, Input, Form, Select } from 'antd';
 
 const flowTypeList = [
+  { value: 0, label: 'BOM审批' },
   { value: 1, label: '文档审批' },
   { value: 2, label: 'OA审批' },
-  { value: 3, label: '合同审批' },
+  { value: 3, label: '合同归档审批' },
 ];
 
 // 审批意见

+ 41 - 4
src/pages/Flow/OaAuditDetail.js

@@ -1,15 +1,17 @@
 // 审批详情
-import React, { useEffect, useState, useRef, useMemo } from 'react';
-import { Steps, Button, Tooltip } from 'antd';
-import { useParams, useRequest, useNavigate, useModel } from 'umi';
+import React, { useState, useMemo } from 'react';
+import { Steps, Button, Tooltip, message } from 'antd';
+import { useParams, useRequest, useModel } from 'umi';
 import AuditModal from './components/AuditModal';
 import FormAndFilesNode from './components/FormAndFilesNode';
-import { queryAuditDetail, audit } from '@/services/boom';
+import { queryAuditDetail, updateAuditList } from '@/services/boom';
 import PageContent from '@/components/PageContent';
+import SignModal from './components/SignModal';
 
 function OaAuditDetail(props) {
   const [auditVisible, setAuditVisible] = useState(false);
   const { oaId, id } = useParams();
+  const [visible, setVisible] = useState(false);
 
   const { data, loading, refresh } = useRequest(queryAuditDetail, {
     defaultParams: [{ id }],
@@ -22,6 +24,7 @@ function OaAuditDetail(props) {
     audit_status,
     AuditorInfo,
   } = data || {};
+  if (OaAuditList) console.log(JSON.stringify(OaAuditList));
   const {
     initialState: { user },
   } = useModel('@@initialState');
@@ -46,6 +49,31 @@ function OaAuditDetail(props) {
     }
     return str;
   };
+  const updateRes = useRequest(
+    (values) => {
+      let list = OaAuditList.map((item) => item.auditor);
+      if (values.type == 'before') {
+        list.splice(current_seq - 1, 0, values.approver);
+      } else {
+        list.splice(current_seq, 0, values.approver);
+      }
+      return updateAuditList(
+        {
+          oa_id: Number(id),
+          audit_list: list,
+        },
+        values.type == 'after',
+      );
+    },
+    {
+      manual: true,
+      onSuccess() {
+        message.success('加签成功');
+        setVisible(false);
+        refresh();
+      },
+    },
+  );
 
   const btns = useMemo(() => {
     if (!user || !data) return;
@@ -66,6 +94,9 @@ function OaAuditDetail(props) {
         <Button key={2} onClick={() => setAuditVisible(2)} danger>
           审批拒绝
         </Button>,
+        <Button key={3} onClick={() => setVisible(true)}>
+          加签
+        </Button>,
       ];
     }
     return [];
@@ -90,6 +121,12 @@ function OaAuditDetail(props) {
         onClose={() => setAuditVisible(false)}
         onOk={refresh}
       />
+      <SignModal
+        visible={visible}
+        onCancel={() => setVisible(false)}
+        onCreate={(values) => updateRes.run(values)}
+        loading={updateRes.loading}
+      />
     </PageContent>
   );
 }

+ 13 - 7
src/pages/Flow/OaDetail.js

@@ -16,6 +16,7 @@ import { useParams, useRequest, useNavigate } from 'umi';
 const OaDetail = () => {
   const [form] = Form.useForm();
   const [approvalProcess, setApprovalProcess] = useState([]);
+  const [auditCheck, setAuditCheck] = useState([]);
   const { oaId } = useParams();
   const formValueRef = useRef({
     form: '',
@@ -89,14 +90,17 @@ const OaDetail = () => {
   const submit = () => {
     form.validateFields().then((values) => {
       const { form: formCur } = formValueRef.current;
-      let audit_list = [];
-      approvalProcess?.forEach((item) => {
-        if (item[0].type == 'role') audit_list.push(item[0].nowValue);
+      let audit_list = [],
+        cc_list = [];
+      approvalProcess?.forEach((item, index) => {
+        let arr = item[0].is_cc == 1 ? cc_list : audit_list;
+
+        if (item[0].type == 'role') arr.push(auditCheck[index]);
         else if (item[0].type == 'leader')
-          audit_list.push(
+          arr.push(
             ...leaderData.slice(0, item[0].value).map((leader) => leader.ID),
           );
-        else audit_list.push(item[0].value);
+        else arr.push(item.map((cur) => cur.value));
       });
       let files = [],
         formData = [];
@@ -107,10 +111,12 @@ const OaDetail = () => {
           formData.push(item);
         }
       });
+      console.log(audit_list, cc_list);
       createRun({
         flow_id: Number(oaId),
         form: JSON.stringify(formData),
-        audit_list,
+        audit_list: audit_list.flat(),
+        cc_list: cc_list.flat(),
         files: files.join(','),
       });
     });
@@ -153,7 +159,7 @@ const OaDetail = () => {
             <ApprovalProcess
               leaderData={leaderData}
               approvalProcess={approvalProcess}
-              onChange={setApprovalProcess}
+              onChange={setAuditCheck}
             />
           )}
         </Col>

+ 233 - 114
src/pages/Flow/components/ApprovalProcess.tsx

@@ -1,85 +1,145 @@
-import React, { useEffect, useMemo, useState } from 'react';
+import React, { CSSProperties, useEffect, useMemo, useState } from 'react';
 import { queryUserListByRoleID, queryLeader } from '@/services/boom';
 import { connect } from 'umi';
-import { PlusOutlined } from '@ant-design/icons';
-import { Popover, Radio, RadioChangeEvent, Spin, Steps } from 'antd';
+import {
+  CheckOutlined,
+  PlusOutlined,
+  PlusSquareOutlined,
+} from '@ant-design/icons';
+import {
+  Popover,
+  Radio,
+  RadioChangeEvent,
+  Space,
+  Spin,
+  Steps,
+  Timeline,
+  Checkbox,
+} from 'antd';
 import { useModel, useRequest } from '@umijs/max';
+import { CheckboxValueType } from 'antd/es/checkbox/Group';
 
 const { Step } = Steps;
 
-enum TYPE {
-  ROLE = 'role',
-  USER = 'user',
-  LEADER = 'leader',
+const TYPE = {
+  ROLE: 'role',
+  USER: 'user',
+  LEADER: 'leader',
+} as const;
+
+interface AuditNode {
+  is_cc: 0 | 1;
+  seq: number;
+  type: (typeof TYPE)[keyof typeof TYPE];
+  value: number[];
+  checkValue: [];
+  label: string;
 }
 
 const ApprovalProcess = (props: any) => {
   const {
     approvalProcess,
-    leaderData,
+    leaderData = [],
     dispatch,
     onChange,
     roleList = [],
   } = props;
-  const [selectUserList, setSelectUserList] = useState([]);
-  const [curNodeIdx, setCurNodeIdx] = useState(-1);
-  const [loading, setLoading] = useState(false);
   const { userList, run } = useModel('userList');
+  const [checkValue, setCheckValue] = useState<number[][]>([]);
 
-  const list = useMemo(() => {
-    approvalProcess
-      ?.filter((item: any) => item)
-      .forEach((item: any) => {
-        if (item.length > 1 && item[0].type == TYPE.USER) {
-          item.forEach((curUser: any) => {
-            curUser.name =
-              userList?.find((user: any) => user.ID == curUser.value)?.CName ||
-              '-';
-          });
-        } else if (item.length == 1 && item[0].type == TYPE.USER) {
-          item[0].name =
-            userList?.find((user: any) => user.ID == item[0].value)?.CName ||
-            '-';
-        } else if (item.length == 1 && item[0].nowType == TYPE.USER) {
-          item[0].name =
-            userList?.find((user: any) => user.ID == item[0].nowValue)?.CName ||
-            '-';
-        } else {
-          item[0].name = null;
-        }
-      });
-    return approvalProcess?.filter((item: any) => item);
+  const { auditList, ccList } = useMemo<{
+    auditList: AuditNode[];
+    ccList: AuditNode[];
+  }>(() => {
+    let auditList: AuditNode[] = [],
+      ccList: AuditNode[] = [];
+    approvalProcess.forEach((item: any, index: number) => {
+      if (!item) return;
+      let node: AuditNode = {
+        is_cc: item[0].is_cc,
+        type: item[0].type,
+        checkValue: [],
+        seq: index,
+        label: item[0].label,
+        value: item.map((node: any) => node.value),
+      };
+
+      if (node.is_cc == 1) {
+        ccList.push(node);
+      } else {
+        auditList.push(node);
+      }
+    });
+    return { auditList, ccList };
   }, [approvalProcess]);
 
-  const onStepsChange = async (current: any, list: any) => {
-    setLoading(true);
-    const itemNode = list[current][0];
-    if (itemNode.type !== 'role') return;
-    const data = await queryUserListByRoleID({ role_id: itemNode.value });
-    setCurNodeIdx(current);
-    setSelectUserList(data);
-    setLoading(false);
+  const onCheckValue = (value: number[], index: number) => {
+    let values = [...checkValue];
+    values[index] = value;
+    setCheckValue(values);
+    onChange(values);
   };
 
-  const selectedUserId = ({ target: { value } }: RadioChangeEvent) => {
-    //userId
-    const name = userList?.find((user: any) => user.ID == value)?.CName || '-';
-    const data = { nowType: TYPE.USER, nowValue: Number(value), name }; //type: TYPE.USER, value: Number(value)
-    list[curNodeIdx][0] = { ...list[curNodeIdx][0], ...data };
-    console.log([...list]);
-    onChange?.([...list]);
+  useEffect(() => {
+    dispatch({
+      type: 'user/getRoleList',
+    });
+    run();
+  }, []);
+  const rowStyle: CSSProperties = {
+    display: 'flex',
+    flexDirection: 'column',
+    fontSize: 16,
   };
 
-  const content = (
-    <Spin spinning={loading}>
-      <Radio.Group onChange={selectedUserId}>
-        {selectUserList.map((item: any) => (
-          // <Button onClick={() => selectedUserId(item.user_id)}>{item.c_name}</Button>
-          <Radio.Button value={item.user_id}>{item.c_name}</Radio.Button>
-        ))}
-      </Radio.Group>
-    </Spin>
+  const renderAudits = (list: AuditNode[]) => {
+    return list.map((item: AuditNode, index: number) => {
+      return {
+        children: (
+          <AuditNodeStep
+            key={`${item.type}-${item.value.join('.')}-${index}`}
+            leaderData={leaderData}
+            item={item}
+            roleList={roleList}
+            userList={userList}
+            value={checkValue[item.seq]}
+            onChange={(value: number[]) => onCheckValue(value, item.seq)}
+          />
+        ),
+      };
+    });
+  };
+
+  return (
+    <div>
+      <Timeline items={renderAudits(auditList)}></Timeline>
+
+      {ccList.length > 0 && <Timeline items={renderAudits(ccList)}></Timeline>}
+    </div>
   );
+};
+
+interface AuditNodeStepProps {
+  item: AuditNode;
+  leaderData: any;
+  roleList: any;
+  userList: any;
+  value: number[];
+  onChange: (value: number[]) => void;
+}
+
+const AuditNodeStep = (props: AuditNodeStepProps) => {
+  const {
+    item,
+    leaderData,
+    roleList = [],
+    userList = [],
+    value,
+    onChange,
+  } = props;
+
+  const [selectUserList, setSelectUserList] = useState([]);
+  const [loading, setLoading] = useState(false);
 
   const getLeaderContent = (length: any) => (
     <Steps
@@ -92,67 +152,126 @@ const ApprovalProcess = (props: any) => {
     ></Steps>
   );
 
-  useEffect(() => {
-    dispatch({
-      type: 'user/getRoleList',
+  const handleOpen = async () => {
+    setLoading(true);
+    if (item.type !== 'role') return;
+    const data = await queryUserListByRoleID({ role_id: item.value[0] });
+    setSelectUserList(data);
+    setLoading(false);
+  };
+
+  const selectedUserId = (list: CheckboxValueType[]) => {
+    onChange(list as number[]);
+  };
+
+  const content = (
+    <Spin spinning={loading}>
+      <Checkbox.Group
+        style={{ display: 'block' }}
+        onChange={selectedUserId}
+        value={value as any}
+      >
+        {selectUserList
+          .filter((item: any) => item.c_name)
+          .map((item: any) => (
+            <Checkbox
+              style={{ whiteSpace: 'nowrap' }}
+              key={item.user_id}
+              value={Number(item.user_id)}
+            >
+              {item.c_name}
+            </Checkbox>
+          ))}
+      </Checkbox.Group>
+    </Spin>
+  );
+
+  if (item.type == TYPE.LEADER) {
+    return (
+      <div style={{ marginBottom: 20 }}>
+        <Popover
+          placement="bottomLeft"
+          title="查看审批人"
+          content={getLeaderContent(item.value[0])}
+          overlayStyle={{ width: '300px' }}
+        >
+          <CheckOutlined style={{ marginRight: 20 }} />
+          {Math.min(item.value[0], leaderData?.length)}级主管审批
+        </Popover>
+      </div>
+    );
+  }
+  if (item.type == TYPE.ROLE) {
+    let label = item.label || '';
+    const names = item.value.map((id) => {
+      const role = roleList.find((cur: any) => cur.ID == id);
+      return role?.Name;
     });
-    run();
-  }, []);
+    let title = `从${names.join('、')}选择`;
+    let userNames = [];
+    if (value?.length > 0) {
+      userNames = value.map(
+        (id: number) => userList.find((cur: any) => cur.ID == id)?.CName,
+      );
+    }
+    return (
+      <div
+        style={{
+          marginBottom: 20,
+          cursor: 'pointer',
+          display: 'flex',
+          justifyContent: 'space-between',
+        }}
+      >
+        <div>
+          <div style={{ fontSize: '18px' }}>{label}</div>
+          <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
+        </div>
+        <Popover
+          placement="bottomLeft"
+          title={'选择审批人'}
+          content={content}
+          trigger="click"
+          overlayStyle={{ width: '300px' }}
+          onOpenChange={handleOpen}
+          style={{ marginBottom: 20, overflow: 'auto' }}
+        >
+          <Space>
+            {userNames.join('、')}
+            <PlusSquareOutlined style={{ fontSize: '36px', color: 'gray' }} />
+          </Space>
+        </Popover>
+      </div>
+    );
+  }
+
+  let label = item.label || '';
+
+  let title = item.is_cc
+    ? `抄送${item.value.length}人`
+    : `${item.value.length}人审批`;
+  const names = item.value.map((id) => {
+    const user = userList.find((cur: any) => cur.ID == id);
+    return user?.CName;
+  });
 
   return (
-    <>
-      <Steps
-        current={-1}
-        direction="vertical"
-        onChange={(value) => onStepsChange(value, list)}
-      >
-        {list?.map((item: any, index: Number) =>
-          item[0]?.type == TYPE.LEADER ? (
-            <Step
-              key={String(index)}
-              icon={
-                <Popover
-                  placement="bottomLeft"
-                  title="查看审批人"
-                  content={getLeaderContent(item[0]?.value)}
-                  overlayStyle={{ width: '300px' }}
-                >
-                  <PlusOutlined />
-                </Popover>
-              }
-              title={`${Math.min(
-                item[0]?.value,
-                leaderData?.length,
-              )}级主管审批`}
-            />
-          ) : (
-            <Step
-              key={String(index)}
-              icon={
-                <Popover
-                  placement="bottomLeft"
-                  title={'选择审批人'}
-                  content={content}
-                  trigger="click"
-                  overlayStyle={{ width: '300px' }}
-                >
-                  <PlusOutlined />
-                </Popover>
-              }
-              title={
-                item[0]?.name ||
-                `从${
-                  roleList?.find((cur: any) => cur.ID == item[0]?.value)
-                    ?.Name || '-'
-                }选择`
-              }
-            />
-          ),
-        )}
-      </Steps>
-    </>
+    <div
+      style={{
+        marginBottom: 20,
+        display: 'flex',
+        justifyContent: 'space-between',
+      }}
+    >
+      <div>
+        <div style={{ fontSize: '18px' }}>{label}</div>
+        <div style={{ fontSize: '14px', color: 'gray' }}>{title}</div>
+      </div>
+      {names.join('、')}
+    </div>
   );
 };
+
 export default connect(({ user }: any) => ({
   roleList: user.roleList,
 }))(ApprovalProcess);

+ 0 - 1
src/pages/Flow/components/AuditDetailed.js

@@ -20,7 +20,6 @@ const AuditDetailed = (props) => {
           return linked ? Object.values(linked).flat() : [];
         })
         .flat() || [];
-    console.log(linkedData, linkedList);
     return { linkedData, linkedList };
   }, [items]);
 

+ 62 - 0
src/pages/Flow/components/SignModal.js

@@ -0,0 +1,62 @@
+import React from 'react';
+import { Modal, Form, Radio, Select, Button } from 'antd';
+import { useModel, useRequest } from '@umijs/max';
+
+const { Option } = Select;
+
+const SignModal = ({ visible, onCancel, onCreate, loading }) => {
+  const [form] = Form.useForm();
+  const { userList } = useModel('userList');
+
+  const handleOk = () => {
+    form.validateFields().then((values) => {
+      onCreate(values);
+    });
+  };
+
+  return (
+    <Modal
+      open={visible}
+      title="加签"
+      onCancel={onCancel}
+      onOk={handleOk}
+      destroyOnClose
+      confirmLoading={loading}
+    >
+      <Form form={form} layout="vertical">
+        <Form.Item
+          name="type"
+          label="加签类型"
+          initialValue={'before'}
+          rules={[{ required: true, message: '请选择加签类型' }]}
+        >
+          <Radio.Group>
+            <Radio value="before">前加</Radio>
+            <Radio value="after">后加</Radio>
+          </Radio.Group>
+        </Form.Item>
+        <Form.Item
+          name="approver"
+          label="审批人"
+          rules={[{ required: true, message: '请选择审批人' }]}
+        >
+          <Select
+            showSearch
+            filterOption={(input, option) =>
+              (option.children ?? '').toLowerCase().includes(input.toLowerCase())
+            }
+            placeholder="请选择审批人"
+          >
+            {userList?.map((item) => (
+              <Option value={item.ID} key={item.ID}>
+                {item.CName}
+              </Option>
+            ))}
+          </Select>
+        </Form.Item>
+      </Form>
+    </Modal>
+  );
+};
+
+export default SignModal;

+ 2 - 2
src/pages/Flow/index.js

@@ -27,7 +27,7 @@ function Audit(props) {
     {
       title: '分类',
       dataIndex: 'classify_id',
-      render: (id) => classify?.find((item) => item.id == id)?.name || '-',
+      render: (id) => classify?.find((item) => item.id == id)?.name || 'BOM',
     },
     {
       title: '操作',
@@ -140,7 +140,7 @@ function Audit(props) {
     dispatch({
       type: 'flow/queryAuditList',
       payload: {
-        flow_type: 1,
+        flow_type: 'all',
       },
     });
     dispatch({

+ 198 - 114
src/pages/ManufacturerMng/ManufacturerList.js

@@ -1,5 +1,17 @@
 import React, { Fragment, useState, useEffect, useRef, useMemo } from 'react';
-import { Table, Icon, message, Spin, Button, Form, DatePicker, Modal, Divider, Select, Input } from 'antd';
+import {
+  Table,
+  Icon,
+  message,
+  Spin,
+  Button,
+  Form,
+  DatePicker,
+  Modal,
+  Divider,
+  Select,
+  Input,
+} from 'antd';
 import { useRequest, useModel } from '@umijs/max';
 import FirmModal from './ManufacturerModal';
 import dayjs from 'dayjs';
@@ -11,57 +23,72 @@ import {
   queryCreaterList,
   editMfr,
   deleteMfr,
-  saveMfr
-} from '@/services/manufacturer'
+  saveMfr,
+} from '@/services/manufacturer';
 function ManufacturerList(props) {
+  const { projectId = 1, data } = props;
   const {
-    projectId = 1,
-    data,
-  } = props;
-  const { initialState: { user } } = useModel('@@initialState');
+    initialState: { user },
+  } = useModel('@@initialState');
   const [visible, setVisible] = useState(false);
   const [curItem, setCurItem] = useState(null);
   const [formDisabled, setFormDisabled] = useState(false);
   const [typeDisabled, setTypeDisabled] = useState(false);
   const [total, setTotal] = useState(0);
-  const [formData, setFormData] = useState({ start_time: "", end_time: "", project_id: projectId * 1, is_super: user?.IsSuper || false, page: 1, page_size: pageSize });
+  const [formData, setFormData] = useState({
+    start_time: '',
+    end_time: '',
+    project_id: projectId * 1,
+    is_super: user?.IsSuper || false,
+    page: 1,
+    page_size: pageSize,
+  });
   const queryMfrListRequest = useRequest(queryMfrList, {
     manual: true,
-    onSuccess: data => {
+    onSuccess: (data) => {
       console.log(data);
-      setFormData({ ...formData, page_size: pageSize })
+      setFormData({ ...formData, page_size: pageSize });
       setTotal(data.count);
-    }
+    },
   });
   const queryCreaterListRequest = useRequest(queryCreaterList, {});
   const saveMfrRequest = useRequest(saveMfr, {
     manual: true,
     onSuccess: () => {
       message.success('新增成功');
-      queryList({ ...formData, page: 1 })
-      queryCreaterListRequest.run({})
-    }
+      queryList({ ...formData, page: 1 });
+      queryCreaterListRequest.run({});
+    },
   });
   const editMfrRequest = useRequest(editMfr, {
     manual: true,
     onSuccess: () => {
       message.success('编辑成功');
-      queryList({ ...formData, page: 1 })
-      queryCreaterListRequest.run({})
-    }
+      queryList({ ...formData, page: 1 });
+      queryCreaterListRequest.run({});
+    },
   });
   const deleteMfrRequest = useRequest(deleteMfr, {
     manual: true,
     onSuccess: () => {
       message.success('删除成功');
-      queryList({ ...formData, page: 1 })
-      queryCreaterListRequest.run({})
-    }
+      queryList({ ...formData, page: 1 });
+      queryCreaterListRequest.run({});
+    },
   });
   const loading = useMemo(() => {
-    var loading = queryMfrListRequest.loading || saveMfrRequest.loading || queryCreaterListRequest.loading || editMfrRequest.loading;
-    return loading
-  }, [queryMfrListRequest.loading, saveMfrRequest.loading, queryCreaterListRequest.loading, editMfrRequest.loading]);
+    var loading =
+      queryMfrListRequest.loading ||
+      saveMfrRequest.loading ||
+      queryCreaterListRequest.loading ||
+      editMfrRequest.loading;
+    return loading;
+  }, [
+    queryMfrListRequest.loading,
+    saveMfrRequest.loading,
+    queryCreaterListRequest.loading,
+    editMfrRequest.loading,
+  ]);
   const columns = [
     {
       title: '供应商(自然人)名称',
@@ -69,34 +96,34 @@ function ManufacturerList(props) {
     },
     {
       title: '主体类型',
-      render: record => {
-        if (record.type == 1) return '供应商'
-        if (record.type == 4) return '自然人'
+      render: (record) => {
+        if (record.type == 1) return '供应商';
+        if (record.type == 4) return '自然人';
       },
-      width: '6%'
+      width: '6%',
     },
     {
       title: '证件类型',
-      render: record => {
-        if (record.id_type == 1) return '身份证'
-        if (record.id_type == 2) return '护照'
+      render: (record) => {
+        if (record.id_type == 1) return '身份证';
+        if (record.id_type == 2) return '护照';
       },
-      width: '6%'
+      width: '6%',
     },
     {
       title: '证件号',
       dataIndex: 'id_card',
-      width: '12%'
+      width: '12%',
     },
     {
       title: '联系人',
-      render: record => record.contact || '-',
-      width: '6%'
+      render: (record) => record.contact || '-',
+      width: '6%',
     },
     {
       title: '联系方式',
-      render: record => record.phone_number || '-',
-      width: '10%'
+      render: (record) => record.phone_number || '-',
+      width: '10%',
       // render: (record) => {
       //   return moment(record.create_time).format('YYYY-MM-DD')
       // }
@@ -104,56 +131,72 @@ function ManufacturerList(props) {
     {
       title: '银行账号',
       dataIndex: 'bank_number',
-      width: '12%'
+      width: '12%',
     },
     {
       title: '创建人',
       dataIndex: 'created_by',
-      width: '6%'
+      width: '6%',
     },
     {
       title: '创建时间',
       render: (record) => {
-        return dayjs(record.created_on).format('YYYY-MM-DD')
+        return dayjs(record.created_on).format('YYYY-MM-DD');
       },
-      width: '8%'
+      width: '8%',
     },
     {
       title: '操作',
       render: (text, record) => (
         <Fragment>
           <>
-            <a style={{ color: "#4096ff" }} onClick={() => {
-              setCurItem(record);
-              setFormDisabled(false);
-              setTypeDisabled(true);
-              setVisible(true);
-            }}>编辑</a>
+            <a
+              style={{ color: '#4096ff' }}
+              onClick={() => {
+                setCurItem(record);
+                setFormDisabled(false);
+                setTypeDisabled(true);
+                setVisible(true);
+              }}
+            >
+              编辑
+            </a>
           </>
           <>
             <Divider type="vertical" />
-            <a style={{ color: "#4096ff" }} onClick={() => {
-              handleDeleteItem(record);
-            }}> 删除</a>
+            <a
+              style={{ color: '#4096ff' }}
+              onClick={() => {
+                handleDeleteItem(record);
+              }}
+            >
+              {' '}
+              删除
+            </a>
           </>
           <>
             <Divider type="vertical" />
-            <a style={{ color: "#4096ff" }} onClick={() => {
-              setCurItem(record);
-              setVisible(true);
-              setFormDisabled(true);
-            }}>详情</a>
+            <a
+              style={{ color: '#4096ff' }}
+              onClick={() => {
+                setCurItem(record);
+                setVisible(true);
+                setFormDisabled(true);
+              }}
+            >
+              详情
+            </a>
           </>
         </Fragment>
       ),
-      width: '12%'
+      width: '12%',
     },
   ];
   const onCancel = () => {
-    setVisible(false)
+    setVisible(false);
     setFormDisabled(false);
-  }
-  const handleDeleteItem = record => {
+  };
+  const handleDeleteItem = (record) => {
     console.log(record);
     Modal.confirm({
       title: '提醒',
@@ -161,18 +204,26 @@ function ManufacturerList(props) {
       okText: '确认',
       cancelText: '取消',
       onOk: () => {
-        deleteMfrRequest.run({ project_id: 1, id: record.id, deleted_by: user?.CName })
+        deleteMfrRequest.run({
+          project_id: 1,
+          id: record.id,
+          deleted_by: user?.CName,
+        });
       },
     });
-  }
+  };
   const handleExportChange = async () => {
     const data = {
       project_id: 1,
       is_super: user?.IsSuper || false,
       created_by: formData.created_by || '',
-      type: formData.type || undefined
+      type: formData.type || undefined,
     };
-    window.downloadFile(`/api/supplier/v1/supplier/export?${stringify(data)}`, '供应商列表.xlsx', false);
+    window.downloadFile(
+      `/api/supplier/v1/supplier/export?${stringify(data)}`,
+      '供应商列表.xlsx',
+      false,
+    );
   };
   const handleSearch = () => {
     console.log(formData);
@@ -185,50 +236,61 @@ function ManufacturerList(props) {
       is_super: user?.IsSuper || false,
       created_by: formData.created_by || '',
       name: formData.name || '',
-      type: formData.type * 1 || undefined
-    }
+      type: formData.type * 1 || undefined,
+    };
     queryList(value);
-  }
-  const queryList = fieldsValue => {
+  };
+  const queryList = (fieldsValue) => {
     console.log(fieldsValue);
     setFormData(fieldsValue);
     var isSuper = user?.IsSuper || false;
-    var created_by = isSuper ? fieldsValue.created_by || '' : user?.CName || undefined
-    queryMfrListRequest.run({ ...fieldsValue, created_by })
-  }
-  const onDateChange = data => {
+    var created_by = isSuper
+      ? fieldsValue.created_by || ''
+      : user?.CName || undefined;
+    queryMfrListRequest.run({ ...fieldsValue, created_by });
+  };
+  const onDateChange = (data) => {
     let start_time = '';
     let end_time = '';
     if (data?.length > 0) {
       start_time = dayjs(data[0]).format('YYYY-MM-DD');
       end_time = dayjs(data[1]).format('YYYY-MM-DD');
     }
-    setFormData({ ...formData, start_time: start_time, end_time: end_time })
-  }
-  const onOk = fieldsValue => {
+    setFormData({ ...formData, start_time: start_time, end_time: end_time });
+  };
+  const onOk = (fieldsValue) => {
     console.log(fieldsValue);
     setVisible(false);
     if (curItem != null)
-      editMfrRequest.run({ ...fieldsValue, project_id: 1, updated_by: user?.CName, id: curItem.id })
+      editMfrRequest.run({
+        ...fieldsValue,
+        project_id: 1,
+        updated_by: user?.CName,
+        id: curItem.id,
+      });
     else
-      saveMfrRequest.run({ ...fieldsValue, project_id: 1, created_by: user?.CName })
-  }
-  const onChange = name => {
-    setFormData({ ...formData, created_by: name })
-  }
-  const onTypeChange = type => {
-    setFormData({ ...formData, type: type })
-  }
-  const onPaginationChange = pagination => {
-    var tempFormData = { ...formData, page: pagination.current }
-    setFormData(tempFormData)
+      saveMfrRequest.run({
+        ...fieldsValue,
+        project_id: 1,
+        created_by: user?.CName,
+      });
+  };
+  const onChange = (name) => {
+    setFormData({ ...formData, created_by: name });
+  };
+  const onTypeChange = (type) => {
+    setFormData({ ...formData, type: type });
+  };
+  const onPaginationChange = (pagination) => {
+    var tempFormData = { ...formData, page: pagination.current };
+    setFormData(tempFormData);
     queryList(tempFormData);
-  }
-  const onInputChange = e => {
-    setFormData({ ...formData, name: e.target.value })
-  }
+  };
+  const onInputChange = (e) => {
+    setFormData({ ...formData, name: e.target.value });
+  };
   useEffect(() => {
-    queryList({ ...formData })
+    queryList({ ...formData });
   }, []);
   return (
     <>
@@ -239,30 +301,33 @@ function ManufacturerList(props) {
               <RangePicker onChange={onDateChange} />
             </Form.Item>
           </div>
-          {
-            user?.IsSuper && <div>
+          {user?.IsSuper && (
+            <div>
               <Form.Item label="主体类型:">
                 <Select
                   onChange={onTypeChange}
-                  options={
-                    [
-                      { value: 1, label: '供应商' },
-                      { value: 4, label: '自然人' },
-                    ]
-                  }
+                  options={[
+                    { value: 1, label: '供应商' },
+                    { value: 4, label: '自然人' },
+                  ]}
                   style={{ width: 180 }}
                   allowClear
                 />
               </Form.Item>
             </div>
-          }
+          )}
           <div style={{ margin: '0 24px' }}>
             <Form.Item label="名称:">
-              <Input placeholder="请输入供应商名称" onChange={e => { onInputChange(e) }} />
+              <Input
+                placeholder="请输入供应商名称"
+                onChange={(e) => {
+                  onInputChange(e);
+                }}
+              />
             </Form.Item>
           </div>
-          {
-            user?.IsSuper && <div>
+          {user?.IsSuper && (
+            <div>
               <Form.Item label="创建人:">
                 <Select
                   onChange={onChange}
@@ -272,32 +337,51 @@ function ManufacturerList(props) {
                 />
               </Form.Item>
             </div>
-          }
+          )}
           <div style={{ display: 'flex' }}>
             <Form.Item>
-              <Button style={{ marginLeft: 24 }} type="primary" onClick={() => { handleSearch() }}>
+              <Button
+                style={{ marginLeft: 24 }}
+                type="primary"
+                onClick={() => {
+                  handleSearch();
+                }}
+              >
                 查询
               </Button>
             </Form.Item>
-            <Button style={{ marginLeft: 10 }} loading={loading} type="primary" onClick={() => {
-              setCurItem(null);
-              setVisible(true);
-              setTypeDisabled(false);
-            }}>
+            <Button
+              style={{ marginLeft: 10 }}
+              loading={loading}
+              type="primary"
+              onClick={() => {
+                setCurItem(null);
+                setVisible(true);
+                setTypeDisabled(false);
+              }}
+            >
               新增
             </Button>
-            <Button style={{ marginLeft: 10 }} loading={loading} onClick={() => handleExportChange()} type="primary">
+            <Button
+              style={{ marginLeft: 10 }}
+              loading={loading}
+              onClick={() => handleExportChange()}
+              type="primary"
+            >
               导出
             </Button>
           </div>
         </div>
       </Form>
       <Table
-        rowKey='id'
+        rowKey="id"
         loading={loading}
         columns={columns}
         dataSource={queryMfrListRequest?.data?.list}
-        pagination={{ current: formData.page, total: total, page_size: pageSize }}
+        pagination={{
+          current: formData.page,
+          total: total,
+        }}
         onChange={onPaginationChange}
       />
       <FirmModal
@@ -310,7 +394,7 @@ function ManufacturerList(props) {
         typeDisabled={typeDisabled}
       ></FirmModal>
     </>
-  )
+  );
 }
 
-export default ManufacturerList;
+export default ManufacturerList;

+ 267 - 193
src/pages/ManufacturerMng/ManufacturerModal.js

@@ -1,5 +1,19 @@
 import React, { Fragment, useState, useEffect, useRef, useMemo } from 'react';
-import { Table, Icon, message, Spin, Button, Form, DatePicker, Row, Col, Modal, Input, Upload, Select } from 'antd';
+import {
+  Table,
+  Icon,
+  message,
+  Spin,
+  Button,
+  Form,
+  DatePicker,
+  Row,
+  Col,
+  Modal,
+  Input,
+  Upload,
+  Select,
+} from 'antd';
 import dayjs from 'dayjs';
 import { getToken, GetTokenFromUrl } from '@/utils/utils';
 const { RangePicker } = DatePicker;
@@ -12,7 +26,7 @@ function FirmModal(props) {
     item = null,
     disabled = true,
     form,
-    typeDisabled
+    typeDisabled,
   } = props;
   const [formRef] = Form.useForm();
   const [type, setType] = useState(item?.type || 1);
@@ -37,16 +51,16 @@ function FirmModal(props) {
     //   };
     //   onOk?.(values);
     // });
-  }
+  };
   const handleOnCancel = () => {
     formRef.resetFields();
-    onCancel?.()
-  }
-  const handleType = value => {
+    onCancel?.();
+  };
+  const handleType = (value) => {
     formRef.resetFields();
     formRef.setFieldValue('type', value);
     setType(value);
-  }
+  };
   const token = getToken() || GetTokenFromUrl();
   const uploadProps = {
     name: 'files',
@@ -55,7 +69,7 @@ function FirmModal(props) {
       'JWT-TOKEN': token,
     },
     showUploadList: false,
-    onChange: info => {
+    onChange: (info) => {
       if (info.file.status !== 'uploading') {
         console.log(info.file, info.fileList);
       }
@@ -68,142 +82,184 @@ function FirmModal(props) {
   };
   useEffect(() => {
     formRef.resetFields();
-    if (visible)
-      setType(item?.type || 1)
+    if (visible) setType(item?.type || 1);
   }, [visible]);
 
-  return <Modal
-    maskClosable={false}
-    open={visible}
-    destroyOnClose
-    onCancel={handleOnCancel}
-    onOk={handleOnOk}
-    forceRender
-    width='60%'
-    title={item == null ? '新增' : disabled ? '详情' : '编辑'}
-    footer={disabled ? null : undefined}
-  >
-    <div style={{ padding: 30 }}>
-      <Form
-        form={formRef}
-        // layout="inline"
-        labelCol={{ span: 4 }}
-        wrapperCol={{ span: 20 }}
-        preserve={false}
-        initialValues={{
-          name: item?.name || '',
-          tax_code: item?.tax_code || '',
-          contact: item?.contact || '',
-          phone_number: item?.phone_number || '',
-          bank_account: item?.bank_account || '',
-          bank_number: item?.bank_number || '',
-          address: item?.address || '',
-          type: item?.type || 1,
-          id_type: item?.id_type || '',
-          id_card: item?.id_card || ''
-        }}
-      >
-        <Row gutter={[48, 24]}>
-          <Col span={12}>
-            <Form.Item style={{ width: '100%' }} label="主体类型:" name='type' rules={
-              [
-                {
-                  required: true,
-                  message: '请选择主体类型',
-                }]}>
-              <Select disabled={disabled || typeDisabled} options={[
-                { value: 1, label: '供应商' },
-                { value: 4, label: '自然人' },
-              ]} placeholder="请选择主体类型" onChange={handleType}>
-              </Select>
-            </Form.Item>
-          </Col>
-        </Row>
-        {
-          type === 1 &&
-          <>
-            <Row gutter={[48, 24]}>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="名称:" name='name' rules={
-                  [
-                    {
-                      required: true,
-                      message: '请输入供应商名称',
-                    }]}>
-                  <Input disabled={disabled} placeholder="请输入供应商名称" />
-                </Form.Item>
-              </Col>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="税号:" name="tax_code" rules={[
-                  {
-                    required: true,
-                    message: '请输入税号',
-                  },
-                ]}>
-                  <Input disabled={disabled} placeholder="请输入税号" />
-                </Form.Item>
-              </Col>
-            </Row>
-            <Row gutter={[48, 24]}>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="联系人:" name="contact" rules={
-                  [
-                    {
-                      required: true,
-                      message: '请输入联系人',
-                    },
-                  ]
-                }>
-                  <Input disabled={disabled} placeholder="请输入联系人" />
-                </Form.Item>
-              </Col>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="联系电话:" name="phone_number" rules={[
-                  {
-                    required: true,
-                    message: '请输入联系电话',
-                  },
-                ]}>
-                  <Input disabled={disabled} placeholder="请输入联系电话" />
-                </Form.Item>
-              </Col>
-            </Row>
-            <Row gutter={[48, 24]}>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="开户银行:" name='bank_account' rules={[
-                  {
-                    required: true,
-                    message: '请输入开户银行',
-                  },
-                ]}>
-                  <Input disabled={disabled} placeholder="请输入开户银行" />
-                </Form.Item>
-              </Col>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="银行账号:" name='bank_number' rules={[
+  return (
+    <Modal
+      maskClosable={false}
+      open={visible}
+      destroyOnClose
+      onCancel={handleOnCancel}
+      onOk={handleOnOk}
+      forceRender
+      width="60%"
+      title={item == null ? '新增' : disabled ? '详情' : '编辑'}
+      footer={disabled ? null : undefined}
+    >
+      <div style={{ padding: 30 }}>
+        <Form
+          form={formRef}
+          // layout="inline"
+          labelCol={{ span: 4 }}
+          wrapperCol={{ span: 20 }}
+          preserve={false}
+          initialValues={{
+            name: item?.name || '',
+            tax_code: item?.tax_code || '',
+            contact: item?.contact || '',
+            phone_number: item?.phone_number || '',
+            bank_account: item?.bank_account || '',
+            bank_number: item?.bank_number || '',
+            address: item?.address || '',
+            type: item?.type || 1,
+            id_type: item?.id_type || '',
+            id_card: item?.id_card || '',
+          }}
+        >
+          <Row gutter={[48, 24]}>
+            <Col span={12}>
+              <Form.Item
+                style={{ width: '100%' }}
+                label="主体类型:"
+                name="type"
+                rules={[
                   {
                     required: true,
-                    message: '请输入银行账号',
+                    message: '请选择主体类型',
                   },
-                ]}>
-                  <Input disabled={disabled} placeholder="请输入银行账号" />
-                </Form.Item>
-              </Col>
-            </Row>
-            <Row>
-              <Col span={24}>
-                <Form.Item labelCol={{ span: 2 }}
-                  wrapperCol={{ span: 22 }} style={{ width: '100%' }} label="地址:" name='address' rules={[
-                    {
-                      required: true,
-                      message: '请输入地址',
-                    },
-                  ]}>
-                  <Input disabled={disabled} placeholder="请输入地址" />
-                </Form.Item>
-              </Col>
-            </Row>
-            {/* <Row gutter={[48, 24]}>
+                ]}
+              >
+                <Select
+                  disabled={disabled || typeDisabled}
+                  options={[
+                    { value: 1, label: '供应商' },
+                    { value: 4, label: '自然人' },
+                  ]}
+                  placeholder="请选择主体类型"
+                  onChange={handleType}
+                ></Select>
+              </Form.Item>
+            </Col>
+          </Row>
+          {type === 1 && (
+            <>
+              <Row gutter={[48, 24]}>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="名称:"
+                    name="name"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入供应商名称',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入供应商名称" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="税号:"
+                    name="tax_code"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入税号',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入税号" />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={[48, 24]}>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="联系人:"
+                    name="contact"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入联系人',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入联系人" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="联系电话:"
+                    name="phone_number"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入联系电话',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入联系电话" />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={[48, 24]}>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="开户银行:"
+                    name="bank_account"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入开户银行',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入开户银行" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="银行账号:"
+                    name="bank_number"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入银行账号',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入银行账号" />
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row>
+                <Col span={24}>
+                  <Form.Item
+                    labelCol={{ span: 2 }}
+                    wrapperCol={{ span: 22 }}
+                    style={{ width: '100%' }}
+                    label="地址:"
+                    name="address"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入地址',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入地址" />
+                  </Form.Item>
+                </Col>
+              </Row>
+              {/* <Row gutter={[48, 24]}>
           <Col span={12}>
             <div style={{ display: 'flex', alignItems: 'center' }}>
               <div style={{
@@ -263,59 +319,77 @@ function FirmModal(props) {
             </div>
           </Col>
         </Row> */}
-          </>
-        }
-        {
-          type === 4 && <>
-            <Row gutter={[48, 24]}>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="姓名:" name='name' rules={
-                  [
-                    {
-                      required: true,
-                      message: '请输入姓名',
-                    }]}>
-                  <Input disabled={disabled} placeholder="请输入姓名" />
-                </Form.Item>
-              </Col>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="证件类型:" name='id_type' rules={
-                  [
-                    {
-                      required: true,
-                      message: '请选择证件类型',
-                    }]}>
-                  <Select disabled={disabled} placeholder="请选择证件类型">
-                    <Option value={1}>身份证</Option>
-                    <Option value={2}>护照</Option>
-                  </Select>
-                </Form.Item>
-              </Col>
-            </Row>
-            <Row gutter={[48, 24]}>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="证件号:" name="id_card" rules={
-                  [
-                    {
-                      required: true,
-                      message: '请输入证件号',
-                    },
-                  ]
-                }>
-                  <Input disabled={disabled} placeholder="请输入证件号" />
-                </Form.Item>
-              </Col>
-              <Col span={12}>
-                <Form.Item style={{ width: '100%' }} label="银行账号:" name='bank_number'>
-                  <Input disabled={disabled} placeholder="请输入银行账号" />
-                </Form.Item>
-              </Col>
-            </Row>
-          </>
-        }
-      </Form>
-    </div>
-  </Modal>
+            </>
+          )}
+          {type === 4 && (
+            <>
+              <Row gutter={[48, 24]}>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="姓名:"
+                    name="name"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入姓名',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入姓名" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="证件类型:"
+                    name="id_type"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请选择证件类型',
+                      },
+                    ]}
+                  >
+                    <Select disabled={disabled} placeholder="请选择证件类型">
+                      <Option value={1}>身份证</Option>
+                      <Option value={2}>护照</Option>
+                    </Select>
+                  </Form.Item>
+                </Col>
+              </Row>
+              <Row gutter={[48, 24]}>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="证件号:"
+                    name="id_card"
+                    rules={[
+                      {
+                        required: true,
+                        message: '请输入证件号',
+                      },
+                    ]}
+                  >
+                    <Input disabled={disabled} placeholder="请输入证件号" />
+                  </Form.Item>
+                </Col>
+                <Col span={12}>
+                  <Form.Item
+                    style={{ width: '100%' }}
+                    label="银行账号:"
+                    name="bank_number"
+                  >
+                    <Input disabled={disabled} placeholder="请输入银行账号" />
+                  </Form.Item>
+                </Col>
+              </Row>
+            </>
+          )}
+        </Form>
+      </div>
+    </Modal>
+  );
 }
 
-export default FirmModal;
+export default FirmModal;

+ 60 - 42
src/pages/Profile/approve.js

@@ -16,7 +16,7 @@ import {
 import { PageContainer } from '@ant-design/pro-components';
 const { RangePicker } = DatePicker;
 import { useRequest, useModel } from '@umijs/max';
-import { queryProfileList, queryApplyList } from '@/services/boom';
+import { queryProfileList, queryApplyList, audit } from '@/services/boom';
 import dayjs from 'dayjs';
 import {
   queryContractCancelCheck,
@@ -100,41 +100,58 @@ function Approve(props) {
     },
   );
 
+  // //审核合同
+  // const { run: runCheck, loading: checkLoading } = useRequest(
+  //   (data) => queryContractCheck(data),
+  //   {
+  //     manual: true,
+  //     onSuccess: () => {
+  //       conAuditRun({ multi_status: '1,4', current: 1, page_size: 10 });
+  //       // conAuditedRun({ check_by: user.CName });
+  //       setConVisible(false);
+  //       message.success('审核成功');
+  //     },
+  //     onErroe: () => {
+  //       message.error('审核失败');
+  //     },
+  //   },
+  // );
+  // //作废审核
+  // const { run: calCheckRun } = useRequest(
+  //   (data) => queryContractCancelCheck(data),
+  //   {
+  //     manual: true,
+  //     onSuccess: () => {
+  //       message.success('审核成功');
+  //       setConVisible(false);
+  //       conAuditRun({ multi_status: '1,4', current: 1, page_size: 10 });
+  //     },
+  //     onError: () => {
+  //       message.success('审核失败');
+  //     },
+  //   },
+  // );
+
   //审核合同
-  const { run: runCheck, loading: checkLoading } = useRequest(
-    (data) => queryContractCheck(data),
-    {
-      manual: true,
-      onSuccess: () => {
-        conAuditRun({
-          multi_status: '1,4',
-          currentPage: 1,
-          page_size: 10,
-        });
-        // conAuditedRun({ check_by: user.CName });
-        setConVisible(false);
-        message.success('审核成功');
-      },
-      onErroe: () => {
-        message.error('审核失败');
-      },
+  const { run: runOACheck } = useRequest(audit, {
+    manual: true,
+    onSuccess: (data) => {
+      if (data?.Code) {
+        message.error(data?.Msg || '审核失败');
+        return;
+      }
+      setTimeout(() => {
+        conAuditRun({ multi_status: '1,4', current: 1, page_size: 10 });
+      }, 1000);
+
+      // conAuditedRun({ check_by: user.CName });
+      setConVisible(false);
+      message.success('审核成功');
     },
-  );
-  //作废审核
-  const { run: calCheckRun } = useRequest(
-    (data) => queryContractCancelCheck(data),
-    {
-      manual: true,
-      onSuccess: () => {
-        message.success('审核成功');
-        setConVisible(false);
-        conAuditRun({ multi_status: '1,4', currentPage: 1, page_size: 10 });
-      },
-      onError: () => {
-        message.success('审核失败');
-      },
+    onErroe: () => {
+      message.error('审核失败');
     },
-  );
+  });
 
   const applyData = useMemo(() => {
     let result = [];
@@ -147,7 +164,7 @@ function Approve(props) {
       OAAuditRun({ current: 1, page_size: 10 });
     } else {
       if (user?.Permission['menu-001-audit'])
-        conAuditRun({ multi_status: '1,4', currentPage: 1, page_size: 10 });
+        conAuditRun({ multi_status: '1,4', current: 1, page_size: 10 });
     }
     setTabActive(activeKey);
   };
@@ -158,13 +175,13 @@ function Approve(props) {
   const handleProfilePaginationChange = (pagination) => {
     conAuditRun({
       multi_status: user?.Permission['menu-001-audit'] ? '1,4' : undefined,
-      currentPage: pagination.current,
+      current: pagination.current,
       page_size: 10,
     });
   };
   const handleApplyPaginationChange = (pagination) => {
     OAAuditRun({
-      currentPage: pagination.current,
+      current: pagination.current,
       pageSize: pagination.pageSize,
     });
   };
@@ -394,12 +411,13 @@ function Approve(props) {
         type={Type.check}
         // projectList={projectData?.list}
         visible={conVisible}
-        handleOk={(data) =>
-          detail.status == Status.Checking
-            ? runCheck(data)
-            : detail.status == Status.CalChecking
-            ? calCheckRun(data)
-            : null
+        handleOk={
+          (data) => runOACheck(data)
+          // detail.status == Status.Checking
+          //   ? runOACheck(data)
+          //   : detail.status == Status.CalChecking
+          //   ? calCheckRun(data)
+          //   : null
         }
         handleCancel={() => setConVisible(false)}
       />

+ 72 - 0
src/pages/UserCenter/index.js

@@ -0,0 +1,72 @@
+import { queryChangePassWord } from '@/services/user';
+import { useModel, useNavigate } from '@umijs/max';
+import { Form, Input, Button, message } from 'antd';
+import { useState } from 'react';
+
+const ChangePassWord = () => {
+  const {
+    initialState: { user },
+  } = useModel('@@initialState');
+  const navigate = useNavigate();
+
+  const onFinish = async (values) => {
+    const res = await queryChangePassWord({
+      ID: user.ID,
+      Password: values.password,
+    });
+    if (res?.code === 200 && res?.msg === 'ok') {
+      message.success('修改密码成功');
+      navigate('/login');
+    }
+  };
+
+  return (
+    <div style={{ margin: 'auto' }}>
+      <Form
+        name="basic"
+        labelCol={{ span: 8 }}
+        wrapperCol={{ span: 16 }}
+        style={{ width: 600 }}
+        initialValues={{ remember: true }}
+        onFinish={onFinish}
+        autoComplete="off"
+      >
+        <Form.Item
+          label="请输入密码:"
+          name="password"
+          rules={[{ required: true, message: '请输入密码' }]}
+        >
+          <Input.Password autoComplete="false" />
+        </Form.Item>
+        <Form.Item
+          label="请再一次输入密码:"
+          name="password2"
+          rules={[
+            {
+              required: true,
+              message: '请再一次输入密码!',
+            },
+            ({ getFieldValue }) => ({
+              validator(_, value) {
+                if (!value || getFieldValue('password') === value) {
+                  return Promise.resolve();
+                }
+                return Promise.reject(new Error('两次输入的密码不一致!'));
+              },
+            }),
+          ]}
+        >
+          <Input.Password />
+        </Form.Item>
+
+        <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
+          <Button type="primary" htmlType="submit">
+            保存
+          </Button>
+        </Form.Item>
+      </Form>
+    </div>
+  );
+};
+
+export default ChangePassWord;

+ 23 - 420
src/services/boom.js

@@ -137,6 +137,15 @@ export async function queryProcessFlows(params) {
     formData: data.form_json ? JSON.parse(data.form_json) : [],
     simpleFlowDteail: data.process_simple_json,
   };
+  // 旧字段formItems  替换为新字段条件组 formItemsOr
+  item.flowDetail.nodes.forEach((node) => {
+    if (node.formItems) {
+      node.formItemsOr = [node.formItems];
+      node.formItems = '';
+    } else {
+      node.formItemsOr = node.formItemsOr || [];
+    }
+  });
   return { data: item };
 }
 export async function saveAuditFlowInfo(data) {
@@ -197,6 +206,7 @@ export async function advanceSubmitNextNode(params) {
     template_id: 0,
     cur_template_id: 0,
     next_template_id: 0,
+    ...params,
     form_list: [JSON.stringify(params)],
   };
   return request(`/api/v1/oa/next/node/advance-submit`, {
@@ -245,423 +255,16 @@ export async function queryFlowDelete(id) {
   return request(`/api/v1/oa/flow/delete/${id}`);
 }
 
-// /**
-//   project_id
-//   version_id	大版本id
-//   template_id
-//   template_node_id	查询某流程和某节点下最新版本的数据记录
-//   node_id	查询某审批流程和某审批节点下最新版本的数据记录
-//  */
-// export async function queryRecord(params) {
-//   return request(`/api/v1/purchase/record?${stringify(params)}`);
-// }
-// //删除excel中单个sheet页
-// export async function queryDelSheetRecord(params) {
-//   const response = await request(`/api/v1/purchase/bom/del-purchase-excel-sheet?${stringify(params)}`);
-//   if (response.code == 200) {
-//     // message.success('删除成功');
-//   }
-// }
-
-// // 查询全部工作流
-// export async function queryFlowList(params) {
-//   return request(`/api/v1/purchase/bom/flows?${stringify(params)}`);
-// }
-
-// // 根据节点id查询所有version
-// export async function queryVserionByNode(params, signal) {
-//   return request(`/api/v1/purchase/bom/flow/node?${stringify(params)}`, {
-//     signal,
-//   });
-// }
-
-// export async function commitSheet(params) {
-//   return request(`/api/v1/purchase/record`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// export async function approve(params) {
-//   return request(`/api/v1/purchase/audit/status`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// export async function queryAuthority(params) {
-//   const depId = localStorage.depId;
-//   return request(`/api/v1/purchase/bom/user/excel/col?depId=${depId}`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// export async function addBomComment(params) {
-//   return request(`/api/v1/purchase/comment`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// export async function queryBomComment(params) {
-//   return request(`/api/v1/purchase/comment?${stringify(params)}`);
-// }
-
-// /**
-//  * 提交流转
-//   "id":3, 当前流转文档id,必填
-//   "project_id":46, 所属项目id
-//   "template_id":1, 所属模板id ,必填
-//   "template_node_id":34,所属节点id,必填
-//   "next_template_id":1,跳转的下级业务模板id,必填
-//   "next_template_node_id":2,跳转的下级业务节点id,必填
-//   "flow_id":1, 跳转的下级审核流程id , 如果不为空,则说明流转的是审核节点,下级业务节点为审核通过后进入的业务节点
-//   "node_id":1,跳转的下级审核节点id
-//   "desc":"流转描述"
-//  */
-// export async function submitNextNode(params) {
-//   return request(`/api/v1/purchase/next/node/submit`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// export async function advanceSubmitNextNode(params) {
-//   return request(`/api/v1/purchase/next/node/advance-submit`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-
-// export async function queryDetail(params) {
-//   let response = await request(`/api/v1/purchase/record?${stringify(params)}`);
-//   let sheet = response.data;
-//   sheet.data = JSON.parse(sheet.data || '[]');
-//   sheet.data.forEach(item => {
-//     item.config = JSON.parse(item.config || '{}');
-//     item.celldata = JSON.parse(item.cell_data || '[]');
-//     delete item.cell_data;
-//   });
-//   return sheet;
-// }
-// export async function queryHistoryDetail(params) {
-//   return request(`/api/v1/purchase/record/history/detail?${stringify(params)}`);
-// }
-// export async function queryHistoryList(params) {
-//   return request(`/api/v1/purchase/record/history?${stringify(params)}`);
-// }
-
-// export async function queryBoomFlowList(params) {
-//   return request(`/api/v1/purchase/bom/flows?${stringify(params)}`);
-// }
-// //请求历史版本
-// export async function queryVersionsTree(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)}`);
-// }
-// //查询审批节点的审核记录
-// export async function queryAuditRecord(params) {
-//   return request(`/api/v1/purchase/audit/record?${stringify(params)}`);
-// }
-// //查询表单数据接口
-// export async function queryDingSchema(params) {
-//   return request(`/api/v1/purchase/bom/ding/schema?${stringify(params)}`);
-// }
-// export async function queryDingInstanceDetail(params) {
-//   let res = await request(`/api/v1/purchase/bom/ding/instance-detail`, {
-//     method: 'POST',
-//     body: params,
-//   });
-//   if (res.data.errcode != 0) {
-//     message.error(res.data.errmsg);
-//     throw new Error(res.data.errmsg);
-//   }
-//   return res;
-// }
-// export async function queryDingInstanceExecute(params) {
-//   let res = await request(`/api/v1/purchase/bom/ding/instance-execute`, {
-//     method: 'POST',
-//     body: params,
-//   });
-//   if (res.data.errcode != 0) {
-//     message.error('审批失败,请联系管理员。');
-//     throw new Error(res.data.errmsg);
-//   }
-//   return res;
-// }
-// export async function queryListParentByUser(params) {
-//   return request(`/api/v1/purchase/bom/ding/department/list-parent-by-user`, {
-//     method: 'POST',
-//     body: params,
-//   });
-// }
-// /**
-//  * 查看项目流程列表
-//  * project_id
-//  */
-// export async function queryProjectRecord(params) {
-//   return request(`/api/v1/purchase/bom/project/record?${stringify(params)}`);
-// }
-// /** 查看版本列表
-//  *  project_id
-//     template_id		流程id
-//     template_node_id	流程节点id
-//  */
-// export async function queryVersionsList(params) {
-//   return request(`/api/v1/purchase/record/versions?${stringify(params)}`);
-// }
-
-// export async function queryBoomFlowDetail(params) {
-//   let { data } = await request(`/api/v1/purchase/bom/flow/info?${stringify(params)}`);
-//   const groups = {
-//     top: {
-//       position: { name: 'top' },
-//       attrs: {
-//         circle: {
-//           r: 4,
-//           magnet: true,
-//           stroke: '#31d0c6',
-//           strokeWidth: 2,
-//           fill: '#fff',
-//           style: { visibility: 'hidden' },
-//         },
-//       },
-//       zIndex: 10,
-//     },
-//     right: {
-//       position: { name: 'right' },
-//       attrs: {
-//         circle: {
-//           r: 4,
-//           magnet: true,
-//           stroke: '#31d0c6',
-//           strokeWidth: 2,
-//           fill: '#fff',
-//           style: { visibility: 'hidden' },
-//         },
-//       },
-//       zIndex: 10,
-//     },
-//     bottom: {
-//       position: { name: 'bottom' },
-//       attrs: {
-//         circle: {
-//           r: 4,
-//           magnet: true,
-//           stroke: '#31d0c6',
-//           strokeWidth: 2,
-//           fill: '#fff',
-//           style: { visibility: 'hidden' },
-//         },
-//       },
-//       zIndex: 10,
-//     },
-//     left: {
-//       position: { name: 'left' },
-//       attrs: {
-//         circle: {
-//           r: 4,
-//           magnet: true,
-//           stroke: '#31d0c6',
-//           strokeWidth: 2,
-//           fill: '#fff',
-//           style: { visibility: 'hidden' },
-//         },
-//       },
-//       zIndex: 10,
-//     },
-//   };
-//   const attrs = {
-//     line: {
-//       stroke: '#A2B1C3',
-//       targetMarker: { name: 'block', width: 12, height: 8 },
-//       strokeDasharray: '5 5',
-//       strokeWidth: 1,
-//     },
-//   };
-//   let nodes = data.Nodes.map(item => {
-//     let node = {
-//       ...item,
-//       id: item.node_id,
-//       renderKey: item.render_key,
-//       zIndex: item.z_index,
-//       isCustom: !!item.is_custom,
-//       ports: JSON.parse(item.ports || '{}'),
-//     };
-//     node.ports.groups = groups;
-//     node.parentKey = '1';
-
-//     return node;
-//   });
-//   let edges = data.Edges.map(item => {
-//     let edge = {
-//       id: item.edge_id,
-//       source: {
-//         cell: item.source_cell,
-//         port: item.source_port,
-//       },
-//       target: {
-//         cell: item.target_cell,
-//         port: item.target_port,
-//       },
-//     };
-//     try {
-//       edge.attrs = item.attr ? JSON.parse(item.attr) : attrs;
-//     } catch (error) {
-//       edge.attrs = attrs;
-//     }
-//     return edge;
-//   });
-//   return {
-//     ...data,
-//     nodes,
-//     edges,
-//   };
-// }
-// export async function updateNode(data) {
-//   return request(`/api/v1/purchase/bom/flow/${data.templateId}/${data.nodeId}`, {
-//     method: 'PUT',
-//     body: data.body,
-//   });
-// }
-// export async function addBoomFlow(data) {
-//   return request(`/api/v1/purchase/bom/flow/info`, {
-//     method: 'POST',
-//     body: data,
-//   });
-// }
-
-// export async function addFlow(data) {
-//   return request(`/api/v1/purchase/bom/flow/info`, {
-//     method: 'POST',
-//     body: data,
-//   });
-// }
-// /**
-//  *  [
-//       {
-//         "flow_id": 23,
-//         "node": "主管",
-//         "desc": "desc",
-//         "auditor": 2,
-//         "seq": 1,
-//         "seq_relate": 0
-//       }
-//     ]
-//  */
-// export async function addAuditNode(data) {
-//   return request(`/api/v1/purchase/flow/info/${data.flowId}`, {
-//     method: 'POST',
-//     body: data.nodes,
-//   });
-// }
-
-// export async function queryRecordSheet(data) {
-//   return request(`/api/v1/purchase/record/sheet?${stringify(data)}`, {
-//     method: 'POST',
-//     body: data,
-//   });
-// }
-// export async function queryDingTemplateList() {
-//   return request(`/api/v1/purchase/bom/ding/template/list`);
-// }
-
-// export async function queryDDdepList(data) {
-//   let res = await request(`/api/v1/purchase/bom/ding/department-list`, {
-//     method: 'POST',
-//     body: data,
-//   });
-//   return res.data.result;
-// }
-
-// export async function queryDDProcessesForecast(data) {
-//   let res = await request(`/api/v1/purchase/bom/ding/processes-forecast`, {
-//     method: 'POST',
-//     body: data,
-//   });
-//   if (res.data.message) {
-//     // message.error(res.data.message);
-//     throw new Error(res.data.message);
-//   }
-//   return res.data.result;
-// }
-
-// export async function uploadFile(data) {
-//   let res = await request(`/api/v1/purchase/bom/ding/upload-file`, {
-//     method: 'POST',
-//     body: data,
-//     headers: {
-//       ContentType: 'application/x-www-form-urlencoded',
-//     },
-//   });
-//   if (!res.data.dentry) {
-//     message.error(res.data.errmsg);
-//     throw new Error(res.data.errmsg);
-//   }
-//   return res.data;
-// }
-
-// export async function bindDDCode(userId, code) {
-//   let res = await request(`/api/v1/purchase/bom/ding/set-ding-user-code?ucode=${userId}:${code}`, {
-//     method: 'GET',
-//   });
-
-//   return res.data;
-// }
-
-// //获取部门结构
-// export async function queryDepV2(params) {
-//   return request(`/api/v2/dep?${stringify(params)}`);
-// }
-
-// //新增工作流时调用接口 给项目绑定默认分类列表
-// //purchase/bom/default-bind-classify?project_id=1
-// export async function queryDefaultBindClassify(params) {
-//   let res = await request(`/api/v1/purchase/bom/default-bind-classify?${stringify(params)}`, {
-//     method: 'GET',
-//   });
-//   return res.data;
-// }
-
-// export async function queryBindClassify(params) {
-//   let res = await request(`/api/v1/purchase/bom/get-bind-classify?${stringify(params)}`, {
-//     method: 'GET',
-//   });
-//   return res.data;
-// }
-
-// export async function queryAddBindClassify(data) {
-//   return request(`/api/v1/purchase/bom/add-bind-classify`, {
-//     method: 'POST',
-//     body: data,
-//   });
-// }
-
-// export async function queryDelPurchaseExcel(params) {
-//   let res = await request(`/api/v1/purchase/bom/del-purchase-excel?${stringify(params)}`, {
-//     method: 'GET',
-//   });
-//   return res;
-// }
-// //提交流转存储表单审批人历史记录
-// export async function querySaveBomForm(data) {
-//   return request(`/api/v1/purchase/bom/save-bom-form`, {
-//     method: 'POST',
-//     body: data,
-//   });
-// }
-
-// //章管家失败,重新申请用印
-// export async function queryTrySeal(params) {
-//   let res = await request(`/api/v1/purchase/bom/try-seal?${stringify(params)}`, {
-//     method: 'GET',
-//   });
-//   return res;
-// }
-
-// export async function ChartTempOSSData(params) {
-//   return request(`/api/v1/purchase/bom/contract-file/${params.projectId}`);
-// }
-// // 设置最终版本
-// export async function setLastVersion(excelId) {
-//   return request(`/api/v1/purchase/bom/set-last-version/${excelId}`);
-// }
+export async function updateAuditList(data, isAfter) {
+  let res = await request(`/api/v1/oa/submit/add-auditor`, {
+    method: 'POST',
+    data,
+  });
+  if (isAfter) {
+    await audit({
+      id: data.oa_id,
+      status: 1,
+    });
+  }
+  return res;
+}

+ 24 - 0
src/services/contract.js

@@ -74,3 +74,27 @@ export const queryCompany = async (data) => {
     params: data,
   });
 };
+//计算合同编号
+export const queryContractCode = async (data) => {
+  return await request('/api/contract/v1/code', {
+    params: data,
+  });
+};
+//获取合同审批详情
+export const queryAuditByCode = async (data) => {
+  return await request('/api/v1/oa/audit/extend/detail', {
+    params: data,
+  });
+};
+
+//撤回合同审批申请
+export const queryOAReCall = async (data) => {
+  return await request(`/api/v1/oa/repeal/${data}`);
+};
+//删除合同
+export const queryDelById = async (data) => {
+  return await request(`/api/contract/v1/delete`, {
+    method: 'DELETE',
+    params: data,
+  });
+};

+ 10 - 2
src/services/user.js

@@ -1,4 +1,5 @@
-import {request }from 'umi';
+import { message } from 'antd';
+import { request } from 'umi';
 
 export async function query() {
   return request('/api/v1/user');
@@ -21,11 +22,18 @@ export async function queryCurrentV2() {
 export async function queryUserRole(userId) {
   return request('/api/v2/user/detail/' + userId, { method: 'GET' });
 }
+//ID:471
+// Password:"123123"
+export async function queryChangePassWord(data) {
+  return request('/api/v1/user/password', {
+    method: 'POST',
+    data,
+  });
+}
 // export async function queryCurrent() {
 //   return request('/api/v1/user/current-user', { method: 'GET' });
 // }
 
-
 // export async function queryUnreadNotification() {
 //   return request('/notification/unread/', { method: 'GET' });
 // }