Преглед изворни кода

feat: 标段管理-树结构

lanjianrong пре 4 година
родитељ
комит
1d9e49303f

+ 1 - 1
config/webpack.config.js

@@ -134,7 +134,7 @@ module.exports = function(webpackEnv) {
           loader,
           options: {
             lessOptions: {
-              modifyVars: { '@primary-color': '#007bff', '@font-size-base': '12px' },
+              modifyVars: { '@primary-color': '#007bff', '@font-size-base': '12px', '@border-radius-base': '.2rem' },
               javascriptEnabled: true,
             },
           },

Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
src/assets/icons/svg/align-center.svg


+ 1 - 1
src/assets/icons/svg/folder.svg

@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M464 128H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M464 128H272l-54.63-54.63c-6-6-14.14-9.37-22.63-9.37H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48zm0 272H48V112h140.12l54.63 54.63c6 6 14.14 9.37 22.63 9.37H464v224z"/></svg>

+ 2 - 1
src/components/SvgIcon/index.scss

@@ -1,6 +1,7 @@
 .svg-class {
   display: inline-block;
-  overflow: hidden;
   width: 1em;
   height: 1em;
+  overflow: hidden;
+  vertical-align: baseline;
 }

+ 0 - 1
src/index.tsx

@@ -12,7 +12,6 @@ ReactDOM.render(
   </Provider>,
   document.getElementById('root')
 )
-
 // If you want your app to work offline and load faster, you can change
 // unregister() to register() below. Note this comes with some pitfalls.
 // Learn more about service workers: https://bit.ly/CRA-PWA

+ 9 - 0
src/pages/Management/Tender/api.ts

@@ -0,0 +1,9 @@
+import request from '@/utils/common/request'
+
+/**
+ * 获取标段管理-树结构数据
+ */
+export async function apiTree() {
+  const { data } = await request.get('/api/tree')
+  return data
+}

+ 29 - 0
src/pages/Management/Tender/index.module.scss

@@ -0,0 +1,29 @@
+.tableContent {
+  margin: 0 16px;
+  font-size: 12px;
+
+  .treeBtn {
+    padding: 1px 0.6rem;
+    color: #007bff;
+    border: 1px solid #007bff;
+    border-radius: 0.2rem;
+    &:hover {
+      color: #ffffff;
+      background-color: #007bff;
+    }
+  }
+
+  :global(.ant-table-thead .ant-table-cell) {
+    padding: 0.4rem;
+    text-align: center;
+    background-color: #e9ecef;
+    border-right: 1px solid #dee2e6;
+    border-bottom: 2px solid #dee2e6;
+  }
+  :global(.ant-table-tbody .ant-table-cell) {
+    padding: 0.4rem;
+  }
+  :global(.ant-table.ant-table-bordered > .ant-table-container > .ant-table-content > table > thead > tr > th) {
+    border-right: 1px solid #dee2e6;
+  }
+}

+ 12 - 0
src/pages/Management/Tender/index.scss

@@ -0,0 +1,12 @@
+.jumbotron {
+  padding: 4rem 2rem;
+  background-color: #e9ecef;
+  border-radius: 0.3rem;
+
+  & > h3 {
+    margin-bottom: 0.5rem;
+    font-size: 1.75rem;
+    font-weight: 500;
+    line-height: 1.2;
+  }
+}

+ 94 - 6
src/pages/Management/Tender/index.tsx

@@ -1,19 +1,107 @@
 import Header from '@/components/Header'
 import Slot from '@/components/Header/slot'
-import { FolderOutlined } from '@ant-design/icons'
-import { Button } from 'antd'
-import React from 'react'
-export default function Tender(props: any) {
-  console.log(props)
+import SvgIcon from '@/components/SvgIcon'
+import { TenderTree } from '@/types/tender'
+import consts from '@/utils/consts'
+import { FolderAddFilled } from '@ant-design/icons'
+import { Button, Table } from 'antd'
+import { ColumnsType } from 'antd/lib/table'
+import React, { useEffect, useState } from 'react'
+import { Link } from 'react-router-dom'
+import { apiTree } from './api'
+import styles from './index.module.scss'
+import './index.scss'
+const Tender: React.FC<{}> = () =>{
 
   return (
     <div className="content-wrap">
       <Header title="标段管理">
         <Slot position="right">
-          <Button type="primary" size="small" icon={<FolderOutlined />}>新建文件夹</Button>
+          <Button type="primary" size="small" icon={<FolderAddFilled />}>新建文件夹</Button>
         </Slot>
       </Header>
+      <Content/>
     </div>
   )
 }
 
+
+const Content: React.FC<{}> = () => {
+  const [ tree, setTree ] = useState<TenderTree[]>([])
+  // const column_name_render = (text: string, record: any, index: number) => {
+  //   console.log(1)
+  //   return (<span>{text}</span>)
+  // }
+  const columns: ColumnsType<TenderTree>  = [
+    {
+      title: '名称',
+      dataIndex: 'name',
+      key: 'name',
+      // eslint-disable-next-line react/display-name
+      render: (text: string, record: TenderTree) => {
+        if (record.isfolder) {
+          return <div style={{ verticalAlign: "baseline" }}><SvgIcon iconClass="folder" fontSize="12" /><span className="pi-mg-left-5">{text}</span></div>
+        } else {
+          return <div><span style={{ color: '#6c757d', marginRight: '.5rem' }}>{record.isEnd ? '└' : '├'}</span><span>{text}</span></div>
+        }
+      }
+    },
+    {
+      title: '成员',
+      dataIndex: 'member',
+      key: 'member',
+      width: 200,
+      // eslint-disable-next-line react/display-name
+      render: (text:string, record: TenderTree, index: number) => {
+        if (record.leaf) {
+          return <div><span className="pi-mg-right-5">{record.ancounts} 成员</span><Link className={styles.treeBtn} to="/">成员管理</Link></div>
+        }
+      }
+    },
+    {
+      title: '操作',
+      dataIndex: 'opreate',
+      key: 'opreate',
+      width: 80
+      // eslint-disable-next-line react/display-name
+      // render: (text:string, record: TenderTree, index: number) => {
+      //   return <Dropdown overlay={(record: TenderTree, index: number) => {
+      //     return (
+      //       <Menu>
+      //         <Menu.Item key="0"></Menu.Item>
+      //         <Menu.Item key="1"></Menu.Item>
+      //         <Menu.Item key="2"></Menu.Item>
+      //         <Menu.Item key="3"></Menu.Item>
+      //       </Menu>
+      //     )
+      //   }} trigger={['click']}>
+      //     <span>
+      //       <SvgIcon iconClass="align-center" fill="#007bff" fontSize="12"></SvgIcon>
+      //       <CaretDownOutlined style={{ fontSize: "12px", color: "#007bff" }}/>
+      //     </span>
+      //   </Dropdown>
+      // }
+    }
+  ]
+  useEffect(() => {
+    getTree()
+  }, [])
+  const getTree = async () => {
+    const { data: { children = [] } = [], code = -1 } = await apiTree()
+    if (code === consts.RET_CODE.SUCCESS) {
+      setTree(children)
+    }
+  }
+
+  return (
+    <div className="pi-flex-column">
+      <div className="pi-mg-16 pi-pd-tb-64 pi-pd-lr-32 jumbotron">
+        <h3>没有标段数据</h3>
+      </div>
+      <div className={styles.tableContent}>
+        <Table<TenderTree> columns={columns} dataSource={tree} pagination={false} rowKey={record => record.id} bordered></Table>
+      </div>
+    </div>
+  )
+}
+export default  Tender

src/types/login.ts → src/types/login.d.ts


src/types/router.ts → src/types/router.d.ts


+ 20 - 0
src/types/tender.d.ts

@@ -0,0 +1,20 @@
+export type TenderTree = {
+  id: string;
+  name: string;
+  projectId: string;
+  tenderId: number;
+  parentId: string;
+  depth: number;
+  serial: string;
+  attribution: string;
+  isfolder: number;
+  createTime: string;
+  updateTime: string;
+  moveId: string;
+  ancounts: number;
+  csrf: string;
+  leaf: boolean;
+  isEnd: boolean;
+  childsTotal: number;
+  children: any[] | null;
+}

+ 26 - 7
src/utils/util.ts

@@ -35,20 +35,39 @@ const storage = {
   }
 }
 
-const debounce = (fn:Function, debTime: number): any | Promise<void> => {
-  let timer:any = null
-  return (debTime: number,...args:any[]) => {
-    if(timer) clearTimeout(timer)
+// 节流
+const throttle = (fn: Function, delay: number) => {
+  // 定义上次触发时间
+  let last: number = 0
+  return (...args: any[]) => {
+    const now: number = + Date.now()
+    console.log("call", now, last, delay)
+    if (now > last + delay) {
+      last = now
+      fn.apply(this, args)
+    }
+  }
+}
+
+const debounce = (fn: Function, delay: number) => {
+  let timer: NodeJS.Timer | null = null
+  return (...args: any[]) => {
+    // 判断定时器是否存在,清除定时器
+    if (timer) {
+      clearTimeout(Number(timer))
+    }
+
+    // 重新调用setTimeout
     timer = setTimeout(() => {
-        fn.apply(this,...args)
-        timer = null
-      }, debTime)
+      fn.apply(this, args)
+    }, delay)
   }
 }
 
 export {
   getCookie,
   storage,
+  throttle,
   debounce
 }