Selaa lähdekoodia

feat: 新增标段权限控制

lanjianrong 4 vuotta sitten
vanhempi
commit
4806d4149f

+ 4 - 0
src/assets/css/common.scss

@@ -354,6 +354,10 @@
   bottom: 0;
   z-index: 2;
 }
+verticalAlign
+.pi-vertical-baseline {
+  vertical-align: baseline;
+}
 
 // 公共头部
 .pi-header {

+ 5 - 0
src/index.scss

@@ -41,3 +41,8 @@ body {
   height: 2px !important;
   background: #1890ff !important;
 }
+
+.expandIcon {
+  margin-right: 0.5rem;
+  color: #6c757d;
+}

+ 0 - 6
src/pages/Contract/List/api.ts

@@ -1,6 +0,0 @@
-import request from "@/utils/common/request"
-
-export async function apiContractList() {
-  const { data } = await request.get('/api/contract/folder')
-  return data
-}

+ 29 - 15
src/pages/Contract/List/index.tsx

@@ -11,9 +11,10 @@ import { ColumnsType } from 'antd/lib/table'
 import React, { useState, useEffect } from 'react'
 import { useAliveController } from 'react-activation'
 import { RouteComponentProps, withRouter } from 'react-router-dom'
-import { apiContractList } from './api'
 import styles from './index.module.scss'
-const List: React.FC<RouteComponentProps> = (props) => {
+import { apiContractList } from '@/utils/common/api'
+import { handleIntoBidsection } from '@/utils/util'
+const List: React.FC<RouteComponentProps> = props => {
   const { clear } = useAliveController()
   const [ loading, setLoading ] = useState<boolean>(false)
   useEffect(() => {
@@ -24,7 +25,7 @@ const List: React.FC<RouteComponentProps> = (props) => {
 
   const getTree = async () => {
     setLoading(true)
-    const { data, code = -1 } = await apiContractList()
+    const { data, code = -1 } = await apiContractList(consts.BIDSECTION_TYPE.CONTRACT)
     if (code === consts.RET_CODE.SUCCESS) {
       setTree(data)
       setLoading(false)
@@ -34,12 +35,15 @@ const List: React.FC<RouteComponentProps> = (props) => {
   const [ tree, setTree ] = useContractTree()
   const [ expandedRowKeys, setRowKeys ] = useTableExpand(tree)
 
-  const linkHandler = (id: string, name: string) => {
+  const handleLinkClick = (id: string, name: string) => {
     tenderStore.saveTenderInfo({ bidsectionId: id, name })
-    props.history.push('/console/contract/content/summary')
+    const hasPermission = handleIntoBidsection("contract")
+    if (hasPermission) {
+      props.history.push('/console/contract/content/summary')
+    }
   }
 
-  const columns:ColumnsType<ContractTree> = [
+  const columns: ColumnsType<ContractTree> = [
     {
       title: '名称',
       dataIndex: 'name',
@@ -47,12 +51,21 @@ const List: React.FC<RouteComponentProps> = (props) => {
       width: '25%',
       render: (text: string, record: ContractTree) => {
         if (record.isfolder) {
-          return <div style={{ verticalAlign: "baseline" }}><SvgIcon type={record.hasFolder ? "xxh-folder-open" : "xxh-folder"} /><span className="pi-mg-left-2">{text}</span></div>
+          return (
+            <div className="pi-vertical-baseline">
+              <SvgIcon type={record.hasFolder ? 'xxh-folder-open' : 'xxh-folder'} />
+              <span className="pi-mg-left-2">{text}</span>
+            </div>
+          )
         } else {
-        return <div><span style={{ color: '#6c757d', marginRight: '.5rem' }}>{record.isEnd ? '└' : '├'}</span>
-        {/* <Link to={{ pathname: '/console/contract/content/summary', state: { id: record.bidsectionId } }}>{text}</Link> */}
-        <span className="pi-link-blue" onClick={() => linkHandler(record.bidsectionId, record.name)}>{text}</span>
-        </div>
+          return (
+            <div>
+              <span className="expandIcon">{record.isEnd ? '└' : '├'}</span>
+              <span className="pi-link-blue" onClick={() => handleLinkClick(record.bidsectionId, record.name)}>
+                {text}
+              </span>
+            </div>
+          )
         }
       }
     },
@@ -111,7 +124,10 @@ const List: React.FC<RouteComponentProps> = (props) => {
       <Header>
         <Slot>
           <Dropdown overlay={menu}>
-            <Button type="text" size="small" className={styles.textBtn}>展开/收起<CaretDownOutlined /></Button>
+            <Button type="text" size="small" className={styles.textBtn}>
+              展开/收起
+              <CaretDownOutlined />
+            </Button>
           </Dropdown>
         </Slot>
       </Header>
@@ -124,9 +140,7 @@ const List: React.FC<RouteComponentProps> = (props) => {
           rowKey={record => record.id}
           indentSize={20}
           expandable={{ expandedRowKeys, onExpand: setRowKeys }}
-          bordered
-        >
-        </Table>
+          bordered></Table>
       </div>
     </div>
   )

+ 0 - 6
src/pages/Quality/List/api.ts

@@ -1,6 +0,0 @@
-import request from "@/utils/common/request"
-
-export async function apiContractList() {
-  const { data } = await request.get('/api/contract/folder')
-  return data
-}

+ 11 - 7
src/pages/Quality/List/index.tsx

@@ -3,15 +3,16 @@ import Slot from '@/components/Header/slot'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
 import { ContractTree } from '@/types/contract'
+import { apiContractList } from '@/utils/common/api'
 import { useContractTree, useTableExpand } from '@/utils/common/customHooks'
 import consts from '@/utils/consts'
+import { handleIntoBidsection } from '@/utils/util'
 import { CaretDownOutlined } from '@ant-design/icons'
 import { Button, Dropdown, Menu, Table } from 'antd'
 import { ColumnsType } from 'antd/lib/table'
 import React, { useEffect, useState } from 'react'
 import { useAliveController } from 'react-activation'
 import { RouteComponentProps, withRouter } from 'react-router-dom'
-import { apiContractList } from './api'
 import styles from './index.module.scss'
 
 const List: React.FC<RouteComponentProps> = props => {
@@ -26,16 +27,19 @@ const List: React.FC<RouteComponentProps> = props => {
   const [ loading, setLoading ] = useState<boolean>(false)
   const getTree = async () => {
     setLoading(true)
-    const { data, code = -1 } = await apiContractList()
+    const { data, code = -1 } = await apiContractList(consts.BIDSECTION_TYPE.QUALITY)
     if (code === consts.RET_CODE.SUCCESS) {
       setTree(data)
       setLoading(false)
     }
   }
 
-  const linkHandler = (id: string, name: string) => {
+  const handleLinkClick = (id: string, name: string) => {
     tenderStore.saveTenderInfo({ bidsectionId: id, name })
-    props.history.push('/console/quality/content/summary')
+    const hasPermission = handleIntoBidsection("quality")
+    if (hasPermission) {
+      props.history.push('/console/quality/content/summary')
+    }
   }
   const columns: ColumnsType<ContractTree> = [
     {
@@ -46,7 +50,7 @@ const List: React.FC<RouteComponentProps> = props => {
       render: (text: string, record: ContractTree) => {
         if (record.isfolder) {
           return (
-            <div style={{ verticalAlign: 'baseline' }}>
+            <div className="pi-vertical-baseline">
               <SvgIcon type={record.hasFolder ? 'xxh-folder-open' : 'xxh-folder'} />
               <span className="pi-mg-left-2">{text}</span>
             </div>
@@ -54,8 +58,8 @@ const List: React.FC<RouteComponentProps> = props => {
         } else {
           return (
             <div>
-              <span style={{ color: '#6c757d', marginRight: '.5rem' }}>{record.isEnd ? '└' : '├'}</span>
-              <span className="pi-link-blue" onClick={() => linkHandler(record.bidsectionId, record.name)}>
+              <span className="expandIcon">{record.isEnd ? '└' : '├'}</span>
+              <span className="pi-link-blue" onClick={() => handleLinkClick(record.bidsectionId, record.name)}>
                 {text}
               </span>
             </div>

+ 0 - 6
src/pages/Safe/List/api.ts

@@ -1,6 +0,0 @@
-import request from "@/utils/common/request"
-
-export async function apiContractList() {
-  const { data } = await request.get('/api/contract/folder')
-  return data
-}

+ 11 - 7
src/pages/Safe/List/index.tsx

@@ -11,8 +11,9 @@ import { ColumnsType } from 'antd/lib/table'
 import React, { useEffect, useState } from 'react'
 import { useAliveController } from 'react-activation'
 import { RouteComponentProps, withRouter } from 'react-router-dom'
-import { apiContractList } from './api'
 import styles from './index.module.scss'
+import { apiContractList } from '@/utils/common/api'
+import { handleIntoBidsection } from '@/utils/util'
 const List: React.FC<RouteComponentProps> = props => {
   const { clear } = useAliveController()
   const [ loading, setLoading ] = useState<boolean>(false)
@@ -23,7 +24,7 @@ const List: React.FC<RouteComponentProps> = props => {
   }, [])
   const getTree = async () => {
     setLoading(true)
-    const { data, code = -1 } = await apiContractList()
+    const { data, code = -1 } = await apiContractList(consts.BIDSECTION_TYPE.SAFE)
     if (code === consts.RET_CODE.SUCCESS) {
       setTree(data)
       setLoading(false)
@@ -32,9 +33,12 @@ const List: React.FC<RouteComponentProps> = props => {
   const [ tree, setTree ] = useContractTree()
   const [ expandedRowKeys, setRowKeys ] = useTableExpand(tree)
 
-  const linkHandler = (id: string, name: string) => {
+  const handleLinkClick = (id: string, name: string) => {
     tenderStore.saveTenderInfo({ bidsectionId: id, name })
-    props.history.push('/console/safe/content/summary')
+    const hasPermission = handleIntoBidsection("safe")
+    if (hasPermission) {
+      props.history.push('/console/safe/content/summary')
+    }
   }
   const columns: ColumnsType<ContractTree> = [
     {
@@ -45,7 +49,7 @@ const List: React.FC<RouteComponentProps> = props => {
       render: (text: string, record: ContractTree) => {
         if (record.isfolder) {
           return (
-            <div style={{ verticalAlign: 'baseline' }}>
+            <div className="pi-vertical-baseline">
               <SvgIcon type={record.hasFolder ? 'xxh-folder-open' : 'xxh-folder'} />
               <span className="pi-mg-left-2">{text}</span>
             </div>
@@ -53,8 +57,8 @@ const List: React.FC<RouteComponentProps> = props => {
         } else {
           return (
             <div>
-              <span style={{ color: '#6c757d', marginRight: '.5rem' }}>{record.isEnd ? '└' : '├'}</span>
-              <span className="pi-link-blue" onClick={() => linkHandler(record.bidsectionId, record.name)}>
+              <span className="expandIcon">{record.isEnd ? '└' : '├'}</span>
+              <span className="pi-link-blue" onClick={() => handleLinkClick(record.bidsectionId, record.name)}>
                 {text}
               </span>
             </div>

+ 16 - 2
src/store/mobx/tender/index.ts

@@ -1,5 +1,5 @@
 import { iPermission } from "@/types/setting"
-import { apiGetPermissionWithBid } from "@/utils/common/api"
+import { apiGetPermission, apiGetPermissionWithBid } from "@/utils/common/api"
 import consts from "@/utils/consts"
 import { storage } from "@/utils/util"
 import { action, computed, observable } from "mobx"
@@ -31,7 +31,21 @@ class Tender {
     safe: { access: 0, add: 0, delete: 0 }
   }
 
-  @action saveTenderInfo(payload: iTenderState) {
+  @action async saveTenderInfo(payload: iTenderState) {
+    const { code = -1, data } = await apiGetPermission(payload.bidsectionId)
+    if (code === consts.RET_CODE.SUCCESS) {
+      const permissionObj = {} as AuthController
+      for (const key in data) {
+        if (Object.prototype.hasOwnProperty.call(data, key)) {
+          const permission = data[key] as string
+          console.log(permission)
+          console.log(JSON.parse(permission))
+
+          permissionObj[key] = JSON.parse(permission)
+        }
+      }
+      this.permission = permissionObj
+    }
     this.tender = payload
     storage.set('tenderInfo', payload)
 

+ 12 - 0
src/utils/common/api.ts

@@ -60,3 +60,15 @@ export async function apiProjectInfo() {
   const { data } = await request.get('/api/project')
   return data
 }
+
+/** 获取当前标段下的当前用户权限 */
+export async function apiGetPermission(bidsectionId: string) {
+  const { data } = await request.get('/api/projectSetting/permission', { bidsectionId })
+  return data
+}
+
+/** 获取合同树 */
+export async function apiContractList(type: number) {
+  const { data } = await request.get('/api/contract/folder', { bidsectionType: type })
+  return data
+}

+ 2 - 1
src/utils/consts.ts

@@ -19,6 +19,7 @@ export default {
     REVIEW: 'https://file-upload.6jlzf.cn/',
     DOWNLOAD: 'https://measuresaas.oss-cn-shenzhen.aliyuncs.com/'
   },
-  CONTRACT_TREE: { RETURN: 0, PAID: 1 } // 合同管理-树结构, 0 - 收入, 1- 支出
+  CONTRACT_TREE: { RETURN: 0, PAID: 1 }, // 合同管理-树结构, 0 - 收入, 1- 支出
+  BIDSECTION_TYPE: { CONTRACT: 0, SAFE: 1, QUALITY: 2 } // 获取标段列表的类型
 }
 

+ 15 - 1
src/utils/util.ts

@@ -1,3 +1,5 @@
+import { tenderStore } from '@/store/mobx'
+import { message } from 'antd'
 import dayjs from 'dayjs'
 
 function getCookie(name: string) {
@@ -171,6 +173,7 @@ const generatePsw = (len: number): string => {
   }
   return password
 }
+// 用于审批日志的日期的显示
 const formatDate = (d: string) => {
   if (!d) return ''
   const date = new Date(d)
@@ -203,4 +206,15 @@ const formatMoney = (num: number | undefined) => {
   if (!num) return '0.00'
   return (Math.round(num) + '').replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,') + '.00'
 }
-export { getCookie, storage, throttle, debounce, combinationPath, dayjsFormat, generatePsw, formatDate, formatMoney }
+
+// 控制是否有权限进入标段
+const handleIntoBidsection = (permission_type: 'contract' | 'safe' | 'quality'): boolean => {
+  const permission = !!tenderStore.permission[permission_type].access
+  if (!permission) {
+    message.error('暂无权限进入此标段,请联系管理员!')
+    return false
+  }
+  else return true
+}
+
+export { getCookie, storage, throttle, debounce, combinationPath, dayjsFormat, generatePsw, formatDate, formatMoney, handleIntoBidsection }