浏览代码

Merge branch 'develop' of xujunjie/BomWeb into master

xujunjie 2 年之前
父节点
当前提交
9e3e683a89

+ 22 - 22
config/plugin.config.js

@@ -15,30 +15,30 @@ export default config => {
     .loader('file-loader')
     .end();
   // pro 和 开发环境再添加这个插件
-  if (process.env.APP_TYPE === 'site' || process.env.NODE_ENV !== 'production') {
-    // 将所有 less 合并为一个供 themePlugin使用
-    const outFile = path.join(__dirname, '../.temp/ant-design-pro.less');
-    const stylesDir = path.join(__dirname, '../src/');
+  // if (process.env.APP_TYPE === 'site' || process.env.NODE_ENV !== 'production') {
+  //   // 将所有 less 合并为一个供 themePlugin使用
+  //   const outFile = path.join(__dirname, '../.temp/ant-design-pro.less');
+  //   const stylesDir = path.join(__dirname, '../src/');
 
-    config.plugin('merge-less').use(MergeLessPlugin, [
-      {
-        stylesDir,
-        outFile,
-      },
-    ]);
+  //   config.plugin('merge-less').use(MergeLessPlugin, [
+  //     {
+  //       stylesDir,
+  //       outFile,
+  //     },
+  //   ]);
 
-    config.plugin('ant-design-theme').use(AntDesignThemePlugin, [
-      {
-        antDir: path.join(__dirname, '../node_modules/antd'),
-        stylesDir,
-        varFile: path.join(__dirname, '../node_modules/antd/lib/style/themes/default.less'),
-        mainLessFile: outFile, //     themeVariables: ['@primary-color'],
-        indexFileName: 'index.html',
-        generateOne: true,
-        lessUrl: 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js',
-      },
-    ]);
-  }
+  //   config.plugin('ant-design-theme').use(AntDesignThemePlugin, [
+  //     {
+  //       antDir: path.join(__dirname, '../node_modules/antd'),
+  //       stylesDir,
+  //       varFile: path.join(__dirname, '../node_modules/antd/lib/style/themes/default.less'),
+  //       mainLessFile: outFile, //     themeVariables: ['@primary-color'],
+  //       indexFileName: 'index.html',
+  //       generateOne: true,
+  //       lessUrl: 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js',
+  //     },
+  //   ]);
+  // }
 
   if (process.env.APP_TYPE !== 'site' || process.env.NODE_ENV !== 'development') {
     config.merge({

+ 11 - 3
config/router.config.js

@@ -9,13 +9,12 @@ export default [
       },
       {
         path: '/bom',
-        redirect: '/home'
+        redirect: '/home',
       },
       {
         path: '/home',
         component: './Index',
         routes: [
-         
           {
             path: '/home',
             component: './List/List',
@@ -40,9 +39,18 @@ export default [
             path: '/home/flow-list',
             component: './Flow/List',
           },
+
+          {
+            path: '/home/auth',
+            component: './Auth/Auth',
+          },
         ],
       },
-   
+      {
+        path: '/mobile/detail/:templateId/:versionId',
+        component: './Detail/Mobile',
+      },
+
       // {
       //   path: '/dd-login/:dingUserId',
       //   component: './DDLogin/index',

文件差异内容过多而无法显示
+ 5 - 0
public/Luckysheet/luckysheet.umd.js


文件差异内容过多而无法显示
+ 0 - 0
public/Luckysheet/luckysheet.umd.js.map


+ 7 - 1
src/components/AttachmentTable/index.js

@@ -76,7 +76,13 @@ function AttachmentTable(props) {
   }, [excelFileList]);
   return (
     <>
-      <Table rowKey="id" loading={loading} columns={columns} dataSource={excelFileData} />
+      <Table
+        title={() => '附件列表'}
+        rowKey="id"
+        loading={loading}
+        columns={columns}
+        dataSource={excelFileData}
+      />
       <FileViewerModal
         data={exportData}
         visible={excelFileVisible}

+ 52 - 0
src/models/authList.js

@@ -0,0 +1,52 @@
+import { queryAuthList } from '@/services/bomAuth';
+export default {
+  namespace: 'authList',
+  state: {
+    authList: [],
+    checkedList: { list: [], pagination: {} },
+  },
+  effects: {
+    *queryAuthList({ payload }, { call, put }) {
+      const responce = yield call(queryAuthList, payload);
+      if (responce) {
+        let data = responce.data;
+        let ret = [];
+        data.forEach(e => {
+          let item = ret.find(item => item.key == `${e.template_id}_${e.project_id}`);
+          if (!item) {
+            item = {
+              key: `${e.template_id}_${e.project_id}`,
+              name: e.name,
+              project_name: e.ding_schema,
+              nodes: [],
+            };
+            ret.push(item);
+          }
+          item.nodes.push({
+            template_id: e.template_id,
+            project_id: e.project_id,
+            version_name: e.version_name,
+            node_name: e.TemplateNodeInfo?.label,
+            author: e.AuthorInfo?.CName,
+            classify_id: e.classify_id,
+            version_id: e.version_id,
+            id: e.id,
+          });
+        });
+        yield put({
+          type: 'save',
+          payload: { authList: ret },
+        });
+      }
+    },
+  },
+
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+        ...action.payload,
+      };
+    },
+  },
+};

+ 106 - 0
src/pages/Auth/Auth.js

@@ -0,0 +1,106 @@
+import React, { useEffect } from 'react';
+import { Table, Collapse } from 'antd';
+import { connect } from 'dva';
+import router from 'umi/router';
+
+const { Panel } = Collapse;
+
+function Auth(props) {
+  const {
+    dispatch,
+    authList,
+    checkedList,
+    checkedPagination,
+    typeOptions,
+    currentUser,
+    loading,
+  } = props;
+
+  //监测当前用户,有值时调用列表接口
+  useEffect(() => {
+    if (!currentUser.ID) return;
+    dispatch({
+      type: 'authList/queryAuthList',
+      payload: { user_id: currentUser.ID },
+    });
+    dispatch({
+      type: 'auth/queryCheckedList',
+      payload: { user_id: currentUser.ID, params: { page_size: 99999 } },
+    });
+  }, [currentUser]);
+
+  useEffect(() => {
+    //分类列表
+    dispatch({ type: 'auth/queryClassify' });
+  }, []);
+
+  const columns = [
+    { title: '流程名称', dataIndex: 'name' },
+    { title: '所属项目', dataIndex: 'project_name' },
+  ];
+
+  const flowColumns = [
+    { title: '名称', dataIndex: 'version_name' },
+    { title: '节点', dataIndex: 'node_name' },
+    { title: '创建人', dataIndex: 'author' },
+    {
+      title: '分类',
+      render: (_, record) => typeOptions.find(cur => cur.id == record.classify_id)?.name,
+    },
+    { title: '操作', render: (_, record) => <a onClick={() => loadNode(record)}>加载</a> },
+  ];
+
+  const loadNode = item => {
+    //调用接口获取version信息
+    dispatch({
+      type: 'auth/queryVersionByNode',
+      callback: versionList => {
+        let version = versionList.find(v => v.id == item.id) || {};
+        localStorage.excelItem = JSON.stringify(version);
+        router.push(`/home/detail/${item.project_id}/${item.template_id}`);
+      },
+    });
+  };
+
+  const renderUnauth = data => (
+    <Table columns={flowColumns} dataSource={data} pagination={false} rowKey="id" />
+  );
+
+  const renderAuth = data => (
+    <Table columns={flowColumns} dataSource={data} pagination={false} rowKey="id" />
+  );
+
+  return (
+    <Collapse defaultActiveKey={['0']}>
+      <Panel header="未审批" key="0">
+        <Table
+          columns={columns}
+          dataSource={authList}
+          expandable={{ expandedRowRender: record => renderUnauth(record.nodes) }}
+          pagination={false}
+          rowKey="key"
+          loading={loading.models.auth}
+        />
+      </Panel>
+      <Panel header="已审批" key="1">
+        <Table
+          columns={columns}
+          dataSource={checkedList}
+          expandable={{ expandedRowRender: record => renderAuth(record.nodes) }}
+          pagination={false}
+          rowKey="key"
+          loading={loading.models.auth}
+        />
+      </Panel>
+    </Collapse>
+  );
+}
+
+export default connect(({ auth, authList, loading, user }) => ({
+  authList: authList.authList,
+  checkedList: auth.checkedList.list,
+  checkedPagination: auth.checkedList.pagination,
+  typeOptions: auth.typeOptions,
+  currentUser: user.currentUser,
+  loading,
+}))(Auth);

+ 71 - 0
src/pages/Auth/models/auth.js

@@ -0,0 +1,71 @@
+import { queryCheckedList, queryVersionByNode } from '@/services/bomAuth';
+import { queryClassify } from '@/services/boom';
+export default {
+  namespace: 'auth',
+  state: {
+    checkedList: { list: [], pagination: {} },
+  },
+  effects: {
+    *queryCheckedList({ payload }, { call, put }) {
+      const responce = yield call(queryCheckedList, payload);
+      if (responce) {
+        let data = responce.data.list;
+        let ret = [];
+        data.forEach(e => {
+          let item = ret.find(item => item.key == `${e.template_id}_${e.project_id}`);
+          if (!item) {
+            item = {
+              key: `${e.template_id}_${e.project_id}`,
+              name: e.name,
+              project_name: e.ding_schema,
+              nodes: [],
+            };
+            ret.push(item);
+          }
+          item.nodes.push({
+            template_id: e.template_id,
+            project_id: e.project_id,
+            version_name: e.version_name,
+            node_name: e.TemplateNodeInfo?.label,
+            author: e.AuthorInfo?.CName,
+            classify_id: e.classify_id,
+            id: e.id,
+          });
+        });
+        yield put({
+          type: 'save',
+          payload: { checkedList: { list: ret, pagination: responce.data.pagination } },
+        });
+      }
+    },
+
+    *queryClassify({ payload, callback }, { call, put }) {
+      const data = yield call(queryClassify, payload);
+      if (data) {
+        yield put({
+          type: 'save',
+          payload: {
+            typeOptions: data?.map(item => {
+              return { ...item, label: item.name, value: item.id };
+            }),
+          },
+        });
+      }
+    },
+
+    *queryVersionByNode({ payload, callback }, { call, put }) {
+      const data = yield call(queryVersionByNode, payload);
+      if (data) {
+        callback && callback(data.data.excel_version_tree);
+      }
+    },
+  },
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+        ...action.payload,
+      };
+    },
+  },
+};

