Renxy 1 жил өмнө
parent
commit
19b9a5c5fb
39 өөрчлөгдсөн 2515 нэмэгдсэн , 114 устгасан
  1. 23 5
      .umirc.ts
  2. 122 0
      public/ZwCloud2DSDK/ZwCloud2D.d.ts
  3. 1 0
      public/ZwCloud2DSDK/ZwCloud2D.js
  4. 465 0
      public/ZwCloud2DSDK/ZwCloud2DPrivateAPI.js
  5. 660 0
      public/ZwCloud2DSDK/ZwCloud2DRestfulAPI.js
  6. 0 0
      public/ZwCloud2DSDK/ZwWasmJs.js
  7. BIN
      public/ZwCloud2DSDK/ZwWasmJs.wasm
  8. BIN
      public/ZwCloud2DSDK/adinit.dat
  9. BIN
      public/ZwCloud2DSDK/home_m.png
  10. BIN
      public/ZwCloud2DSDK/image1.png
  11. BIN
      public/ZwCloud2DSDK/image2.png
  12. 0 0
      public/ZwCloud2DSDK/readLMFData.js
  13. BIN
      public/ZwCloud2DSDK/text.png
  14. BIN
      public/ZwCloud2DSDK/textGlyph/SimSun-01.ttf
  15. BIN
      src/assets/SideMenu/cadIcon.png
  16. BIN
      src/assets/UnityMenu/cad.png
  17. 32 25
      src/components/AuditForm/ComponentLibrary.js
  18. 124 15
      src/components/AuditForm/FormContent.js
  19. 147 0
      src/components/AuditForm/FormulaModal.js
  20. 71 4
      src/components/AuditForm/ItemAttribute.js
  21. 19 0
      src/components/AuditForm/constant.js
  22. 134 13
      src/components/AuditForm/index.js
  23. 2 2
      src/components/DDComponents/DDDateField/index.js
  24. 3 3
      src/components/DDComponents/DDSelectField/index.js
  25. 7 0
      src/components/DDComponents/DIYTable/index.css
  26. 210 0
      src/components/DDComponents/DIYTable/index.tsx
  27. 10 0
      src/components/DDComponents/FormulaField/index.js
  28. 4 3
      src/components/DDComponents/NumberField/index.js
  29. 14 1
      src/components/DDComponents/index.js
  30. 17 0
      src/pages/Cad/components/UploadModal.js
  31. 37 0
      src/pages/Cad/detail.js
  32. 148 0
      src/pages/Cad/index.js
  33. 6 7
      src/pages/Flow/Audit.js
  34. 2 4
      src/pages/Flow/OaAuditDetail.js
  35. 170 10
      src/pages/Flow/OaDetail.js
  36. 42 11
      src/pages/Flow/components/AuditDetailed.js
  37. 25 11
      src/pages/Flow/components/FormAndFilesNode.js
  38. 10 0
      src/pages/Home/index.js
  39. 10 0
      src/services/cad.js

+ 23 - 5
.umirc.ts

@@ -34,14 +34,20 @@ export default defineConfig({
   //   },
   //   },
   // ],
   // ],
   // scripts: [
   // scripts: [
-  //   { src: 'http://localhost:3000/plugins/js/plugin.js' },
-  //   { src: 'http://localhost:3000/luckysheet.umd.js' },
+  //   { src: '/ZwCloud2DSDK/ZwCloud2D.js' },
+  //   { src: '/ZwCloud2DSDK/ZwWasmJs.js' },
+  //   { src: '/ZwCloud2DSDK/ZwCloud2DAPI.js' },
   // ],
   // ],
+  headScripts: [
+    '/ZwCloud2DSDK/ZwCloud2D.js',
+    '/ZwCloud2DSDK/ZwWasmJs.js',
+    '/ZwCloud2DSDK/ZwCloud2DPrivateAPI.js',
+  ],
   proxy: {
   proxy: {
     '/api': {
     '/api': {
-      // target: 'http://47.96.12.136:8888/',
-      // target: 'http://47.96.12.136:8895/',
-      target: 'https://work.greentech.com.cn/',
+      // target: 'http://192.168.20.232:1007/',
+      target: 'http://47.96.12.136:8895/',
+      // target: 'https://work.greentech.com.cn/',
       changeOrigin: true,
       changeOrigin: true,
     },
     },
   },
   },
@@ -206,6 +212,18 @@ export default defineConfig({
       component: './PSRManage/detail',
       component: './PSRManage/detail',
       hideInMenu: true,
       hideInMenu: true,
     },
     },
+    // {
+    //   name: 'CAD实例',
+    //   path: '/cad',
+    //   component: './Cad',
+    //   icon: 'https://water-service-test.oss-cn-hangzhou.aliyuncs.com/doc/contract/2023-07-31/3f72fccf-4f9c-4891-a6ec-f04fe4b1d9a2.png',
+    // },
+    // {
+    //   name: 'CAD详情',
+    //   path: '/cad/detail',
+    //   component: './Cad/detail',
+    //   hideInMenu: true,
+    // },
   ],
   ],
   npmClient: 'yarn',
   npmClient: 'yarn',
 });
 });

+ 122 - 0
public/ZwCloud2DSDK/ZwCloud2D.d.ts