+ 15 - 4
src/pages/Detail/AuditModal.js

@@ -1,12 +1,11 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import { Form } from '@ant-design/compatible';
 import '@ant-design/compatible/assets/index.css';
 import { Modal, Input } from 'antd';
 
-
 // 审批意见
 function AuditModal(props) {
-  const { visible, onClose, onOk, form, loading } = props;
+  const { visible, onClose, onOk, form, sheetRef, loading } = props;
 
   const handleOk = () => {
     form.validateFields((err, fieldsValue) => {
@@ -14,6 +13,18 @@ function AuditModal(props) {
       onOk(fieldsValue);
     });
   };
+  useEffect(() => {
+    if (visible) {
+      const comment = sheetRef.current.getComment();
+      console.log(comment);
+      let str = '';
+      comment.forEach(item => {
+        let col = String.fromCharCode(item.c + 65);
+        str += `单元格${col}${item.r}:${item.value}\n`;
+      });
+      form.setFieldsValue({ audit_comment: str });
+    }
+  }, [visible]);
 
   return (
     <Modal
@@ -31,4 +42,4 @@ function AuditModal(props) {
   );
 }
 
-export default Form.create()(AuditModal)
+export default Form.create()(AuditModal);

+ 5 - 1
src/pages/Detail/FlowModal.js

@@ -401,7 +401,11 @@ function FlowModal(props) {
         destroyOnClose
         title="流程图"
         visible={visible}
-        onCancel={onClose}
+        onCancel={() => {
+          setSelectType(SELECT_TYPE.NAME);
+          setInputValue('');
+          onClose();
+        }}
         footer={false}
         width="98%"
         // bodyStyle={{ maxHeight: '660px', overflow: 'auto' }}

+ 13 - 34
src/pages/Detail/FormAndFilesNode.js

@@ -12,51 +12,30 @@ const { Panel } = Collapse;
 const FormAndFilesNode = props => {
   const { formData, excelFileList, comment, version, loading } = props;
 
-  const handleSubmitCell = (value, callback) => {
-    if (!value) return;
-    dispatch({
-      type: 'detail/addComment',
-      payload: {
-        ...cellPosition.current,
-        comment: value,
-      },
-      callback,
-    });
-  };
-
   const FormContent = useMemo(() => {
     return renderFrom(formData);
   }, [formData]);
 
   return (
-    <Collapse style={{ marginTop: 20 }}>
-      <Panel header="附件" key="2">
-        <AttachmentTable version={version} canDelete={version.last_version == 0} />
-      </Panel>
-      {FormContent && (
-        <Panel header="表单信息" key="1">
-          {FormContent}
-        </Panel>
-      )}
-
-      <Panel header="评论" key="3">
-        <CommentContent
-          title="单元格沟通记录"
-          comment={comment}
-          onSubmit={handleSubmitCell}
-          loading={loading.effects['detail/queryComment'] || loading.effects['detail/addComment']}
-        />
-      </Panel>
-    </Collapse>
+    <>
+      <Card title="审批信息">
+        <Row gutter={20}>
+          <Col span={12}>{FormContent}</Col>
+          <Col span={12}>
+            <AttachmentTable version={version} canDelete={version.last_version == 0} />
+          </Col>
+        </Row>
+      </Card>
+    </>
   );
 };
 
 const renderFrom = data => {
-  if (!data) return null;
+  if (!data) return <Empty description="没有表单信息" />;
   try {
     const ding_schema = JSON.parse(data)[0];
     const formData = JSON.parse(ding_schema)?.formComponentValues;
-    if (formData.length == 0) return null;
+    if (formData.length == 0) return <Empty description="没有表单信息" />;
     return (
       <>
         {formData.map((item, idx) => {
@@ -85,7 +64,7 @@ const renderFrom = data => {
       </>
     );
   } catch {
-    return null;
+    return <Empty description="没有表单信息" />;
   }
 };
 export default connect(({ detail, loading }) => ({

+ 71 - 36
src/pages/Detail/Index.js

@@ -16,7 +16,7 @@ import TimeNode from './TimeNode';
 import FilesModal from './FilesModal';
 import VersionModal from './VersionModal';
 import CommitAuditModal from './CommitAuditModal';
-// import CommentContent from '@/components/CommentContent';
+import CommentContent from '@/components/CommentContent';
 import MergeModal from './MergeModal';
 import { GetTokenFromUrl, getToken } from '@/utils/utils';
 import {
@@ -50,6 +50,7 @@ function Detail(props) {
     typeOptions,
     classifyList,
     excelFileList,
+    comment,
   } = props;
   const [versionTreeVisible, setVersionTreeVisible] = useState(false);
   const [commentVisible, setCommentVisible] = useState(false);
@@ -80,6 +81,7 @@ function Detail(props) {
     edit: false,
     compare: false,
   });
+  const cellPosition = useRef({});
 
   useEffect(() => {
     if (!version.attachment_id) return;
@@ -181,6 +183,9 @@ function Detail(props) {
         cid: cell.cid,
         sheet_index: String(s.seq || 0),
       };
+      cellPosition.current = {
+        ...payload,
+      };
       dispatch({
         type: 'detail/queryComment',
         payload,
@@ -216,9 +221,9 @@ function Detail(props) {
       },
     });
   };
-
-  const onUpdate = () => {
-    if (flow.active != 0) return;
+  // 更新表单,flag为true时不判断是否属于审批,强制更新
+  const onUpdate = flag => {
+    if (!flag && flow.active != 0) return;
     let currentData = sheetRef.current.getSheetJson().data;
     let sheets = JSON.parse(JSON.stringify(currentData));
     sheets.forEach(item => {
@@ -263,6 +268,11 @@ function Detail(props) {
             id: templateId,
           },
         });
+        //更新未审批列表
+        dispatch({
+          type: 'authList/queryAuthList',
+          payloda: { user_id: currentUser.ID },
+        });
         localStorage.excelId = newVersion.id;
         setVersion({
           ...version,
@@ -387,7 +397,17 @@ function Detail(props) {
       }
     } catch (error) {}
   };
-
+  const handleSubmitCell = (value, callback) => {
+    if (!value) return;
+    dispatch({
+      type: 'detail/addComment',
+      payload: {
+        ...cellPosition.current,
+        comment: value,
+      },
+      callback,
+    });
+  };
   useEffect(() => {
     dispatch({
       type: 'detail/queryProjectRecord',
@@ -521,33 +541,51 @@ function Detail(props) {
         projectId={projectId}
         setAuditVisible={setAuditVisible}
       ></TimeNode>
-
-      {/* 判断是否为比对模式 */}
-      {compareList.length == 2 ? (
-        <>
-          <Alert
-            message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
-            type="info"
-          />
-          <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
-        </>
-      ) : (
-        <div className={styles.sheetBox}>
-          {version.id && (
-            <LuckySheet
-              className={styles.sheet}
-              ref={sheetRef}
-              onClickCell={onClickCell}
-              version={version}
-              templateId={templateId}
-              getUser={getUser}
-              onUpdate={onUpdate}
-              onDelSheet={onDelSheet}
+      <div
+        className={styles.content}
+        style={{
+          // 合同清单先显示附件再显示清单详情
+          flexDirection: version?.TemplateNodeInfo?.flow_id == 9 ? 'column-reverse' : 'column',
+        }}
+      >
+        {/* 判断是否为比对模式 */}
+        {compareList.length == 2 ? (
+          <>
+            <Alert
+              message={`比对结果:${updateCount.diff}项差异。${updateCount.add}项新增`}
+              type="info"
             />
-          )}
-        </div>
-      )}
-
+            <div className={styles.sheetBox}>{compareList.map(renderSheetDom)}</div>
+          </>
+        ) : (
+          <div className={styles.sheetBox}>
+            {version.id && (
+              <LuckySheet
+                className={styles.sheet}
+                ref={sheetRef}
+                onClickCell={onClickCell}
+                version={version}
+                templateId={templateId}
+                getUser={getUser}
+                onUpdate={onUpdate}
+                onDelSheet={onDelSheet}
+              />
+            )}
+          </div>
+        )}
+
+        <FormAndFilesNode
+          formData={version?.ding_schema}
+          excelFileList={excelFileList}
+          version={version}
+        />
+      </div>
+      <CommentContent
+        title="单元格沟通记录"
+        comment={comment}
+        onSubmit={handleSubmitCell}
+        loading={loading.effects['detail/queryComment'] || loading.effects['detail/addComment']}
+      />
       <HistoryDrawer
         versionTree={versionTree}
         version={version}
@@ -556,11 +594,6 @@ function Detail(props) {
         onClose={() => setVersionTreeVisible(false)}
       />
 
-      <FormAndFilesNode
-        formData={version?.ding_schema}
-        excelFileList={excelFileList}
-        version={version}
-      />
       <RightDrawer
         version={version}
         visible={commentVisible}
@@ -596,6 +629,7 @@ function Detail(props) {
       <AuditModal
         loading={getLoading()}
         visible={auditVisible}
+        sheetRef={sheetRef}
         onClose={() => setAuditVisible(false)}
         onOk={onAudit}
       />
@@ -630,5 +664,6 @@ export default connect(({ detail, user, xflow, loading }) => ({
   typeOptions: detail.typeOptions,
   classifyList: detail.classifyList,
   excelFileList: detail.excelFileList,
+  comment: detail.comment,
   loading,
 }))(Detail);

+ 18 - 6
src/pages/Detail/Index.less

@@ -5,6 +5,7 @@
   font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif;
   vertical-align: middle;
 }
+.mobileSheetBox,
 .sheetBox {
   display: flex;
   .sheetItem {
@@ -22,6 +23,11 @@
     border: none;
   }
 }
+.mobileSheetBox {
+  iframe {
+    height: 100vh;
+  }
+}
 .top {
   display: flex;
   justify-content: space-between;
@@ -47,13 +53,19 @@
 .historyList {
   padding: 0 10px;
 }
-.curTitle  {
+.curTitle {
   margin-left: 20px;
- span {
-  color: #1890FF;
-  margin-right: 10px;
- }
+  span {
+    color: #1890ff;
+    margin-right: 10px;
+  }
 }
-.topF{
+.topF {
   margin: 20px;
 }
+.content {
+  display: flex;
+  flex-direction: column;
+  // justify-content: center;
+  // align-items: center;
+}

+ 70 - 3
src/pages/Detail/LuckySheet.js

@@ -2,7 +2,7 @@ import React from 'react';
 import { message } from 'antd';
 import exportExcel, { getExcelBolob } from '@/utils/exportExcl';
 import LuckyExcel from 'luckyexcel';
-import { getToken } from '@/utils/utils';
+import { getToken, GetTokenFromUrl } from '@/utils/utils';
 
 const hintText = '禁止编辑!请先点击编辑按钮。';
 const DIFF_COLOR = '#ff0000';
@@ -74,7 +74,7 @@ class LuckySheet extends React.Component {
       }, 300);
       return;
     }
-    let token = getToken();
+    let token = GetTokenFromUrl() || getToken();
     let option = {
       lang: 'zh',
       showinfobar: false,
@@ -105,6 +105,14 @@ class LuckySheet extends React.Component {
             }, 3000);
           }
         },
+        // 修改批注后保存sheet
+        commentUpdateAfter() {
+          clearTimeout(_this.updateTimer);
+          _this.updateTimer = setTimeout(() => {
+            onUpdate.bind(_this);
+            onUpdate(true);
+          }, 3000);
+        },
         sheetActivate: sheet => {
           console.log(sheet);
           setTimeout(() => {
@@ -137,7 +145,8 @@ class LuckySheet extends React.Component {
         updateUrl: wsUrl + `api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
         // updateUrl: `ws://47.96.12.136:8896/api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
         // updateUrl: `ws://120.55.44.4:8896/api/v1/ws?id=${version.id}&sid=${templateId}&JWT-TOKEN=${token}`,
-        authorityUrl: `/api/v1/purchase/bom/user/excel/col?depId=${localStorage.depId}&JWT-TOKEN=${token}`,
+        authorityUrl: `/api/v1/purchase/bom/user/excel/col?depId=${localStorage.depId ||
+          0}&JWT-TOKEN=${token}`,
         getUser,
         // workbookCreateBefore(luckysheet) {
         //   console.log('===============================', luckysheet);
@@ -151,21 +160,59 @@ class LuckySheet extends React.Component {
         // },
       };
       console.log(version);
+
+      const unableEdit = option => {
+        option.showtoolbar = false;
+        option.enableAddRow = false;
+        option.sheetFormulaBar = false;
+        option.enableAddBackTop = false;
+        option.showsheetbarConfig = {
+          add: false,
+          sheet: false,
+        };
+        option.cellRightClickConfig = {
+          copy: false, // 复制
+          copyAs: false, // 复制为
+          paste: false, // 粘贴
+          insertRow: false, // 插入行
+          insertColumn: false, // 插入列
+          deleteRow: false, // 删除选中行
+          deleteColumn: false, // 删除选中列
+          deleteCell: false, // 删除单元格
+          hideRow: false, // 隐藏选中行和显示选中行
+          hideColumn: false, // 隐藏选中列和显示选中列
+          rowHeight: false, // 行高
+          columnWidth: false, // 列宽
+          clear: false, // 清除内容
+          matrix: false, // 矩阵操作选区
+          sort: false, // 排序选区
+          filter: false, // 筛选选区
+          chart: false, // 图表生成
+          image: false, // 插入图片
+          link: false, // 插入链接
+          data: false, // 数据验证
+          cellFormat: false, // 设置单元格格式
+        };
+      };
+
       if (version.flow_id) {
         option.authority = {
           sheet: true,
           hintText: '当前处于审批节点,禁止编辑!',
         };
+        unableEdit(option);
       } else if (version.last_version) {
         option.authority = {
           sheet: true,
           hintText: '该清单已设置为最终版本,禁止编辑!',
         };
+        unableEdit(option);
       } else if (version.audit_status != 0 || version.status == 1) {
         option.authority = {
           sheet: true,
           hintText: '当前清单不可编辑!',
         };
+        unableEdit(option);
       }
     } else if (data && data.length > 0) {
       option.data = JSON.parse(JSON.stringify(data));
@@ -240,6 +287,7 @@ class LuckySheet extends React.Component {
         } else {
           allCell[cell.v.cid] = cell;
         }
+        if (cell.v.tb) cell.v.tb = Number(cell.v.tb);
         // 清除比对样式
         if (cell.v.bg == DIFF_COLOR || cell.v.bg == ADD_COLOR) {
           delete cell.v.bg;
@@ -540,6 +588,25 @@ class LuckySheet extends React.Component {
     let currentData = this.getExcelData(checkValue);
     exportExcel(currentData, '下载');
   }
+  // 获取批注
+  getComment() {
+    let sheets = this.luckysheet.toJson().data;
+    let comment = [];
+    sheets.forEach(sheet => {
+      sheet.celldata.forEach(cell => {
+        // 判断是否含有批注
+        if (cell?.v?.ps?.value) {
+          comment.push({
+            sheet: sheet.name,
+            r: cell.r,
+            c: cell.c,
+            value: cell.v.ps.value || '',
+          });
+        }
+      });
+    });
+    return comment;
+  }
 
   render() {
     return (

+ 20 - 0
src/pages/Detail/Mobile.js

@@ -0,0 +1,20 @@
+import React, { useEffect } from 'react';
+import styles from './Index.less';
+import LuckySheet from './LuckySheet';
+
+function Mobile(props) {
+  const {
+    match: { params },
+  } = props;
+
+  const templateId = parseInt(params.templateId);
+  const version = { id: parseInt(params.versionId), flow_id: true };
+
+  return (
+    <div className={styles.mobileSheetBox}>
+      <LuckySheet className={styles.sheet} version={version} templateId={templateId} />
+    </div>
+  );
+}
+
+export default Mobile;

+ 14 - 1
src/pages/Detail/TimeNode.js

@@ -4,6 +4,7 @@ import '@ant-design/compatible/assets/index.css';
 import { connect } from 'dva';
 import { Steps, Button, Modal } from 'antd';
 import styles from './Index.less';
+import { getCurrentUser } from '@/utils/authority';
 
 const { Step } = Steps;
 // 时间节点
@@ -19,6 +20,8 @@ function TimeNode(props) {
     setAuditVisible,
     projectId,
     dispatch,
+
+    currentUser,
   } = props;
   const { current, list, active } = flow;
 
@@ -101,6 +104,13 @@ function TimeNode(props) {
                 audit_series: version.audit_series,
               },
             });
+
+            //更新未审核列表
+            dispatch({
+              type: 'authList/queryAuthList',
+              payload: { user_id: currentUser.ID },
+            });
+
             if (flow.current == flow.list.FlowNodes.length - 1) {
               // 最后一个审核节点通过后  需要更新version id 不更不更,留在原地
               // localStorage.excelId = newVersion.id;
@@ -154,4 +164,7 @@ function TimeNode(props) {
   return null;
 }
 
-export default connect(({ detail }) => ({ versionList: detail.versionList }))(TimeNode);
+export default connect(({ user, detail }) => ({
+  currentUser: user.currentUser,
+  versionList: detail.versionList,
+}))(TimeNode);

+ 1 - 1
src/pages/Flow/FlowDetail.json

@@ -361,7 +361,7 @@
       "y": 6,
       "zIndex": 0,
       "muti_version": 1,
-      "flow_id": 17,
+      "flow_id": 8,
       "node_type": 1,
       "count": 0,
       "role_list": ""

+ 27 - 4
src/pages/Index.js

@@ -1,15 +1,17 @@
 import React, { useEffect } from 'react';
-import { Layout, Menu } from 'antd';
+import { Badge, Layout, Menu } from 'antd';
 import { connect } from 'dva';
 import RightContent from './RightContent';
 import Link from 'umi/link';
+import styles from './Index.less';
 
 const { Header, Content, Footer } = Layout;
 const { SubMenu } = Menu;
+let timer;
 
 // 布局
 function LayoutDetail(props) {
-  const { currentUser, permission } = props;
+  const { currentUser, permission, dispatch, authList } = props;
   const isAdmin = currentUser.UserName == 'admin';
   var logoStyle = {
     color: 'white',
@@ -25,7 +27,20 @@ function LayoutDetail(props) {
       type: 'user/fetchCurrent',
     });
   }, []);
- 
+
+  useEffect(() => {
+    if (!currentUser.ID) return;
+    clearInterval(timer);
+    timer = setInterval(() => {
+      dispatch({
+        type: 'authList/queryAuthList',
+        payload: { user_id: currentUser.ID },
+      });
+    }, 10000);
+
+    return () => clearInterval(timer);
+  }, [currentUser.ID]);
+
   return (
     <Layout>
       <Header>
@@ -44,6 +59,13 @@ function LayoutDetail(props) {
               <Menu.Item key="/home/flow-list">
                 <Link to="/home/flow-list">流程管理</Link>
               </Menu.Item>
+              <Menu.Item key="/home/auth">
+                <Link to="/home/auth">
+                  <Badge count={authList.length} className={styles.badge}>
+                    审核列表
+                  </Badge>
+                </Link>
+              </Menu.Item>
             </Menu>
           </div>
           <RightContent />
@@ -56,7 +78,8 @@ function LayoutDetail(props) {
     </Layout>
   );
 }
-export default connect(({ user }) => ({
+export default connect(({ user, authList }) => ({
   currentUser: user.currentUser,
   permission: user.currentUser.Permission,
+  authList: authList.authList,
 }))(LayoutDetail);

+ 3 - 0
src/pages/Index.less

@@ -0,0 +1,3 @@
+.badge {
+  color: inherit;
+}

+ 1 - 1
src/pages/List/models/list.js

@@ -35,7 +35,7 @@ export default {
         }
         temp[item.template_id].children.push(item);
       });
-      data.list = Object.values(temp);
+      data.list = Object.values(temp).reverse();
       yield put({
         type: 'save',
         payload: { excel: data },

+ 19 - 0
src/services/bomAuth.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request';
+import { stringify } from 'qs';
+
+//获取未审核列表
+//params: user_id
+export async function queryAuthList({ user_id }) {
+  return request(`/purchase/bom/get-audit-list/${user_id}`);
+}
+
+//获取已审核列表
+//params: user_id, page_size, current_page
+export async function queryCheckedList({ user_id, params }) {
+  return request(`/purchase/bom/get-checked-list/${user_id}?${stringify(params)}`);
+}
+
+// 根据节点id查询所有version
+export async function queryVersionByNode(params) {
+  return request(`/purchase/bom/flow/node?${stringify(params)}`);
+}

部分文件因为文件数量过多而无法显示