@@ -0,0 +1,122 @@
+declare class Zw2DCloud {
+    /**
+     * Zw2DCloud 构造函数 传入一个div元素
+     * @param container 容器,一个div元素
+     */
+    constructor(container: HTMLDivElement)
+
+    /**
+     * 设置面板的属性:位置、大小等
+     * @param pageConfig 配置对象,详细信息请参考文档
+     */
+    ZwSetPageConfig(pageConfig: config): void
+
+    /**
+     * 进入图纸,可调用加载默认布局数据
+     * @param data lmf数据
+     */
+    ZwLoadDwgData(data: ArrayBuffer): void
+
+    /**
+     * 切换布局时,加载对应布局数据
+     * @param data lmf数据
+     */
+    ZwLoadLayoutData(data: ArrayBuffer): void
+
+    /**
+     * 设置布局信息
+     * @param info 布局信息的数组
+     */
+    ZwSetLayoutInfo(info: Array<{
+        handleId: number,
+        isDefault: 0 | 1,
+        layoutName: string,
+        order: number
+    }>): void
+
+    /**
+     * 传递图纸相关字体数据
+     * @param fontDatas 字体数据的数组
+     */
+    ZwSetFontDataList(fontDatas: Array<{
+        fontName: string,
+        fontData: ArrayBuffer
+    }>): void
+
+    /**
+     * 设置蒙版loading状态
+     * @param isLoading 布尔值,loading状态
+     */
+    ZwSetLoadingState(isLoading: boolean): void
+
+    /**
+     * 设置图纸内部图片数据
+     * @param imageDatas 图片数据的数组
+     */
+    ZwLoadImageData(imageDatas: Array<{
+        path: string,
+        data: ArrayBuffer
+    }>): void
+
+    /**
+     * 内部打印触发事件
+     * @param logInfo 打印事件抛出的信息
+     */
+    ZwEvtLogInfo(logInfo: {
+        type: 'Logger',
+        data: string
+    }): void
+
+    /**
+     * 切换布局触发的事件
+     * @param handleId 切换布局内部抛出的布局handleId
+     */
+    ZwEvtChangeLayout(handleId: number): void
+}
+
+type config = {
+    top?: number,
+    bottom?: number,
+    left?: number,
+    right?: number,
+
+    layerPanel?: {
+        WindowOrient?: "left"|"right"|"top"|"bottom",
+        WindowVisible?: "hide"|"show",
+        index?: number,
+        xval?: number,
+        yval?: number,
+        width?: number,
+        height?: number,
+        showPosition?: Array<"left" | "right" | "top" | "bottom">
+    },
+    xrefPanel?: {
+        WindowOrient?: "left" | "right" | "top" | "bottom",
+        WindowVisible?: "hide" | "show",
+        index?: number,
+        xval?: number,
+        yval?: number,
+        width?: number,
+        height?: number,
+        showPosition?: Array<"left" | "right" | "top" | "bottom">
+    },
+
+    commandPanel?: {
+        WindowOrient?: "left" | "right" | "top" | "bottom",
+        WindowVisible?: "hide" | "show",
+        index?: number,
+        xval?: number,
+        yval?: number,
+        width?: number,
+        height?: number,
+        showPosition?: Array<"left" | "right" | "top" | "bottom">
+    },
+    options?: {
+        usingWebGL?: boolean,
+        justShowTextBorder?: boolean,
+        zoomBreak?: boolean,
+        zoomNoHatch?: boolean,
+        cursorNotShow?: boolean,
+        cursorSize?: number,
+    }
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 0
public/ZwCloud2DSDK/ZwCloud2D.js


+ 465 - 0
public/ZwCloud2DSDK/ZwCloud2DPrivateAPI.js

@@ -0,0 +1,465 @@
+let baseUrl = 'http://192.168.51.174:5199';
+let wsUrl = '';
+let dwgPath = '';
+let javaUrl = '';
+
+class Request {
+  constructor() {}
+
+  get(url, params, resType, type) {
+    return new Promise((res, rej) => {
+      let paramsArr = [];
+      for (let k in params) {
+        paramsArr.push(
+          encodeURIComponent(k) + '=' + encodeURIComponent(params[k]),
+        );
+      }
+      url = url + '?' + paramsArr.join('&');
+      let ajax = new XMLHttpRequest();
+      let checkUrl = type === 'java' ? javaUrl + url : baseUrl + url;
+      ajax.open('GET', checkUrl);
+      resType && (ajax.responseType = resType);
+      ajax.send();
+      ajax.onload = function () {
+        if (resType) res(ajax.response);
+        else {
+          let data = JSON.parse(ajax.response);
+          if (data.code === 0) {
+            res(data.data);
+          } else {
+            rej(data.msg);
+          }
+        }
+      };
+    });
+  }
+
+  post(url, params, resType, type) {
+    return new Promise((res, rej) => {
+      let ajax = new XMLHttpRequest();
+      let checkUrl = type === 'java' ? javaUrl + url : baseUrl + url;
+      ajax.open('POST', checkUrl);
+      resType && (ajax.responseType = resType);
+      if (!(params instanceof FormData)) {
+        ajax.setRequestHeader('content-type', 'application/json');
+      }
+      ajax.send(params);
+      ajax.onreadystatechange = function () {
+        if (ajax.readyState === 4) {
+          if (ajax.status === 200) {
+            res(ajax.response);
+          } else {
+            rej();
+          }
+        }
+      };
+    });
+  }
+
+  arrayBufferToBase64(buffer) {
+    let binary = '';
+    let bytes = new Uint8Array(buffer);
+    let len = bytes.byteLength;
+    for (let i = 0; i < len; i++) {
+      binary += String.fromCharCode(bytes[i]);
+    }
+    return btoa(binary);
+  }
+
+  fontDownload(fontName) {
+    return this.get('/sdk/font/download', { fontName }, 'blob');
+  }
+
+  transferDoc() {
+    return this.get('/sdk/transfer', {
+      projectId: 0,
+      dwgPath: dwgPath,
+      type: 1,
+    });
+  }
+
+  getDisplayData(handleId = 34) {
+    return this.get(
+      '/sdk/layout/lmf',
+      { projectId: 0, handleId, dwgPath: dwgPath },
+      'arraybuffer',
+    );
+  }
+
+  getXrefData(handleId, xrefIds) {
+    let params = { handleId: handleId, xrefIds: xrefIds, dwgPath: dwgPath };
+    params = JSON.stringify(params);
+    return this.post('/sdk/xref', params, 'arraybuffer');
+  }
+
+  getXrefRelation() {
+    return this.get('/sdk/xref/list', { dwgPath: dwgPath });
+  }
+
+  getXrefThumb(filePath) {
+    return this.get(
+      '/sdk/xref/thumb',
+      { filePath: filePath },
+      'arraybuffer',
+    ).then((res) => {
+      let url = this.arrayBufferToBase64(res);
+      return 'data:image/jpeg;base64,' + url;
+    });
+  }
+  getPlotData(params) {
+    let data = JSON.stringify(params);
+    return this.post('/sdk/print', data, 'arraybuffer');
+  }
+  getImageSrc(filePath) {
+    return this.get(
+      '/sdk/image/download',
+      { filePath: filePath },
+      'arraybuffer',
+    ).then((res) => {
+      let url = this.arrayBufferToBase64(res);
+      return 'data:image/jpeg;base64,' + url;
+    });
+  }
+  getImageData(filePath) {
+    return this.get(
+      '/sdk/image/download',
+      { filePath: filePath },
+      'arraybuffer',
+    );
+  }
+  getImageList() {
+    return this.get('/sdk/image/list');
+  }
+  getPermissionList() {
+    return this.get('/sdk/getStatus');
+  }
+  getRegenData(params) {
+    Object.assign(params, { dwgPath: dwgPath });
+    let data = JSON.stringify(params);
+    return this.post('/sdk/regen', data, 'arraybuffer');
+  }
+  getDwgFile() {
+    return this.get(
+      '/sdk/doc/download',
+      { dwgPath: dwgPath },
+      'arrayBuffer',
+      'java',
+    );
+  }
+  uploadFile(file) {
+    let formData = new FormData();
+    formData.append('file', file);
+    return this.post('/sdk/doc/upload', formData, 'json', 'java');
+  }
+}
+
+function resizeCheck() {
+  if (Date.now() - timer > 400) {
+    const windowInfo = {
+      width: window.innerWidth,
+      height: window.innerHeight,
+    };
+    console.log(windowInfo);
+    if (windowInfo.width <= 1190 || windowInfo.height <= 620) {
+      mainMobile.style.display = 'unset';
+      main.style.display = 'none';
+    } else {
+      mainMobile.style.display = 'none';
+      main.style.display = 'unset';
+    }
+    timer = Date.now();
+  }
+}
+
+ZwCloud2D.ZwDataProcessor.ZwSetConnectUrl = (url1, url2, url3) => {
+  javaUrl = url1;
+  baseUrl = url2;
+  wsUrl = url3;
+};
+
+ZwCloud2D.ZwDataProcessor.ZwSetLoadDwg = (path) => {
+  dwgPath = path;
+};
+
+ZwCloud2D.ZwDataProcessor.uploadDwg = (file) => {
+  let req = new Request();
+  return new Promise((resolve, reject) => {
+    req.uploadFile(file).then((res) => {
+      resolve(res);
+    });
+  });
+
+  // req.uploadFile(file).then(res => {
+  //     dwgPath = res.data.path;
+  //     ZwCloud2D.ZwDataProcessor.ZwLoad();
+  //     let main = document.getElementById('main');
+  //     main.style.display = "none"
+  //     let mainMobile = document.getElementById('main-mobile');
+  //     mainMobile.style.display = "none"
+  //     let showDwgBtn = document.getElementById('showDwgBtn');
+  //     let showFontBtn = document.getElementById('showFontBtn');
+  //     showDwgBtn.style.display = "unset"
+  //     showFontBtn.style.display = "unset"
+  // })
+};
+
+ZwCloud2D.ZwDataProcessor.uploadFont = (file) => {
+  let req = new Request();
+  let pArray = new Array();
+  for (let i = 0; i < file.length; i++) {
+    pArray.push(
+      new Promise((resolve, reject) => {
+        req.uploadFile(file[i]).then((res) => {
+          if (res.code === 200) {
+            resolve();
+          } else {
+            reject();
+          }
+        });
+      }),
+    );
+  }
+  Promise.all(pArray)
+    .then(() => {
+      alert('上传成功');
+    })
+    .catch(() => {
+      alert('上传失败');
+    });
+};
+
+ZwCloud2D.ZwDataProcessor.ZwLoad = () => {
+  let docId = new Date().getTime().toString();
+  let req = new Request();
+
+  // 切换布局时候触发回调
+  ZwCloud2D.ZwMessageCallback.ZwEvtChangeLayout = (layout) => {
+    req
+      .getDisplayData(layout.handleId)
+      .then((data) => {
+        let timestamp = new Date().getTime();
+        ZwCloud2D.ZwDataManager.ZwSetDwgData(layout.handleId, data, timestamp);
+      })
+      .catch((error) => {
+        console.error(error);
+      });
+  };
+  ZwCloud2D.ZwMessageCallback.ZwEvtLoadXrefData = (data) => {
+    req
+      .getXrefData(data.handleId, data.xrefIds)
+      .then((res) => {
+        ZwCloud2D.ZwDataManager.ZwSetXrefData(res);
+      })
+      .catch(() => {
+        ZwCloud2D.ZwDataManager.ZwSetXrefData();
+      });
+  };
+  ZwCloud2D.ZwMessageCallback.ZwEvtDrawEnd = () => {};
+
+  ZwCloud2D.ZwMessageCallback.ZwEvtGetRegenData = (data) => {
+    req
+      .getRegenData(data)
+      .then((res) => {
+        ZwCloud2D.ZwDataManager.ZwSetRegenData(res);
+      })
+      .catch(() => {
+        ZwCloud2D.ZwDataManager.ZwSetRegenData(null);
+      });
+  };
+  ZwCloud2D.ZwMessageCallback.ZwEvtLoadImageData = (data) => {
+    let pArr = new Array();
+    let imageMap = new Map();
+    data.forEach((imageUrl) => {
+      pArr.push(
+        new Promise((res, rej) => {
+          req
+            .getImageData(imageUrl)
+            .then((result) => {
+              imageMap.set(imageUrl, result);
+              res(true);
+            })
+            .catch((err) => {
+              res(true);
+            });
+        }),
+      );
+    });
+    Promise.all(pArr)
+      .then(() => {
+        ZwCloud2D.ZwDataManager.ZwSetImageData(imageMap);
+      })
+      .catch((error) => {
+        console.error(error);
+      });
+  };
+  ZwCloud2D.ZwMessageCallback.ZwEvtLoadImageList = () => {
+    req.getImageList().then((res) => {
+      res.forEach((image) => {
+        let path = image.completePath + image.name;
+        req.getImageSrc(path).then((imageData) => {
+          let item = {
+            name: image.name,
+            data: imageData,
+            completePath: image.completePath,
+          };
+          ZwCloud2D.ZwDataManager.ZwSetImageList(item);
+        });
+      });
+    });
+  };
+  ZwCloud2D.ZwMessageCallback.ZwEvtPlotDwg = (data) => {
+    let params = Object.assign(data.params, { dwgPath: dwgPath });
+    req
+      .getPlotData(params)
+      .then((res) => {
+        ZwCloud2D.ZwDataManager.ZwSetPlotData(data, res);
+        ZwCloud2D.ZwEditor.ZwSetLoadingState(false);
+      })
+      .catch((error) => {
+        console.error(error);
+      });
+  };
+  ZwCloud2D.ZwEditor.ZwSetUserOptions({ panel: { commentPanel: false } });
+  req
+    .getPermissionList()
+    .then((data) => {
+      ZwCloud2D.ZwDataManager.ZwSetSdkPermission(data);
+    })
+    .catch((error) => {
+      console.error(error);
+    });
+  if (!dwgPath) return;
+  req
+    .transferDoc()
+    .then((data) => {
+      // 显示当前布局的数据
+      let layouts = [];
+      data.layouts.forEach((layout) => {
+        let res = {
+          handleId: layout.handleId,
+          isDefault: layout.isDefault === 1 ? 'YES' : 'NO',
+          name: layout.layoutName,
+          tabOrder: layout.order,
+        };
+        layouts.push(res);
+      });
+      ZwCloud2D.ZwDataManager.ZwSetDwgInfo({
+        id: docId,
+        fonts: data.fontList,
+        layouts: layouts,
+        name: data.name,
+      }).then((res) => {
+        let pArr = [];
+        let fontArr = [];
+        res.missingFonts.forEach((fontName) => {
+          let arr = fontName.split('.');
+          let type = (arr[arr.length - 1] || '').toUpperCase();
+
+          pArr.push(
+            req.fontDownload(fontName).then(async (data) => {
+              if (data.type === 'application/octet-stream') {
+                let arraybuffer = await data.arrayBuffer();
+                fontArr.push({
+                  name: fontName,
+                  type: type,
+                  data: arraybuffer,
+                });
+              }
+            }),
+          );
+        });
+        Promise.all(pArr)
+          .then(() => {
+            ZwCloud2D.ZwDataManager.ZwSetFontDataList(fontArr).then(() => {
+              req
+                .getDisplayData(res.layout.handleId)
+                .then((lmfInfo) => {
+                  if (res.timestamp === '')
+                    res.timestamp = new Date().getTime();
+                  ZwCloud2D.ZwDataManager.ZwSetDwgData(
+                    res.layout.handleId,
+                    lmfInfo,
+                    res.timestamp,
+                  );
+                })
+                .catch((error) => {
+                  console.error(error);
+                });
+
+              req
+                .getXrefRelation()
+                .then((xrefRelations) => {
+                  let xrefPromises = [];
+                  let srcMap = new Map();
+                  xrefRelations.forEach((xrefRelation) => {
+                    if (xrefRelation.foundPath) {
+                      xrefPromises.push(
+                        new Promise((res, rej) => {
+                          req
+                            .getXrefThumb(xrefRelation.foundPath)
+                            .then((xrefThumb) => {
+                              srcMap.set(xrefRelation.foundPath, xrefThumb);
+                              res(true);
+                            });
+                        }),
+                      );
+                    }
+                  });
+                  Promise.all(xrefPromises)
+                    .then(() => {
+                      let params = {
+                        docName: data.name,
+                        xrefRelations: xrefRelations,
+                        srcMap: srcMap,
+                      };
+                      ZwCloud2D.ZwDataManager.ZwSetXrefList(params);
+                    })
+                    .catch(() => {
+                      let params = {
+                        docName: data.name,
+                        xrefRelations: xrefRelations,
+                        srcMap: srcMap,
+                      };
+                      ZwCloud2D.ZwDataManager.ZwSetXrefList(params);
+                    });
+                })
+                .catch((error) => {
+                  console.error(error);
+                });
+
+              if (wsUrl) {
+                let url =
+                  wsUrl +
+                  '/CadService?sub=' +
+                  Math.floor(Math.random() * 1000) +
+                  '&docId=' +
+                  docId +
+                  '&dwgPath=' +
+                  dwgPath;
+                ZwCloud2D.ZwDataManager.ZwEntryEdit(url);
+              }
+            });
+          })
+          .catch((error) => {
+            console.error(error);
+          });
+      });
+    })
+    .catch((error) => {
+      ZwCloud2D.ZwEditor.ZwSetLoadingState(false);
+
+      alert(error);
+      let main = document.getElementById('main');
+      main.style.display = 'unset';
+      let mainMobile = document.getElementById('main-mobile');
+      mainMobile.style.display = 'unset';
+      let showDwgBtn = document.getElementById('showDwgBtn');
+      let showFontBtn = document.getElementById('showFontBtn');
+      showDwgBtn.style.display = 'none';
+      showFontBtn.style.display = 'none';
+
+      resizeCheck();
+      window.addEventListener('resize', resizeCheck);
+      console.error(error);
+    });
+};

+ 660 - 0
public/ZwCloud2DSDK/ZwCloud2DRestfulAPI.js

@@ -0,0 +1,660 @@
+let baseUrl = 'http://192.168.51.174:9092'
+let userUrl = 'http://192.168.51.174:9091'
+let appKey = ''
+
+let docId = ''
+
+let fullVersionPermissions = {
+    'productName': 'ZW2D_CLOUD_FULL_2024',
+    'featureId': 167,
+    'projectId': 0,
+    'expiredTime': '2022-12-12T00:00:00',
+    'authClientNum': 10,
+    'forCloud2D': true,
+    'permissions': [
+        {
+            'description': 'DWG 100',
+            'name': 'DWG 100',
+            'permissionId': '100',
+            'type': 'SDK'
+        },
+        {
+            'description': 'DXF 101',
+            'name': 'DXF 101',
+            'permissionId': '101',
+            'type': 'SDK'
+        },
+        {
+            'description': '天正 102',
+            'name': '天正 102',
+            'permissionId': '102',
+            'type': 'SDK'
+        },
+        {
+            'description': '图纸预览图获取',
+            'name': '图纸预览图获取',
+            'permissionId': '201',
+            'type': 'SDK'
+        },
+        {
+            'description': '视口重生成',
+            'name': '视口重生成',
+            'permissionId': '202',
+            'type': 'SDK'
+        },
+        {
+            'description': '外部参照图片',
+            'name': '外部参照图片',
+            'permissionId': '203',
+            'type': 'SDK'
+        },
+        {
+            'description': 'DWG轻量数据生成',
+            'name': 'DWG轻量数据生成',
+            'permissionId': '204',
+            'type': 'SDK'
+        },
+        {
+            'description': '字体设置',
+            'name': '字体设置',
+            'permissionId': '205',
+            'type': 'SDK'
+        },
+        {
+            'description': '字体替换设置',
+            'name': '字体替换设置',
+            'permissionId': '206',
+            'type': 'SDK'
+        },
+        {
+            'description': '字体库',
+            'name': '字体库',
+            'permissionId': '207',
+            'type': 'SDK'
+        },
+        {
+            'description': '图纸二维线框显示',
+            'name': '图纸二维线框显示',
+            'permissionId': '300',
+            'type': 'SDK'
+        },
+        {
+            'description': '大图浏览(20M)',
+            'name': '大图浏览(20M)',
+            'permissionId': '301',
+            'type': 'SDK'
+        },
+        {
+            'description': '着色模式显示支持',
+            'name': '着色模式显示支持',
+            'permissionId': '302',
+            'type': 'SDK'
+        },
+        {
+            'description': '缩放',
+            'name': '缩放',
+            'permissionId': '303',
+            'type': 'SDK'
+        },
+        {
+            'description': '平移',
+            'name': '平移',
+            'permissionId': '304',
+            'type': 'SDK'
+        },
+        {
+            'description': '图片显示',
+            'name': '图片显示',
+            'permissionId': '305',
+            'type': 'SDK'
+        },
+        {
+            'description': '外部参照显示',
+            'name': '外部参照显示',
+            'permissionId': '306',
+            'type': 'SDK'
+        },
+        {
+            'description': '布局显示和切换',
+            'name': '布局显示和切换',
+            'permissionId': '307',
+            'type': 'SDK'
+        },
+        {
+            'description': '图层面板',
+            'name': '图层面板',
+            'permissionId': '308',
+            'type': 'SDK'
+        },
+        {
+            'description': '图层显示/隐藏',
+            'name': '图层显示/隐藏',
+            'permissionId': '309',
+            'type': 'SDK'
+        },
+        {
+            'description': '命令行窗口',
+            'name': '命令行窗口',
+            'permissionId': '310',
+            'type': 'SDK'
+        },
+        {
+            'description': '线宽显示',
+            'name': '线宽显示',
+            'permissionId': '311',
+            'type': 'SDK'
+        },
+        {
+            'description': '栅格显示',
+            'name': '栅格显示',
+            'permissionId': '312',
+            'type': 'SDK'
+        },
+        {
+            'description': '外部参照面板',
+            'name': '外部参照面板',
+            'permissionId': '313',
+            'type': 'SDK'
+        },
+        {
+            'description': '系统参数设置',
+            'name': '系统参数设置',
+            'permissionId': '314',
+            'type': 'SDK'
+        },
+        {
+            'description': '测量长度/面积/角度/坐标/弧长',
+            'name': '测量长度/面积/角度/坐标/弧长',
+            'permissionId': '400',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Text 单行文字',
+            'name': 'Text 单行文字',
+            'permissionId': '500',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Revcloud 云线',
+            'name': 'Revcloud 云线',
+            'permissionId': '501',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Leader 引线',
+            'name': 'Leader 引线',
+            'permissionId': '502',
+            'type': 'SDK'
+        },
+        {
+            'description': 'MLeader 多重引线',
+            'name': 'MLeader 多重引线',
+            'permissionId': '503',
+            'type': 'SDK'
+        },
+        {
+            'description': '图片(即图章功能)',
+            'name': '图片(即图章功能)',
+            'permissionId': '504',
+            'type': 'SDK'
+        },
+        {
+            'description': 'PLine 多段线',
+            'name': 'PLine 多段线',
+            'permissionId': '505',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Rectangle 矩形',
+            'name': 'Rectangle 矩形',
+            'permissionId': '506',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Circle 圆',
+            'name': 'Circle 圆',
+            'permissionId': '507',
+            'type': 'SDK'
+        },
+        {
+            'description': 'Arc 弧线',
+            'name': 'Arc 弧线',
+            'permissionId': '508',
+            'type': 'SDK'
+        },
+        {
+            'description': 'DWG导出',
+            'name': 'DWG导出',
+            'permissionId': '600',
+            'type': 'SDK'
+        },
+        {
+            'description': '图片输出',
+            'name': '图片输出',
+            'permissionId': '601',
+            'type': 'SDK'
+        },
+        {
+            'description': 'PDF输出',
+            'name': 'PDF输出',
+            'permissionId': '602',
+            'type': 'SDK'
+        },
+        {
+            'description': '添加预览水印',
+            'name': '添加预览水印',
+            'permissionId': '700',
+            'type': 'SDK'
+        },
+        {
+            'description': '书签、审图',
+            'name': '书签、审图',
+            'permissionId': '800',
+            'type': 'SDK'
+        },
+        {
+            'description': '批注面版',
+            'name': '批注面版',
+            'permissionId': '801',
+            'type': 'SDK'
+        },
+        {
+            'description': '书签定义和调用接口、布局信息和坐标转换接口、缩放比例和生成截图接口等',
+            'name': '书签定义和调用接口、布局信息和坐标转换接口、缩放比例和生成截图接口等',
+            'permissionId': '900',
+            'type': 'SDK'
+        },
+    ]
+}
+
+class Request {
+    constructor() {
+    }
+
+    getData(url, ticket, params, resType) {
+        return new Promise((res, rej) => {
+            let paramsArr = []
+            for (let k in params) {
+                paramsArr.push(encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
+            }
+            if (params) {
+                url = url + '?' + paramsArr.join('&')
+            }
+            let ajax = new XMLHttpRequest()
+            let ip = ticket ? userUrl : baseUrl
+            ajax.open('GET', ip + url)
+            resType && (ajax.responseType = resType)
+            ticket && Object.keys(ticket).forEach(key => {
+                ajax.setRequestHeader(key, ticket[key])
+            })
+            ajax.send()
+            ajax.onload = function () {
+                if (resType) res(ajax.response)
+                else {
+                    let data = JSON.parse(ajax.response)
+                    if (data.code === 0) {
+                        res(data.data)
+                    } else if (data.code === 2060) {
+                        rej(data.code)
+                    } else rej(data.msg)
+                }
+            }
+        })
+    }
+
+    postData(url, ticket, params, resType) {
+        return new Promise((res, rej) => {
+            let ajax = new XMLHttpRequest()
+            let ip = ticket ? userUrl : baseUrl
+            ajax.open('POST', ip + url)
+            resType && (ajax.responseType = resType)
+            ajax.setRequestHeader('content-type', 'application/json')
+            ticket && Object.keys(ticket).forEach(key => {
+                ajax.setRequestHeader(key, ticket[key])
+            })
+            ajax.send(params)
+            ajax.onreadystatechange = function () {
+                if (ajax.readyState === 4) {
+                    if (ajax.status === 200) {
+                        res(ajax.response)
+                    } else {
+                        rej()
+                    }
+                }
+            }
+        })
+    }
+
+    get(url, params, resType) {
+        if (appKey) {
+            let ticket = { 'x-ca-key': appKey }
+            return this.getData(url, ticket, params, resType)
+        } else {
+            return this.getData('/auth/js/ticket?url=' + url).then(res => {
+                let ticket = {
+                    'x-ca-key': res.appKey,
+                    'x-ca-nonce': res.nonce,
+                    'x-ca-date': res.timestamp,
+                    'x-ca-signature': res.signature,
+                }
+                return ticket
+            }).then(ticket => {
+                return this.getData(url, ticket, params, resType)
+            })
+        }
+    }
+
+    post(url, params, resType) {
+        if (appKey) {
+            let ticket = { 'x-ca-key': appKey }
+            return this.postData(url, ticket, params, resType)
+        } else {
+            return this.getData('/auth/js/ticket?url=' + url).then(res => {
+                let ticket = {
+                    'x-ca-key': res.appKey,
+                    'x-ca-nonce': res.nonce,
+                    'x-ca-date': res.timestamp,
+                    'x-ca-signature': res.signature,
+                }
+                return ticket
+            }).then(ticket => {
+                return this.postData(url, ticket, params, resType)
+            })
+        }
+
+    }
+
+    arrayBufferToBase64(buffer) {
+        let binary = '';
+        let bytes = new Uint8Array(buffer);
+        let len = bytes.byteLength;
+        for (let i = 0; i < len; i++) {
+            binary += String.fromCharCode(bytes[i]);
+        }
+        return btoa(binary);
+    }
+
+    fontDownload(fileId) {
+        return this.get('/api/js/v1/font/gzip', { fileId: fileId, projectId: 0 }, 'arraybuffer')
+    }
+
+    getTransferStatus(){
+        let params = { id: docId }
+        params = JSON.stringify(params)
+        return this.post('/api/js/v1/doc/transferStatus', params,'json')
+    }
+
+    transferDoc() {
+        return this.get('/api/js/v1/doc/details', { docId: docId })
+    }
+
+    getDisplayData(handleId = 34) {
+        return this.get('/api/js/v1/layout/lmf', { projectId: 0, handleId, docId: docId })
+    }
+
+    filePartDownload(lmfId) {
+        return this.get('/api/js/v1/file/partDownload', { fileId: lmfId }, 'arraybuffer')
+    }
+
+    getFileInfo(lmfId) {
+        return this.get('/api/js/v1/file/info', { id: lmfId })
+    }
+
+    getXrefRelation() {
+        return this.get('/api/js/v1/xref/info', { id: docId })
+    }
+
+    getXrefThumb(fileId) {
+        return this.get('/api/js/v1/file/partDownload', { fileId: fileId }, 'arraybuffer').then(res => {
+            let url = this.arrayBufferToBase64(res);
+            return 'data:image/jpeg;base64,' + url;
+        })
+    }
+
+    getXrefFile(handleId, xrefIds) {
+        let params = { docId: docId, handleId: handleId, xrefIds: xrefIds }
+        params = JSON.stringify(params)
+        return this.post('/api/js/v1/xref', params, 'json')
+    }
+
+    getImageInfo(filePath) {
+        let params = { docId: docId, path: filePath }
+        params = JSON.stringify(params)
+        return this.post('/api/js/v1/link', params, 'json')
+    }
+
+    getImageData(fileId) {
+        return this.get('/api/js/v1/file/partDownload', { fileId: fileId }, 'arraybuffer').then(res => {
+            let url = this.arrayBufferToBase64(res);
+            return 'data:image/jpeg;base64,' + url;
+        })
+    }
+
+    getPlotData(params) {
+        let data = JSON.stringify(params)
+        return this.post('/api/js/v1/doc/print', data, 'arraybuffer')
+    }
+
+    getBatchPlot(params) {
+        let data = JSON.stringify(params)
+        return this.post('/api/js/v1/doc/batchPrint', data, 'arraybuffer')
+    }
+
+    getRegenData(params) {
+        Object.assign(params, { docId: docId })
+        let data = JSON.stringify(params)
+        return this.post('/api/js/v1/layout/regen', data, 'arraybuffer')
+    }
+}
+
+ZwCloud2D.ZwDataProcessor.ZwSetConnectUrl = (url1, url2) => {
+    userUrl = url1
+    baseUrl = url2;
+}
+
+ZwCloud2D.ZwDataProcessor.ZwSetAppKey = (key) => {
+    appKey = key
+}
+
+ZwCloud2D.ZwDataProcessor.ZwSetLoadDwg = (path) => {
+    docId = path;
+}
+
+ZwCloud2D.ZwDataProcessor.ZwLoad = () => {
+
+    let req = new Request();
+
+    // 切换布局时候触发回调
+    ZwCloud2D.ZwMessageCallback.ZwEvtChangeLayout = layout => {
+        req.getDisplayData(layout.handleId).then(result => {
+            ZwCloud2D.ZwDataProcessor.ZwGetLmfData(result.lmfId).then(lmfInfo => {
+                if (lmfInfo) {
+                    function zcGetFileInfo() {
+                        req.getFileInfo(result.lmfId).then(fileInfo => {
+
+                            let curTimestamp = new Date(fileInfo.updateTime || fileInfo.createTime).getTime();
+
+                            if (lmfInfo.hasCache && curTimestamp.toString() === lmfInfo.timestamp) {
+                                ZwCloud2D.ZwDataManager.ZwSetDwgData(result.lmfId)
+                            } else {
+                                req.filePartDownload(result.lmfId).then(lmfInfo => {
+                                    ZwCloud2D.ZwDataManager.ZwSetDwgData(result.lmfId, lmfInfo, curTimestamp)
+                                })
+                            }
+                        }).catch((res) => {
+                            if (res === 2060) {
+                                this.timer = setTimeout(() => {
+                                    clearTimeout(this.timer)
+                                    zcGetFileInfo()
+                                }, 3000);
+                            } else {
+                                console.error(res)
+                            }
+                        })
+                    }
+                    zcGetFileInfo()
+                }
+            });
+        }).catch(error => {
+            console.error(error)
+        })
+    };
+
+    ZwCloud2D.ZwMessageCallback.ZwEvtLoadXrefData = data => {
+        req.getXrefFile(data.handleId, data.xrefIds).then(xrefFile => {
+            if (xrefFile.data.fileId) {
+                req.filePartDownload(xrefFile.data.fileId).then(fileData => {
+                    ZwCloud2D.ZwDataManager.ZwSetXrefData(fileData);
+                })
+            } else {
+                ZwCloud2D.ZwDataManager.ZwSetXrefData();
+            }
+        }).catch(() => {
+            ZwCloud2D.ZwDataManager.ZwSetXrefData();
+        })
+    };
+
+    ZwCloud2D.ZwMessageCallback.ZwEvtLoadImageData = data => {
+        let pArr = new Array();
+        let imageMap = new Map();
+        data.forEach((imageUrl) => {
+            pArr.push(new Promise((res, rej) => {
+                req.getImageInfo(imageUrl).then(info => {
+                    if (info.data.fileId) {
+                        req.getImageData(info.data.fileId).then(result => {
+                            imageMap.set(imageUrl, result);
+                            res(true)
+                        })
+                    } else {
+                        res(true)
+                    }
+                }).catch(err => {
+                    res(true);
+                });
+            }));
+        });
+        Promise.all(pArr).then(() => {
+            ZwCloud2D.ZwDataManager.ZwSetImageData(imageMap);
+        }).catch(error => {
+            console.error(error)
+        });
+    };
+    ZwCloud2D.ZwMessageCallback.ZwEvtPlotDwg = (data) => {
+        let params = Object.assign(data.params, { docId: docId })
+        if (params.isZwPlot) {
+            req.getBatchPlot(params).then(res => {
+                ZwCloud2D.ZwDataManager.ZwSetPlotData(data, res);
+                ZwCloud2D.ZwEditor.ZwSetLoadingState(false);
+            })
+        } else {
+            req.getPlotData(params).then(res => {
+                ZwCloud2D.ZwDataManager.ZwSetPlotData(data, res);
+                ZwCloud2D.ZwEditor.ZwSetLoadingState(false);
+            })
+        }
+    };
+    ZwCloud2D.ZwMessageCallback.ZwEvtGetRegenData = (data) => {
+        req.getRegenData(data).then(res => {
+            ZwCloud2D.ZwDataManager.ZwSetRegenData(res);
+        }).catch(() => {
+            ZwCloud2D.ZwDataManager.ZwSetRegenData(null);
+        });
+    };
+    let ZwMain=()=>{
+        req.transferDoc().then(data => {
+
+            ZwCloud2D.ZwDataManager.ZwSetSdkPermission(fullVersionPermissions);
+    
+            // 显示当前布局的数据
+            ZwCloud2D.ZwDataManager.ZwSetDwgInfo({ fonts: data.fonts, layouts: data.layouts, name: data.name }).then(res => {
+                let pArr = []
+                let fontArr = []
+    
+                res.missingFonts.forEach(font => {
+                    let arr = font.name.split('.');
+                    let type = (arr[arr.length - 1] || '').toUpperCase();
+    
+                    pArr.push(req.fontDownload(font.fileId).then(data => {
+                        if (data.byteLength > 0) {
+                            fontArr.push(
+                                {
+                                    name: font.name,
+                                    type: type,
+                                    data: data,
+                                }
+                            );
+                        }
+                    }));
+                });
+    
+                Promise.all(pArr).then(() => {
+                    ZwCloud2D.ZwDataManager.ZwSetFontDataList(fontArr).then(() => {
+    
+                        req.getDisplayData(res.layout.handleId).then(result => {
+    
+                            req.getXrefRelation().then(xrefRelations => {
+                                let xrefPromises = [];
+                                let srcMap = new Map();
+                                xrefRelations.forEach((xrefRelation) => {
+                                    if (xrefRelation.fileId) {
+                                        xrefPromises.push(new Promise((res, rej) => {
+                                            req.getXrefThumb(xrefRelation.fileId).then(xrefThumb => {
+                                                srcMap.set(xrefRelation.fileId, xrefThumb);
+                                                res(true);
+                                            });
+                                        }));
+                                    }
+                                });
+                                Promise.all(xrefPromises).then(() => {
+                                    let params = { docName: data.name, xrefRelations: xrefRelations, srcMap: srcMap };
+                                    ZwCloud2D.ZwDataManager.ZwSetXrefList(params);
+                                }).catch(() => {
+                                    let params = { docName: data.name, xrefRelations: xrefRelations, srcMap: srcMap };
+                                    ZwCloud2D.ZwDataManager.ZwSetXrefList(params);
+                                });
+                            });
+    
+                            req.getFileInfo(result.lmfId).then(lmfInfo => {
+                                let curTimestamp = new Date(lmfInfo.updateTime || lmfInfo.createTime).getTime();
+                                if (res.hasCache && res.timestamp === curTimestamp.toString()) {
+                                    ZwCloud2D.ZwDataManager.ZwSetDwgData(result.lmfId)
+                                } else {
+                                    req.filePartDownload(result.lmfId).then(lmfInfo => {
+                                        ZwCloud2D.ZwDataManager.ZwSetDwgData(result.lmfId, lmfInfo, curTimestamp)
+                                    })
+                                }
+                            }).catch(error => {
+                                console.error(error)
+                            })
+    
+                        }).catch(error => {
+                            console.error(error)
+                        })
+                    })
+                }).catch(error => {
+                    console.error(error)
+                })
+            });
+        }).catch(error => {
+            console.error(error)
+        });
+    }
+    let getTransferStatus=()=>{
+        req.getTransferStatus().then(fileInfo=>{
+            let status=fileInfo.data.status
+            if (status === 1) {
+                let timer = setTimeout(() => {
+                    clearTimeout(timer)
+                    getTransferStatus()
+                }, 3000);
+            } else if(status === 2) {
+                ZwMain()
+            }else if(status === 3){
+                console.error(fileInfo.failedReason)
+            }
+        }).catch(err=>{
+            console.error(err)
+        })
+    }
+    getTransferStatus()
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
public/ZwCloud2DSDK/ZwWasmJs.js


BIN
public/ZwCloud2DSDK/ZwWasmJs.wasm


BIN
public/ZwCloud2DSDK/adinit.dat


BIN
public/ZwCloud2DSDK/home_m.png


BIN
public/ZwCloud2DSDK/image1.png


BIN
public/ZwCloud2DSDK/image2.png


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
public/ZwCloud2DSDK/readLMFData.js


BIN
public/ZwCloud2DSDK/text.png


BIN
public/ZwCloud2DSDK/textGlyph/SimSun-01.ttf


BIN
src/assets/SideMenu/cadIcon.png


BIN
src/assets/UnityMenu/cad.png


+ 32 - 25
src/components/AuditForm/ComponentLibrary.js

@@ -3,16 +3,16 @@ import React, { useState } from 'react';
 import { COMPONENT_LIST } from './constant';
 import { COMPONENT_LIST } from './constant';
 
 
 function ComponentLibrary(props) {
 function ComponentLibrary(props) {
-  const { visible, onCancel, onOk } = props;
-  const [currnetItem, setCurrentItem] = useState(null);
+  const { visible, onCancel, onOk, addToTable } = props;
+  const [currentItem, setCurrentItem] = useState(null);
 
 
   const handleOk = () => {
   const handleOk = () => {
-    if (!currnetItem) {
+    if (!currentItem) {
       message.error('请选择控件');
       message.error('请选择控件');
       return;
       return;
     }
     }
     setCurrentItem(null);
     setCurrentItem(null);
-    onOk?.(currnetItem);
+    onOk?.(currentItem);
   };
   };
   const handleCancel = () => {
   const handleCancel = () => {
     setCurrentItem(null);
     setCurrentItem(null);
@@ -21,27 +21,34 @@ function ComponentLibrary(props) {
   return (
   return (
     <Modal open={visible} onCancel={handleCancel} onOk={handleOk}>
     <Modal open={visible} onCancel={handleCancel} onOk={handleOk}>
       <Row gutter={12} style={{ paddingTop: 20 }}>
       <Row gutter={12} style={{ paddingTop: 20 }}>
-        {COMPONENT_LIST.map((item) => (
-          <Col span={8} key={item.componentName}>
-            <div
-              onClick={() => setCurrentItem(item)}
-              style={{
-                display: 'flex',
-                justifyContent: 'flex-start',
-                alignItems: 'center',
-                border:
-                  item == currnetItem ? '1px solid #1890FF' : '1px solid #aaa',
-                width: '100%',
-                padding: '4px 12px',
-                cursor: 'pointer',
-                margin: '10px 0',
-              }}
-            >
-              {item.icon}
-              <span style={{ marginLeft: 8 }}>{item.props.label}</span>
-            </div>
-          </Col>
-        ))}
+        {COMPONENT_LIST.map((item) => {
+          if (addToTable && item.props.label === '表格') {
+            return null;
+          }
+          return (
+            <Col span={8} key={item.componentName}>
+              <div
+                onClick={() => setCurrentItem(item)}
+                style={{
+                  display: 'flex',
+                  justifyContent: 'flex-start',
+                  alignItems: 'center',
+                  border:
+                    item === currentItem
+                      ? '1px solid #1890FF'
+                      : '1px solid #aaa',
+                  width: '100%',
+                  padding: '4px 12px',
+                  cursor: 'pointer',
+                  margin: '10px 0',
+                }}
+              >
+                {item.icon}
+                <span style={{ marginLeft: 8 }}>{item.props.label}</span>
+              </div>
+            </Col>
+          );
+        })}
       </Row>
       </Row>
     </Modal>
     </Modal>
   );
   );

+ 124 - 15
src/components/AuditForm/FormContent.js

@@ -1,13 +1,15 @@
-import { Form } from 'antd';
+import { Button, Form } from 'antd';
 import React, { useState, useMemo } from 'react';
 import React, { useState, useMemo } from 'react';
 import {
 import {
   ArrowUpOutlined,
   ArrowUpOutlined,
   ArrowDownOutlined,
   ArrowDownOutlined,
   DeleteOutlined,
   DeleteOutlined,
+  PlusOutlined,
 } from '@ant-design/icons';
 } from '@ant-design/icons';
+import position from '../Flow/node/fields/position';
 
 
 function FormContent(props) {
 function FormContent(props) {
-  const { list, onChange, onSelect } = props;
+  const { list, onChange, onSelect, onTableColumnChange } = props;
   const [currentItem, setCurrentItem] = useState(null);
   const [currentItem, setCurrentItem] = useState(null);
 
 
   const linkedList = useMemo(() => {
   const linkedList = useMemo(() => {
@@ -41,22 +43,24 @@ function FormContent(props) {
     _list[index] = temp;
     _list[index] = temp;
     onChange(_list);
     onChange(_list);
   };
   };
-  const handleSelect = (index) => {
-    setCurrentItem(index);
-    onSelect(index);
+
+  const handleFormItemClick = (id) => {
+    setCurrentItem(id[0]);
+    onSelect(id);
   };
   };
+
   return (
   return (
     <div style={{ width: 500, height: 636, overflow: 'auto' }}>
     <div style={{ width: 500, height: 636, overflow: 'auto' }}>
       {list.map((item, index) => {
       {list.map((item, index) => {
         const btns = (
         const btns = (
           <>
           <>
-            {index != 0 && (
+            {index !== 0 && (
               <ArrowUpOutlined
               <ArrowUpOutlined
                 style={{ marginLeft: 5, cursor: 'pointer' }}
                 style={{ marginLeft: 5, cursor: 'pointer' }}
                 onClick={() => handleUp(index)}
                 onClick={() => handleUp(index)}
               />
               />
             )}
             )}
-            {index != list.length - 1 && (
+            {index !== list.length - 1 && (
               <ArrowDownOutlined
               <ArrowDownOutlined
                 style={{ marginLeft: 5, cursor: 'pointer' }}
                 style={{ marginLeft: 5, cursor: 'pointer' }}
                 onClick={() => handleDown(index)}
                 onClick={() => handleDown(index)}
@@ -68,14 +72,16 @@ function FormContent(props) {
             />
             />
           </>
           </>
         );
         );
+
         return (
         return (
           <FormItem
           <FormItem
             key={item.props?.id}
             key={item.props?.id}
             islinked={
             islinked={
-              linkedList?.findIndex((id) => id == item.props?.id) !== -1
+              linkedList?.findIndex((id) => id === item.props?.id) !== -1
             } //不等于-1表示是被单选框关联的组件需要置灰
             } //不等于-1表示是被单选框关联的组件需要置灰
-            active={index == currentItem}
-            onClick={() => handleSelect(index)}
+            active={item.props?.id === currentItem}
+            onClick={handleFormItemClick}
+            onTableColumnChange={onTableColumnChange}
             item={item}
             item={item}
             btns={btns}
             btns={btns}
           />
           />
@@ -86,8 +92,46 @@ function FormContent(props) {
 }
 }
 
 
 function FormItem(props) {
 function FormItem(props) {
-  const { item, btns, active, onClick, islinked = false } = props;
+  const {
+    item,
+    btns,
+    active,
+    onClick,
+    onTableColumnChange,
+    islinked = false,
+  } = props;
   const { label, placeholder, required } = item.props;
   const { label, placeholder, required } = item.props;
+
+  // 子控件激活id
+  const [selectColumnID, setSelectColumnID] = useState('');
+
+  // 新增列时通过id定位
+  const addTableColumn = (event) => {
+    // 记录当前表格uuid
+    onTableColumnChange(item.props.id);
+  };
+
+  // 修改表格内部的控件顺序
+  const changeIndex = (index, operate) => {
+    let newCol = [...item.columns];
+    const prev = newCol[index - 1];
+    const next = newCol[index + 1];
+    switch (operate) {
+      case 'up':
+        newCol[index - 1] = newCol[index];
+        newCol[index] = prev;
+        break;
+      case 'down':
+        newCol[index + 1] = newCol[index];
+        newCol[index] = next;
+        break;
+      case 'delete':
+        newCol.splice(index, 1);
+        break;
+    }
+    onTableColumnChange(item.props.id, newCol);
+  };
+
   return (
   return (
     <div
     <div
       style={{
       style={{
@@ -95,13 +139,24 @@ function FormItem(props) {
         marginBottom: 20,
         marginBottom: 20,
         padding: '4px 12px',
         padding: '4px 12px',
         border: islinked ? '1px solid #bebcbc' : '1px solid #666',
         border: islinked ? '1px solid #bebcbc' : '1px solid #666',
-        borderLeft: active ? '10px solid #1890FF' : '1px solid #666',
+        borderLeft:
+          active && !item.isTable ? '10px solid #1890FF' : '1px solid #666',
+      }}
+      onClick={(e) => {
+        // 停止冒泡
+        e.stopPropagation();
+        if (item.isColumn === undefined) {
+          // 触发正常的事件
+          onClick([item.props.id]);
+        } else {
+          // 触发列中的click事件
+          onClick();
+        }
       }}
       }}
-      onClick={onClick}
     >
     >
       <div
       <div
         style={{
         style={{
-          fontSzie: 24,
+          fontSize: 16,
           color: '#000',
           color: '#000',
           fontWeight: 'bold',
           fontWeight: 'bold',
           position: 'relative',
           position: 'relative',
@@ -120,7 +175,61 @@ function FormItem(props) {
           {btns}
           {btns}
         </div>
         </div>
       </div>
       </div>
-      <div style={{ color: '#999', fontSize: 16 }}>{placeholder}</div>
+      {item.isTable ? (
+        <div style={{ padding: '10px 0 5px 0' }}>
+          {item.columns.map((column, index) => {
+            // column的按钮和外部的控件按钮不一样
+            const colBtns = (
+              <>
+                {index !== 0 && (
+                  <ArrowUpOutlined
+                    style={{ marginLeft: 5, cursor: 'pointer' }}
+                    onClick={() => {
+                      changeIndex(index, 'up');
+                    }}
+                  />
+                )}
+                {index !== item.columns.length - 1 && (
+                  <ArrowDownOutlined
+                    style={{ marginLeft: 5, cursor: 'pointer' }}
+                    onClick={() => {
+                      changeIndex(index, 'down');
+                    }}
+                  />
+                )}
+                <DeleteOutlined
+                  style={{ marginLeft: 5, cursor: 'pointer' }}
+                  onClick={() => {
+                    changeIndex(index, 'delete');
+                  }}
+                />
+              </>
+            );
+            return (
+              <FormItem
+                key={column.props?.id}
+                item={column}
+                active={active && column.props?.id === selectColumnID}
+                onClick={() => {
+                  setSelectColumnID(column.props.id);
+                  onClick([item.props.id, column.props.id]);
+                }}
+                btns={colBtns}
+              />
+            );
+          })}
+          <Button
+            type="dashed"
+            block
+            onClick={addTableColumn}
+            icon={<PlusOutlined />}
+          >
+            点击添加列
+          </Button>
+        </div>
+      ) : (
+        <div style={{ color: '#999', fontSize: 16 }}>{placeholder}</div>
+      )}
     </div>
     </div>
   );
   );
 }
 }

+ 147 - 0
src/components/AuditForm/FormulaModal.js

@@ -0,0 +1,147 @@
+import { useEffect, useMemo, useState } from 'react';
+import { Divider, Input, Modal, Select, Table, message, Button } from 'antd';
+
+const { TextArea } = Input;
+
+export const FormulaType = {
+  Filed: 'filed',
+  Symbol: 'symbol',
+  Number: 'number',
+};
+
+const FormulaModal = (props) => {
+  const { item, numFiledList = [], visible, onCancel, onChange } = props;
+  const symbolList = ['+', '-', '*', '/', '(', ')'];
+  const numberList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.'];
+
+  const [formula, setFormula] = useState([]);
+
+  useEffect(() => {
+    if (!visible) setFormula([]);
+    if (item?.props) setFormula(item.props.formula || []);
+  }, [visible, item]);
+
+  const value = useMemo(() => {
+    const strList = formula.map((item) =>
+      item.type == FormulaType.Filed ? `【${item.label}】` : item.label,
+    );
+    return '计算公式=' + strList.join('');
+  }, [formula]);
+  console.log('-----------------', formula);
+
+  const isSameBeforItem = (type) => {
+    return formula.length > 0 && formula[formula.length - 1].type == type;
+  };
+
+  const handlerChange = (type, item) => {
+    let obj = {};
+    console.log(formula[formula.length - 1]);
+    switch (type) {
+      case FormulaType.Filed:
+        if (isSameBeforItem(FormulaType.Filed)) {
+          message.error('不能选择连续两个组件');
+        }
+        obj = {
+          type: FormulaType.Filed,
+          id: item.props.id,
+          label: item.props.label,
+        };
+        setFormula([...formula, obj]);
+        break;
+      case FormulaType.Symbol:
+        if (isSameBeforItem(FormulaType.Symbol)) {
+          message.error('不能选择连续两个符号');
+        }
+        obj = { type: FormulaType.Symbol, label: item };
+        setFormula([...formula, obj]);
+        break;
+      case FormulaType.Number:
+        //如果前一个选择的也是数字则合并数字 否则直接添加
+        if (isSameBeforItem(FormulaType.Number)) {
+          const len = formula.length - 1;
+          const label = formula[len].label + item;
+          obj = { type: FormulaType.Number, label };
+          const result = [...formula];
+          result[len] = obj;
+          setFormula(result);
+        } else {
+          obj = { type: FormulaType.Number, label: item };
+          setFormula([...formula, obj]);
+        }
+        break;
+    }
+  };
+
+  return (
+    <Modal
+      title="编辑计算公式"
+      open={visible}
+      onCancel={onCancel}
+      onOk={() => {
+        onChange?.({ ...item.props, formula, formulaLabel: value });
+      }}
+      width={1000}
+      pagination={false}
+    >
+      <Divider />
+
+      <Button
+        type="primary"
+        style={{ marginBottom: '20px' }}
+        onClick={() => setFormula([])}
+      >
+        清空
+      </Button>
+      <TextArea value={value} />
+      <div style={{ margin: '20px 20px 20px 0' }}>
+        计算对象:
+        {numFiledList.map((item, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Filed, item)}
+          >
+            {item.props.label}
+          </span>
+        ))}
+      </div>
+      <div style={{ margin: '0 20px 20px 0' }}>
+        计算符号:
+        {symbolList.map((item, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Symbol, item)}
+          >
+            {item}
+          </span>
+        ))}
+      </div>
+      <div style={{ margin: '0 20px 20px 0' }}>
+        数字键盘:
+        {numberList.map((item, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Number, item)}
+          >
+            {item}
+          </span>
+        ))}
+      </div>
+    </Modal>
+  );
+};
+export default FormulaModal;

+ 71 - 4
src/components/AuditForm/ItemAttribute.js

@@ -1,9 +1,11 @@
 import { Form, Button, Switch, Input, Radio, Space, Row } from 'antd';
 import { Form, Button, Switch, Input, Radio, Space, Row } from 'antd';
 import React, { useMemo, useState, useEffect } from 'react';
 import React, { useMemo, useState, useEffect } from 'react';
 import { DeleteOutlined } from '@ant-design/icons';
 import { DeleteOutlined } from '@ant-design/icons';
-function ItemAttribute(props) {
-  const { item, onChange, onRelClick } = props;
 
 
+function ItemAttribute(props) {
+  const { item, onChange, onRelClick, onFormulaClick } = props;
+  console.log(item);
+  if (!item) return null;
   const renderForm = () => {
   const renderForm = () => {
     let FormContent;
     let FormContent;
     const formProps = {
     const formProps = {
@@ -57,16 +59,22 @@ function ItemAttribute(props) {
       case 'DDDateField':
       case 'DDDateField':
         FormContent = <DDDateField {...formProps} />;
         FormContent = <DDDateField {...formProps} />;
         break;
         break;
+      case 'DIYTable':
+        FormContent = <TableName {...formProps} />;
+        break;
       case 'CodeField':
       case 'CodeField':
         FormContent = <CodeField {...formProps} />;
         FormContent = <CodeField {...formProps} />;
         break;
         break;
+      case 'FormulaField':
+        FormContent = (
+          <FormulaField {...formProps} onFormulaClick={onFormulaClick} />
+        );
+        break;
     }
     }
 
 
     return FormContent;
     return FormContent;
   };
   };
 
 
-  if (!item) return null;
-
   return (
   return (
     <div
     <div
       style={{
       style={{
@@ -121,6 +129,7 @@ function InnerContactField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function DepartmentField(props) {
 function DepartmentField(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -154,6 +163,7 @@ function DepartmentField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function ProjectField(props) {
 function ProjectField(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -229,6 +239,7 @@ function ManufacturerField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function TextField(props) {
 function TextField(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -258,6 +269,7 @@ function TextField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function DDAttachment(props) {
 function DDAttachment(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -329,6 +341,7 @@ function DDDateField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function TextareaField(props) {
 function TextareaField(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -354,6 +367,7 @@ function TextareaField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function DDSelectField(props) {
 function DDSelectField(props) {
   const { item, btns, onFinish, onRelClick } = props;
   const { item, btns, onFinish, onRelClick } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -396,6 +410,7 @@ function DDSelectField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
 function DDMultiSelectField(props) {
 function DDMultiSelectField(props) {
   const { item, btns, onFinish } = props;
   const { item, btns, onFinish } = props;
   const [form] = Form.useForm();
   const [form] = Form.useForm();
@@ -559,3 +574,55 @@ function NumberField(props) {
     </Form>
     </Form>
   );
   );
 }
 }
+
+function TableName(props) {
+  const { item, btns, onFinish } = props;
+  const [form] = Form.useForm();
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 4 }}
+      wrapperCol={{ span: 20 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
+      <Form.Item label="表格名称" name="label">
+        <Input />
+      </Form.Item>
+      {btns}
+    </Form>
+  );
+}
+
+function FormulaField(props) {
+  const { item, btns, onFinish, onFormulaClick } = props;
+  const [form] = Form.useForm();
+  const value = useMemo(() => {
+    return item.props.formulaLabel;
+  }, [item.props]);
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 4 }}
+      wrapperCol={{ span: 20 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={(values) => onFinish({ ...item.props, ...values })}
+    >
+      <Form.Item label="标题" name="label">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字" name="placeholder">
+        <Input />
+      </Form.Item>
+      <Form.Item label="计算公式">
+        <Input value={value} onClick={onFormulaClick} />
+      </Form.Item>
+      <Form.Item label="必填" name="required" valuePropName="checked">
+        <Switch />
+      </Form.Item>
+      {btns}
+    </Form>
+  );
+}

+ 19 - 0
src/components/AuditForm/constant.js

@@ -12,6 +12,8 @@ import {
   ProjectOutlined,
   ProjectOutlined,
   SolutionOutlined,
   SolutionOutlined,
   NumberOutlined,
   NumberOutlined,
+  TableOutlined,
+  LaptopOutlined,
 } from '@ant-design/icons';
 } from '@ant-design/icons';
 
 
 export const COMPONENT_LIST = [
 export const COMPONENT_LIST = [
@@ -141,4 +143,21 @@ export const COMPONENT_LIST = [
       required: false,
       required: false,
     },
     },
   },
   },
+  {
+    componentName: 'DIYTable',
+    icon: <TableOutlined />,
+    props: {
+      label: '表格',
+      required: false,
+    },
+  },
+  {
+    componentName: 'FormulaField',
+    icon: <LaptopOutlined />,
+    props: {
+      label: '计算公式',
+      placeholder: '自动计算数值',
+      required: false,
+    },
+  },
 ];
 ];

+ 134 - 13
src/components/AuditForm/index.js

@@ -5,17 +5,49 @@ import ItemAttribute from './ItemAttribute';
 import { uuidv4 } from '@antv/xflow';
 import { uuidv4 } from '@antv/xflow';
 import { Button } from 'antd';
 import { Button } from 'antd';
 import RelModal from './RelModal';
 import RelModal from './RelModal';
+import FormulaModal from './FormulaModal';
 
 
 function AuditForm(props) {
 function AuditForm(props) {
   const { value, onChange } = props;
   const { value, onChange } = props;
   const [formList, setFormList] = useState([]);
   const [formList, setFormList] = useState([]);
-  const [select, setSelect] = useState(-1);
+  const [select, setSelect] = useState('');
+  const [selectList, setSelectList] = useState([]);
   const [visible, setVisible] = useState(false);
   const [visible, setVisible] = useState(false);
+
   const [relVisible, setRelVisible] = useState(false); //关联选项弹窗
   const [relVisible, setRelVisible] = useState(false); //关联选项弹窗
+  const [forVisible, setForVisible] = useState(false); //计算公式弹窗
+  const [addToTable, setAddToTable] = useState(false);
+  const [currentTableID, setCurrentTableID] = useState('');
+
+  console.log('-----------------', formList);
 
 
   const handleAddItem = (item) => {
   const handleAddItem = (item) => {
-    const formItem = generateItem(item);
-    handleChangeList([...formList, formItem]);
+    if (addToTable) {
+      // 新增列处理
+      const column = generateItem(item);
+      // 找到对应的表格
+      const tableItem = formList.find(
+        (item) => item.props.id === currentTableID,
+      );
+      column.isColumn = true;
+      // 把新增的列加入到表格中
+      tableItem.columns.push(column);
+      // 把新增列的表格放回
+      const newFormList = [];
+      for (const item of formList) {
+        if (item.props.id !== currentTableID) {
+          newFormList.push(item);
+        } else {
+          newFormList.push(tableItem);
+        }
+      }
+      handleChangeList(newFormList);
+      setCurrentTableID('');
+    } else {
+      const formItem = generateItem(item);
+      handleChangeList([...formList, formItem]);
+    }
+    setAddToTable(false);
     setVisible(false);
     setVisible(false);
   };
   };
 
 
@@ -24,14 +56,40 @@ function AuditForm(props) {
       ...item,
       ...item,
       props: { ...item.props, id: `${item.componentName}_${uuidv4()}` },
       props: { ...item.props, id: `${item.componentName}_${uuidv4()}` },
     };
     };
+    // 如果是表格的话
+    if (item.props.label === '表格') {
+      newItem.columns = [];
+      newItem.isTable = true;
+    }
     delete newItem.icon;
     delete newItem.icon;
     return newItem;
     return newItem;
   };
   };
 
 
-  const onChangeAttribute = (newItem) => {
-    let oldValue = formList[select].props;
-    formList[select].props = { ...oldValue, ...newItem };
-    handleChangeList([...formList]);
+  const onChangeAttribute = (newItemProps) => {
+    let oldFormItem = findFormItem();
+    let newFormList = [];
+    // 是列
+    if (oldFormItem.isColumn) {
+      // 找到表格和col然后改掉属性
+      for (const item of formList) {
+        if (item.isTable) {
+          for (const column of item.columns) {
+            if (column.props.id === selectList[selectList.length - 1]) {
+              column.props = { ...column.props, ...newItemProps };
+            }
+          }
+        }
+        newFormList.push(item);
+      }
+    } else {
+      for (const item of formList) {
+        if (item.props.id === select) {
+          item.props = { ...item.props, ...newItemProps };
+        }
+        newFormList.push(item);
+      }
+    }
+    handleChangeList(newFormList);
   };
   };
 
 
   const handleChangeList = (list) => {
   const handleChangeList = (list) => {
@@ -39,6 +97,50 @@ function AuditForm(props) {
     onChange?.(list);
     onChange?.(list);
   };
   };
 
 
+  // 表格列变化时(新增,调整顺序)
+  const handleTableColumnChange = (id, newCole = []) => {
+    if (newCole.length) {
+      // 调整col顺序
+      const tableItem = formList.find((item) => item.props.id === id);
+      tableItem.columns = newCole;
+      const newFormList = [];
+      for (const item of formList) {
+        if (item.props.id !== currentTableID) {
+          newFormList.push(item);
+        } else {
+          newFormList.push(tableItem);
+        }
+      }
+      handleChangeList(newFormList);
+    } else {
+      setCurrentTableID(id);
+      setAddToTable(true);
+    }
+  };
+
+  const handleFormContentSelect = (ids) => {
+    setSelectList(ids);
+    setSelect(ids[0]);
+  };
+
+  const findFormItem = () => {
+    let formItem = formList.find((item) => item.props.id === selectList[0]);
+
+    if (formItem?.isTable) {
+      // 如果是表格的话,还要寻找内部的被点击的col
+      if (selectList.length === 1) {
+        return formItem || null;
+      }
+      return (
+        formItem.columns.find(
+          (item) => item.props.id === selectList[selectList.length - 1],
+        ) || null
+      );
+    } else {
+      return formList.find((item) => item.props.id === select) || null;
+    }
+  };
+
   useEffect(() => {
   useEffect(() => {
     if (value instanceof Array) {
     if (value instanceof Array) {
       setFormList([...value]);
       setFormList([...value]);
@@ -59,24 +161,31 @@ function AuditForm(props) {
         }}
         }}
       >
       >
         <FormContent
         <FormContent
-          onSelect={setSelect}
+          onSelect={handleFormContentSelect}
           onChange={handleChangeList}
           onChange={handleChangeList}
+          onTableColumnChange={handleTableColumnChange}
           list={formList}
           list={formList}
         ></FormContent>
         ></FormContent>
         <ItemAttribute
         <ItemAttribute
-          key={select}
-          item={formList[select]}
+          formList={formList}
+          key={selectList[selectList.length - 1]}
+          item={findFormItem()}
           onRelClick={() => setRelVisible(true)}
           onRelClick={() => setRelVisible(true)}
+          onFormulaClick={() => setForVisible(true)}
           onChange={onChangeAttribute}
           onChange={onChangeAttribute}
         ></ItemAttribute>
         ></ItemAttribute>
       </div>
       </div>
       <ComponentLibrary
       <ComponentLibrary
+        addToTable={addToTable}
         onOk={handleAddItem}
         onOk={handleAddItem}
-        visible={visible}
-        onCancel={() => setVisible(false)}
+        visible={visible || addToTable}
+        onCancel={() => {
+          setVisible(false);
+          setAddToTable(false);
+        }}
       />
       />
       <RelModal
       <RelModal
-        item={formList[select]}
+        item={formList.find((item) => item.props.id === select)}
         formList={formList}
         formList={formList}
         visible={relVisible}
         visible={relVisible}
         onCancel={() => setRelVisible(false)}
         onCancel={() => setRelVisible(false)}
@@ -85,6 +194,18 @@ function AuditForm(props) {
           onChangeAttribute(value);
           onChangeAttribute(value);
         }}
         }}
       />
       />
+      <FormulaModal
+        item={formList.find((item) => item.props.id === select)}
+        numFiledList={formList.filter(
+          (item) => item.componentName == 'NumberField',
+        )}
+        visible={forVisible}
+        onCancel={() => setForVisible(false)}
+        onChange={(value) => {
+          setForVisible(false);
+          onChangeAttribute(value);
+        }}
+      />
     </div>
     </div>
   );
   );
 }
 }

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

@@ -2,10 +2,10 @@ import React from 'react';
 import { DatePicker } from 'antd';
 import { DatePicker } from 'antd';
 
 
 function DDDateField(props) {
 function DDDateField(props) {
-  const { format = "", disabled, onChange, placeholder } = props;
+  const { format = '', disabled, onChange, placeholder } = props;
 
 
   const handleChange = (date) => {
   const handleChange = (date) => {
-    onChange?.(date.format('YYYY-MM-DD HH:mm:ss'));
+    onChange?.(date.format('YYYY-MM-DD HH:mm:ss'), props.id, props.label);
   };
   };
   return (
   return (
     <DatePicker
     <DatePicker

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

@@ -10,11 +10,11 @@ function DDSelectField(props) {
     <Select
     <Select
       style={{ width: '100%' }}
       style={{ width: '100%' }}
       disabled={disabled}
       disabled={disabled}
-      onChange={value => {
-        onChange(String(value));
+      onChange={(value) => {
+        onChange(String(value), props.id, props.label);
       }}
       }}
     >
     >
-      {options?.map(cur => {
+      {options?.map((cur) => {
         return (
         return (
           <Option key={cur} value={cur}>
           <Option key={cur} value={cur}>
             {cur}
             {cur}

+ 7 - 0
src/components/DDComponents/DIYTable/index.css

@@ -0,0 +1,7 @@
+.hidden {
+  display: none;
+}
+
+.p-8{
+  padding: 10px !important;
+}

+ 210 - 0
src/components/DDComponents/DIYTable/index.tsx

@@ -0,0 +1,210 @@
+import React, { useEffect, useState } from 'react';
+// @ts-ignore
+import { Button, Input, Table } from 'antd';
+import type { ColumnsType } from 'antd/lib/table';
+import DDSelectField from '@/components/DDComponents/DDSelectField';
+import './index.css';
+import DDDateField from '@/components/DDComponents/DDDateField';
+import NumberField from '@/components/DDComponents/NumberField';
+import TextNote from '@/components/DDComponents/TextNote';
+import { PlusOutlined } from '@ant-design/icons';
+
+interface IProps {
+  table?: any; // 整个表格
+  columns?: Array<any>; // 当前列配置
+  onChange?: (e?: any, id?: string, label?: string) => void; // 表格修改后的值
+  displayOnly?: boolean; // 是否仅用于展示
+}
+
+type TableDataType = {
+  index: number;
+  id?: string;
+  col1?: any;
+  col2?: any;
+  col3?: any;
+  col4?: any;
+  col5?: any;
+};
+
+function DIYTable(props: IProps) {
+  const { table, columns, displayOnly, onChange } = props;
+  // table数据
+  const [tableData, setTableData] = useState<TableDataType[]>([{ index: 1 }]);
+  // table 列配置
+  const [tableColumnDef, setTableColumnDef] = useState<ColumnsType<any>>([
+    {
+      title: '序号',
+      dataIndex: 'index',
+      className: 'hidden',
+    },
+  ]);
+
+  // 表单填写时的表格生成
+  const handleGenerateTable = () => {
+    if (columns !== undefined && columns.length) {
+      for (let index = 0; index < columns.length; index++) {
+        let column = columns[index];
+        let columnID = column.props.id;
+        let columnLabel = column.props.label;
+        let colDef: any = {
+          dataIndex: 'col' + (index + 1),
+          title: columnLabel || column.name,
+          className: 'p-8',
+        };
+        switch (column.componentName) {
+          case 'DDSelectField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              let id =
+                rowIndex + ',' + index + ';' + columnID + '>' + table.props.id;
+              return (
+                <DDSelectField
+                  id={id}
+                  label={columnLabel + '>' + table.props.label}
+                  style={{ padding: '0', margin: '0' }}
+                  options={column.props.options}
+                  disabled={column.props.disabled}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'DDDateField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              let id =
+                rowIndex + ',' + index + ';' + columnID + '>' + table.props.id;
+              return (
+                <DDDateField
+                  id={id}
+                  label={columnLabel + '>' + table.props.label}
+                  key={index + rowIndex + ''}
+                  style={{ padding: '0', margin: '0' }}
+                  placeholder={column.props.placeholder}
+                  format={column.props.format}
+                  disabled={column.props.disabled}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'NumberField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              let id =
+                rowIndex + ',' + index + ';' + columnID + '>' + table.props.id;
+              return (
+                <NumberField
+                  id={id}
+                  label={columnLabel + '>' + table.props.label}
+                  size="small"
+                  width="50%"
+                  style={{ padding: '4px 11px' }}
+                  disabled={column.props.disabled}
+                  unit={column.props.unit}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'TextField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              let id =
+                rowIndex + ',' + index + ';' + columnID + '>' + table.props.id;
+              return (
+                <Input
+                  disabled={column.props.disabled}
+                  placeholder={column.props.placeholder}
+                  onChange={(e) =>
+                    onChange?.(
+                      e.target.value,
+                      id,
+                      columnLabel + '>' + table.props.label,
+                    )
+                  }
+                />
+              );
+            };
+            break;
+          case 'TextNote':
+            colDef.title = '说明';
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              let id =
+                rowIndex + ',' + index + ';' + columnID + '>' + table.props.id;
+              return (
+                <TextNote
+                  id={id}
+                  style={{ padding: '0', margin: '0' }}
+                  value={column.props.placeholder}
+                />
+              );
+            };
+            break;
+        }
+        tableColumnDef.push(colDef);
+      }
+    }
+  };
+
+  // 当仅用作展示时
+  const handleDisplayOnly = () => {
+    const rows = columns;
+    const newTableData = [];
+    const newColumnDef: ColumnsType<any> = [];
+    if (rows && columns.length) {
+      for (let index = 0; index < rows.length; index++) {
+        // 把每一行的数据提出来到一个对象里
+        if (rows) {
+          const row = rows[index];
+
+          if (index === 0) {
+            // 列配置
+            row.forEach((col: any) => {
+              newColumnDef.push({ title: col.name, dataIndex: col.type });
+            });
+          }
+          let rowData: any = {};
+          row.forEach((col: any) => {
+            rowData[col.type] = col.value[0];
+            rowData.key = col.id + index;
+          });
+          newTableData.push(rowData);
+        }
+      }
+      setTableColumnDef(newColumnDef);
+      setTableData(newTableData);
+    }
+  };
+
+  const handleRowChange = () => {
+    setTableData([...tableData, { index: tableData.length }]);
+  };
+
+  useEffect(() => {
+    if (displayOnly) {
+      handleDisplayOnly();
+    } else {
+      handleGenerateTable();
+    }
+  }, []);
+
+  return (
+    <>
+      {table.name ? table.name : table.props.label}
+      <Table
+        style={displayOnly ? { margin: '10px 24px 10px 0' } : {}}
+        columns={tableColumnDef}
+        dataSource={tableData}
+        pagination={false}
+      />
+      <Button
+        type="dashed"
+        icon={<PlusOutlined />}
+        block
+        onClick={handleRowChange}
+        style={displayOnly ? { display: 'none' } : {}}
+      >
+        新增行
+      </Button>
+    </>
+  );
+}
+
+export default DIYTable;

+ 10 - 0
src/components/DDComponents/FormulaField/index.js

@@ -0,0 +1,10 @@
+import React, { useEffect, useState } from 'react';
+import { Input } from 'antd';
+
+function FormulaField(props) {
+  const { evalStr } = props;
+
+  return <Input value={eval(evalStr)} />;
+}
+
+export default FormulaField;

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

@@ -2,15 +2,16 @@ import React from 'react';
 import { InputNumber } from 'antd';
 import { InputNumber } from 'antd';
 
 
 function NumberField(props) {
 function NumberField(props) {
-  const { onChange, disabled, unit } = props;
+  const { onChange, disabled, unit, size, width } = props;
 
 
   return (
   return (
     <InputNumber
     <InputNumber
-      style={{ width: '100%' }}
+      size={size}
+      style={{ width: '100%', padding: size === 'small' ? '4px' : '0' }}
       disabled={disabled}
       disabled={disabled}
       formatter={(value) => `${value}${unit || ''}`}
       formatter={(value) => `${value}${unit || ''}`}
       onChange={(e) => {
       onChange={(e) => {
-        onChange?.(e ? String(e) : 0);
+        onChange?.(e ? String(e) : 0, props.id, props.label);
       }}
       }}
     />
     />
   );
   );

+ 14 - 1
src/components/DDComponents/index.js

@@ -14,9 +14,11 @@ import DDDateRangeField from './DDDateRangeField';
 import DDAttachment from './DDAttachment';
 import DDAttachment from './DDAttachment';
 import TextNote from './TextNote';
 import TextNote from './TextNote';
 import CodeField from './CodeFiled';
 import CodeField from './CodeFiled';
+import DIYTable from './DIYTable';
+import FormulaField from './FormulaField';
 
 
 export default function DDComponents(props) {
 export default function DDComponents(props) {
-  const { depId = '', item, onChange } = props;
+  const { depId = '', evalStr = '', item, onChange } = props;
   const { placeholder, options, format, unit, disabled, notUpper } = item.props;
   const { placeholder, options, format, unit, disabled, notUpper } = item.props;
   let component = null;
   let component = null;
   switch (item.componentName) {
   switch (item.componentName) {
@@ -112,6 +114,17 @@ export default function DDComponents(props) {
     case 'ManufacturerField':
     case 'ManufacturerField':
       component = <ManufacturerField onChange={onChange} />;
       component = <ManufacturerField onChange={onChange} />;
       break;
       break;
+    case 'DIYTable':
+      component = (
+        <DIYTable table={item} columns={item.columns} onChange={onChange} />
+      );
+      break;
+    case 'CodeField': //合同编号控件
+      component = <CodeField depId={depId} />;
+      break;
+    case 'FormulaField': //计算控件
+      component = <FormulaField evalStr={evalStr} />;
+      break;
     case 'RelateField': //关联审批单
     case 'RelateField': //关联审批单
       component = '关联审批单控件未渲染!';
       component = '关联审批单控件未渲染!';
       break;
       break;

+ 17 - 0
src/pages/Cad/components/UploadModal.js

@@ -0,0 +1,17 @@
+import { Checkbox, Modal, message, Space, Divider } from 'antd';
+import { useEffect, useMemo, useRef, useState } from 'react';
+import dayjs from 'dayjs';
+
+const UploadModal = ({ open, onCancel, onOk }) => {
+  useEffect(() => {}, [open]);
+  return (
+    <Modal
+      title="上传"
+      open={open}
+      onCancel={onCancel}
+      onOk={() => onOk(values)}
+      destroyOnClose
+    ></Modal>
+  );
+};
+export default UploadModal;

+ 37 - 0
src/pages/Cad/detail.js

@@ -0,0 +1,37 @@
+import { useRef, useEffect } from 'react';
+import PageContent from '@/components/PageContent';
+import { useLocation, useNavigate } from '@umijs/max';
+
+const CadDeTail = () => {
+  const cadRef = useRef();
+  const location = useLocation();
+  const {
+    state: { path },
+  } = location;
+
+  useEffect(() => {
+    console.log(window);
+    const content = document.getElementById('container');
+    window.ZwCloud2D.ZwEditor.ZwInit(content);
+
+    ZwCloud2D.ZwDataProcessor.ZwSetConnectUrl(
+      'http://222.130.26.205:9080',
+      'http://222.130.26.205:5121',
+      'ws://222.130.26.205:5121',
+    );
+    ZwCloud2D.ZwDataProcessor.ZwSetLoadDwg(path);
+    window.ZwCloud2D.ZwDataProcessor.ZwLoad();
+  }, []);
+  return (
+    <PageContent>
+      <div>CAD在线审批</div>
+      <div
+        id="container"
+        style={{ width: '100%', height: '80vh' }}
+        ref={cadRef}
+      />
+    </PageContent>
+  );
+};
+
+export default CadDeTail;

+ 148 - 0
src/pages/Cad/index.js

@@ -0,0 +1,148 @@
+import { useRef, useEffect, useState } from 'react';
+import PageContent from '@/components/PageContent';
+import { queryCadList, queryCreateCad } from '@/services/cad';
+import { useRequest, useNavigate } from '@umijs/max';
+import { Table, Button, message, Space } from 'antd';
+
+const CadDemo = () => {
+  let navigate = useNavigate();
+  const columns = [
+    {
+      title: '名称',
+      dataIndex: 'name',
+      key: 'name',
+      align: 'center',
+      width: 160,
+    },
+    {
+      title: '创建人',
+      dataIndex: 'created_by',
+      key: 'created_by',
+      align: 'center',
+      width: 120,
+    },
+    {
+      title: '创建时间',
+      dataIndex: 'created_on',
+      key: 'created_on',
+      align: 'center',
+      width: 100,
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      align: 'center',
+      width: 100,
+      render: (status) => {
+        let str = '';
+        let color = 'black';
+        switch (status) {
+          case 1:
+            str = '待审核';
+            color = 'blue';
+            break;
+          case 2:
+            str = '审核通过';
+            color = 'red';
+            break;
+          case 3:
+            str = '审核拒绝';
+            color = 'green';
+            break;
+        }
+        return <div style={{ color }}>{str}</div>;
+      },
+    },
+    {
+      title: '操作',
+      align: 'center',
+      width: '10%',
+      render: (record) => (
+        <Space>
+          <a
+            onClick={() =>
+              navigate('/cad/detail', {
+                state: {
+                  path: record.path,
+                },
+              })
+            }
+          >
+            详情
+          </a>
+          <a onClick={() => {}}>提审</a>
+        </Space>
+      ),
+    },
+  ];
+  const [uploading, setUpLoading] = useState(false);
+
+  //请求列表
+  const { data, run, loading } = useRequest(queryCadList);
+
+  //上传
+  const { run: runCreate } = useRequest((data) => queryCreateCad(data), {
+    manual: true,
+    onSuccess: () => {
+      run();
+      message.success('上传成功');
+      setUpLoading(false);
+    },
+  });
+
+  useEffect(() => {
+    ZwCloud2D.ZwDataProcessor.ZwSetConnectUrl(
+      'http://222.130.26.205:9080',
+      'http://222.130.26.205:5121',
+      'ws://222.130.26.205:5121',
+    );
+  }, []);
+
+  function uploadDwg(event) {
+    const selectedFile = event.target.files[0];
+    if (selectedFile) {
+      // ZwCloud2D.ZwEditor.ZwSetLoadingState(true);
+      setUpLoading(true);
+      ZwCloud2D.ZwDataProcessor.uploadDwg(selectedFile).then((res) => {
+        if (res.code == 200) {
+          runCreate({ name: res.data.name, path: res.data.path });
+        }
+        setUpLoading(false);
+      });
+    }
+  }
+  function dwgUpload() {
+    let uploadDwg = document.getElementById('uploadDwg');
+    uploadDwg.click();
+  }
+
+  return (
+    <PageContent>
+      <Button type="primary" onClick={dwgUpload}>
+        上传
+      </Button>
+      <Table
+        loading={loading}
+        columns={columns}
+        dataSource={data?.list}
+        indentSize={70}
+        // pagination={{
+        //   ...pagination,
+        //   showSizeChanger: false,
+        //   onChange: onPageChange,
+        // }}
+      />
+      {/* <div id="container"></div> */}
+      <input
+        style={{ display: 'none' }}
+        id="uploadDwg"
+        type="file"
+        onChange={uploadDwg}
+        accept=".dwg, .dxf"
+      />
+    </PageContent>
+  );
+};
+
+export default CadDemo;

+ 6 - 7
src/pages/Flow/Audit.js

@@ -17,10 +17,8 @@ function Audit(props) {
   } = props;
   } = props;
   const [tabActiveKey, setTabActiveKey] = useState('1');
   const [tabActiveKey, setTabActiveKey] = useState('1');
   const ref = useRef();
   const ref = useRef();
-  const {
-    initialState,
-  } = useModel('@@initialState');
-  const user = initialState?.user || {}
+  const { initialState } = useModel('@@initialState');
+  const user = initialState?.user || {};
   const permission = user?.Permission || {};
   const permission = user?.Permission || {};
 
 
   const curItem = useMemo(() => {
   const curItem = useMemo(() => {
@@ -121,10 +119,10 @@ function Audit(props) {
         },
         },
       ]}
       ]}
     >
     >
-      {tabActiveKey == 1 && (
-        <AuditForm value={formData} onChange={(values) => onChange(values)} />
+      {tabActiveKey === '1' && (
+        <AuditForm value={formData} onChange={onChange} />
       )}
       )}
-      {tabActiveKey == 2 && (
+      {tabActiveKey === '2' && (
         <Flow
         <Flow
           meta={{ type: 'edit', editMode, flowId: curItem.id }}
           meta={{ type: 'edit', editMode, flowId: curItem.id }}
           flowDetail={flowDetail}
           flowDetail={flowDetail}
@@ -134,6 +132,7 @@ function Audit(props) {
     </PageContent>
     </PageContent>
   );
   );
 }
 }
+
 export default connect(({ flow, loading, user, xflow }) => ({
 export default connect(({ flow, loading, user, xflow }) => ({
   roleList: flow.roleList,
   roleList: flow.roleList,
   loading: loading.effects,
   loading: loading.effects,

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

@@ -13,10 +13,8 @@ import { Type } from '../Profile';
 import { queryContractDetail } from '../../services/contract';
 import { queryContractDetail } from '../../services/contract';
 
 
 function OaAuditDetail() {
 function OaAuditDetail() {
-  const {
-    initialState,
-  } = useModel('@@initialState');
-  const user = initialState?.user || {}
+  const { initialState } = useModel('@@initialState');
+  const user = initialState?.user || {};
   const [auditVisible, setAuditVisible] = useState(false);
   const [auditVisible, setAuditVisible] = useState(false);
   const location = useLocation();
   const location = useLocation();
   const {
   const {

+ 170 - 10
src/pages/Flow/OaDetail.js

@@ -12,11 +12,15 @@ import {
   queryLeader,
   queryLeader,
 } from '@/services/boom';
 } from '@/services/boom';
 import { useParams, useRequest, useNavigate } from 'umi';
 import { useParams, useRequest, useNavigate } from 'umi';
+import table from '../Table';
 
 
 const OaDetail = () => {
 const OaDetail = () => {
   const [form] = Form.useForm();
   const [form] = Form.useForm();
+
   const [approvalProcess, setApprovalProcess] = useState([]);
   const [approvalProcess, setApprovalProcess] = useState([]);
   const [auditCheck, setAuditCheck] = useState([]);
   const [auditCheck, setAuditCheck] = useState([]);
+  const [tableData, setTableData] = useState([]);
+
   const { oaId } = useParams();
   const { oaId } = useParams();
   const formValueRef = useRef({
   const formValueRef = useRef({
     form: '',
     form: '',
@@ -87,31 +91,186 @@ const OaDetail = () => {
     run(params);
     run(params);
   };
   };
 
 
-  const submit = () => {
+  const handleTableValChange = (value, id, label) => {
+    let ids = id.split(';');
+    let [rowIndex, colIndex] = ids[0].split(',').map((item) => Number(item));
+    let [columnID, tableID] = ids[1].split('>');
+    let [columnLabel, tableLabel] = label.split('>');
+
+    const cell = {
+      name: columnLabel,
+      id: columnID,
+      type: columnID.split('_')[0],
+      value: [value],
+    };
+    // 组装可能用到的数据
+    const cols = [];
+    cols[colIndex] = cell;
+    const rows = [];
+    rows[rowIndex] = cols;
+    // 如果已经有数据
+    let oldTableData = [];
+    // 这里不知道为什么不能直接读取state(tableData)
+    setTableData((prevState) => {
+      oldTableData = prevState;
+      return prevState;
+    });
+    if (oldTableData && oldTableData.length > 0) {
+      let table = oldTableData.find((item) => item.id === tableID);
+      // 如果某个表格数据存在
+      if (table) {
+        const oldRows = table.value;
+        // 如果某个表格的行数据存在
+        if (oldRows) {
+          let odlCols = oldRows[rowIndex];
+          // 如果某个表格的某个行数据存在
+          if (odlCols) {
+            // 记录可编辑控件
+            table.value[rowIndex][colIndex] = cell;
+            // 不可编辑控件
+            table.value[rowIndex] = addUnEditableColumn(
+              table.value[rowIndex],
+              tableID,
+            );
+            const newTableData = oldTableData.map((item) => {
+              if (item.id === table.id) {
+                return table;
+              }
+              return item;
+            });
+
+            setTableData(newTableData);
+          } else {
+            // 如果某个表格的某个行数据不存在
+            // 写入可编辑控件
+            table.value[rowIndex] = cols;
+            // 写入不可编辑控件的值
+            table.value[rowIndex] = addUnEditableColumn(
+              table.value[rowIndex],
+              tableID,
+            );
+            const newTableData = oldTableData.map((item) => {
+              if (item.id === table.id) {
+                return table;
+              }
+              return item;
+            });
+            setTableData([]);
+            setTableData(newTableData);
+          }
+        } else {
+          // 如果某个表格的行数据不存在
+          // 写入可编辑控件
+          table.value = rows;
+          // 写入不可编辑控件
+          table.value[rowIndex] = addUnEditableColumn(
+            table.value[rowIndex],
+            tableID,
+          );
+          const newTableData = oldTableData.map((item) => {
+            if (item.id === table.id) {
+              return table;
+            }
+            return item;
+          });
+          setTableData(newTableData);
+        }
+      } else {
+        // 如果某个table的数据不存在
+        rows[rowIndex] = addUnEditableColumn(rows[rowIndex], tableID);
+        const newTableData = [
+          {
+            name: tableLabel,
+            id: tableID,
+            type: tableID.split('_')[0],
+            value: rows,
+          },
+        ];
+        setTableData([...oldTableData, ...newTableData]);
+      }
+    } else {
+      // 如果没有数据
+      // 添加不可编辑控件
+      rows[rowIndex] = addUnEditableColumn(rows[rowIndex], tableID);
+      const newTableData = [
+        {
+          name: tableLabel,
+          id: tableID,
+          type: tableID.split('_')[0],
+          value: rows,
+        },
+      ];
+      setTableData(newTableData);
+    }
+  };
+
+  const addUnEditableColumn = (rows, tableID) => {
+    const { columns: originColumns } = data.formData.find(
+      (item) => item.props.id === tableID,
+    );
+    // 检查是否有文字说明控件,有的话需要添加在第几列的index后写入tableData
+    const allTextNote = originColumns.filter((item, index) => {
+      if (item.componentName === 'TextNote') {
+        item.index = index;
+        return true;
+      }
+      return false;
+    });
+    // 对这个表格的每个第 (allTextNote.item 的 index )列写入
+    let textNoteCellList = [];
+    if (allTextNote && allTextNote.length) {
+      textNoteCellList = allTextNote.map((item) => {
+        return {
+          name: item.props.label,
+          id: item.props.id,
+          type: item.componentName,
+          value: [item.props.placeholder],
+          colIndex: item.index,
+        };
+      });
+    }
+    if (textNoteCellList.length) {
+      for (const note of textNoteCellList) {
+        rows[note.colIndex] = note;
+      }
+    }
+    return rows;
+  };
+
+  const submit = async () => {
     form.validateFields().then((values) => {
     form.validateFields().then((values) => {
       const { form: formCur } = formValueRef.current;
       const { form: formCur } = formValueRef.current;
-      let audit_list = [],
-        cc_list = [];
+      let audit_list = [];
+      let cc_list = [];
       approvalProcess?.forEach((item, index) => {
       approvalProcess?.forEach((item, index) => {
-        let arr = item[0].is_cc == 1 ? cc_list : audit_list;
+        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')
+        if (item[0].type === 'role') arr.push(auditCheck[index]);
+        else if (item[0].type === 'leader')
           arr.push(
           arr.push(
             ...leaderData.slice(0, item[0].value).map((leader) => leader.ID),
             ...leaderData.slice(0, item[0].value).map((leader) => leader.ID),
           );
           );
         else arr.push(item.map((cur) => cur.value));
         else arr.push(item.map((cur) => cur.value));
       });
       });
-      let files = [],
-        formData = [];
+      let files = [];
+      let formData = [];
       formCur.forEach((item) => {
       formCur.forEach((item) => {
-        if (item.type == 'DDAttachment') {
+        if (item.type === 'DDAttachment') {
           files = files.concat(item.value);
           files = files.concat(item.value);
         } else {
         } else {
           formData.push(item);
           formData.push(item);
         }
         }
       });
       });
-      console.log(audit_list, cc_list);
+
+      // 根据表格在原来的form中的顺序插入
+      const tableIndex = tableData.map((table) => {
+        return data.formData.findIndex((item) => item.props.id === table.id);
+      });
+
+      // 按保存的顺序把表格再插入进去
+      tableIndex.forEach((item, index) => {
+        formData.splice(item, 0, tableData[index]);
+      });
       createRun({
       createRun({
         flow_id: Number(oaId),
         flow_id: Number(oaId),
         form: JSON.stringify(formData),
         form: JSON.stringify(formData),
@@ -151,6 +310,7 @@ const OaDetail = () => {
             form={form}
             form={form}
             items={data?.formData}
             items={data?.formData}
             onValuesChange={advanceSubmit}
             onValuesChange={advanceSubmit}
+            onTableValChange={handleTableValChange}
           />
           />
         </Col>
         </Col>
         <Col span={12}>
         <Col span={12}>

+ 42 - 11
src/pages/Flow/components/AuditDetailed.js

@@ -1,10 +1,17 @@
 import DDComponents from '@/components/DDComponents';
 import DDComponents from '@/components/DDComponents';
 import React, { useMemo, useState } from 'react';
 import React, { useMemo, useState } from 'react';
 import { Button, Form } from 'antd';
 import { Button, Form } from 'antd';
+import { FormulaType } from '@/components/AuditForm/FormulaModal';
 
 
 const AuditDetailed = (props) => {
 const AuditDetailed = (props) => {
   // const [form] = Form.useForm();
   // const [form] = Form.useForm();
-  const { allValues = [], items, form, onValuesChange } = props;
+  const {
+    allValues = [],
+    items,
+    form,
+    onValuesChange,
+    onTableValChange,
+  } = props;
 
 
   const depId = useMemo(() => {
   const depId = useMemo(() => {
     const id = items.find((item) => item.componentName == 'DepartmentField')
     const id = items.find((item) => item.componentName == 'DepartmentField')
@@ -66,21 +73,45 @@ const AuditDetailed = (props) => {
       }
       }
     }
     }
 
 
+    const renderComponents = () => {
+      let content = '';
+      if (item.componentName === 'CodeField') {
+        content = <DDComponents item={item} depId={depId} />;
+      } else if (item.componentName === 'FormulaField') {
+        const strList = item.props?.formula?.map((formu) => {
+          if (formu.type == FormulaType.Filed) {
+            const numItem = allValues?.find((item) => item.id == formu.id);
+            return numItem?.value[0] || 0;
+          } else {
+            return formu.label;
+          }
+        });
+        console.log('-------44444-------------', item, strList);
+        const evalStr = strList?.join('');
+        content = <DDComponents item={item} evalStr={evalStr} />;
+      } else {
+        content = <DDComponents item={item} />;
+      }
+      return content;
+    };
+
     // const component = DDComponents({ item });
     // const component = DDComponents({ item });
     // if (!component) return null;
     // if (!component) return null;
     return (
     return (
-      <Form.Item
-        key={id}
-        name={id}
-        label={formLabel}
-        rules={[{ required: required }]}
-      >
-        {item.componentName == 'CodeField' ? (
-          <DDComponents item={item} depId={depId} />
+      <>
+        {item?.isTable === undefined ? (
+          <Form.Item
+            key={id}
+            name={id}
+            label={formLabel}
+            rules={[{ required: required }]}
+          >
+            {renderComponents()}
+          </Form.Item>
         ) : (
         ) : (
-          <DDComponents item={item} />
+          <DDComponents item={item} onChange={onTableValChange} />
         )}
         )}
-      </Form.Item>
+      </>
     );
     );
   };
   };
 
 

+ 25 - 11
src/pages/Flow/components/FormAndFilesNode.js

@@ -1,16 +1,17 @@
 import { Card, Col, Row, Empty } from 'antd';
 import { Card, Col, Row, Empty } from 'antd';
-import { Form } from 'antd';
+import { Form, Table } from 'antd';
 import { useMemo, useState } from 'react';
 import { useMemo, useState } from 'react';
 import { useModel } from 'umi';
 import { useModel } from 'umi';
 import AttachmentTable from '@/components/AttachmentTable';
 import AttachmentTable from '@/components/AttachmentTable';
 import InnerContactField from '@/components/DDComponents/InnerContactField';
 import InnerContactField from '@/components/DDComponents/InnerContactField';
 import DepartmentField from '@/components/DDComponents/DepartmentField';
 import DepartmentField from '@/components/DDComponents/DepartmentField';
 import ProjectField from '@/components/DDComponents/ProjectField';
 import ProjectField from '@/components/DDComponents/ProjectField';
+import DIYTable from '../../../components/DDComponents/DIYTable';
 
 
 const FormAndFilesNode = (props) => {
 const FormAndFilesNode = (props) => {
   const { formData, fileList } = props;
   const { formData, fileList } = props;
 
 
-  const renderFormItem = (type, value) => {
+  const renderFormItem = (type, value, item) => {
     switch (type) {
     switch (type) {
       case 'InnerContactField':
       case 'InnerContactField':
         return <InnerContactField value={value} disabled={true} />;
         return <InnerContactField value={value} disabled={true} />;
@@ -40,20 +41,33 @@ const FormAndFilesNode = (props) => {
     if (!data) return <Empty description="没有表单信息" />;
     if (!data) return <Empty description="没有表单信息" />;
     try {
     try {
       const formData = JSON.parse(data);
       const formData = JSON.parse(data);
-      if (formData.length == 0) return <Empty description="没有表单信息" />;
+      if (formData.length === 0) return <Empty description="没有表单信息" />;
       return (
       return (
         <>
         <>
           {formData.map((item, idx) => {
           {formData.map((item, idx) => {
             const value = item.value.join(',');
             const value = item.value.join(',');
             return (
             return (
-              <Form.Item
-                key={`FormAndFilesNode_${idx}`}
-                labelCol={{ span: 4 }}
-                wrapperCol={{ span: 14 }}
-                label={item.name}
-              >
-                {renderFormItem(item.type, value)}
-              </Form.Item>
+              <>
+                {item.type !== 'DIYTable' ? (
+                  <Form.Item
+                    key={`FormAndFilesNode_${idx}`}
+                    labelCol={{ span: 4 }}
+                    wrapperCol={{ span: 14 }}
+                    label={item.name}
+                    labelAlign="left"
+                  >
+                    {renderFormItem(item.type, value, item)}
+                  </Form.Item>
+                ) : (
+                  <div style={{ marginBottom: '24px' }}>
+                    <DIYTable
+                      table={item}
+                      columns={item.value}
+                      displayOnly={true}
+                    ></DIYTable>
+                  </div>
+                )}
+              </>
             );
             );
           })}
           })}
         </>
         </>

+ 10 - 0
src/pages/Home/index.js

@@ -85,6 +85,7 @@ function HomePage(props) {
       },
       },
       Icon: require('@/assets/UnityMenu/system.png'),
       Icon: require('@/assets/UnityMenu/system.png'),
     },
     },
+
     {
     {
       id: 9,
       id: 9,
       name: '个人中心',
       name: '个人中心',
@@ -94,6 +95,15 @@ function HomePage(props) {
       },
       },
       Icon: require('@/assets/UnityMenu/userCenter.png'),
       Icon: require('@/assets/UnityMenu/userCenter.png'),
     },
     },
+    // {
+    //   id: 10,
+    //   name: 'cad管理',
+    //   active: true,
+    //   click: () => {
+    //     navigate('/cad');
+    //   },
+    //   Icon: require('@/assets/UnityMenu/cad.png'),
+    // },
   ];
   ];
   return (
   return (
     <div className={menuStyle.background}>
     <div className={menuStyle.background}>

+ 10 - 0
src/services/cad.js

@@ -0,0 +1,10 @@
+import { request } from 'umi';
+export const queryCadList = async () => {
+  return await request('/api/contract/v1/cad');
+};
+export async function queryCreateCad(data) {
+  return request(`/api/contract/v1/cad`, {
+    method: 'POST',
+    data,
+  });
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно