Sfoglia il codice sorgente

refactor: 合同管理table重构

lanjianrong 4 anni fa
parent
commit
ec363fcab1

+ 9 - 9
src/pages/Contract/Content/Income/api.ts

@@ -5,8 +5,9 @@ import consts from '@/utils/consts'
  * 标段升降、上下移、增删
  * @param type - 操作类型
  * @param payload - 载荷
+ * @param contractType - 合同类型: 0-收入合同|1-支出合同
  */
-export async function apiResfulContractTree(type: string, payload: object) {
+export async function apiResfulContractTree(type: string, payload: object, contractType: number) {
   let url: string = '', method: string = ''
   switch (type) {
     case 'serial':
@@ -28,7 +29,7 @@ export async function apiResfulContractTree(type: string, payload: object) {
     default:
       break
   }
-  const { data } = await request[method](url, { ...payload, treeType: consts.CONTRACT_TREE.RETURN })
+  const { data } = await request[method](url, { ...payload, treeType: contractType })
   return data
 }
 
@@ -37,8 +38,8 @@ export async function apiResfulContractTree(type: string, payload: object) {
  * @param id - 项目节id
  * @param bidsectionId - 标段id
  */
-export async function apiGetIncome(id: string, bidsectionId: string) {
-  const { data } = await request.get('/api/contract/income', { id, bidsectionId })
+export async function apiGetIncome(id: string, bidsectionId: string, contractType: 'income' | 'expenditure') {
+  const { data } = await request.get(`/api/contract/${contractType}`, { id, bidsectionId })
   return data
 }
 
@@ -55,12 +56,11 @@ export async function apiUpdateSerial(id: string, bidsectionId: string, serial:
 
 /**
  * 修改合同节名称
- * @param id 项目节id
- * @param bidsectionId 标段id
- * @param name 名称
+ * @param payload - 载荷
+
  */
-export async function apiUpdateName(id: string, bidsectionId: string, name: string) {
-  const { data } = await request.post('/api/contract/section/save', { id, bidsectionId, name, treeType: consts.CONTRACT_TREE.RETURN })
+export async function apiUpdateContractName(payload: object) {
+  const { data } = await request.post('/api/contract/section/save', { ...payload })
   return data
 }
 

+ 3 - 4
src/pages/Contract/Content/Income/components/Modal/api.ts

@@ -1,12 +1,11 @@
 import request from '@/utils/common/request'
-import consts from '@/utils/consts'
 
 /**
- * 获得标段回款-项目节信息
+ * 获取标段合同树-项目节信息(收入/支出)
  * @param bidsectionId 标段id
  */
-export async function apiContractIncome(bidsectionId: string) {
-  const { data } = await request.get('/api/contract/income/section/all', { bidsectionId })
+export async function apiContractTree(type: 'income' | 'expenditure',bidsectionId: string) {
+  const { data } = await request.get(`/api/contract/${type}/section/all`, { bidsectionId })
   return data
 }
 

+ 102 - 0
src/pages/Contract/Content/Income/components/TableContent/EditableTable.tsx

@@ -0,0 +1,102 @@
+import React, { useContext, useState, useEffect, useRef } from 'react'
+import { Input, Form } from 'antd'
+import { FormInstance } from 'antd/lib/form'
+import { ContractTree } from '@/types/contract'
+
+const EditableContext = React.createContext<FormInstance<any> | null>(null)
+
+interface EditableRowProps {
+  index: number;
+}
+
+const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
+  const [ form ] = Form.useForm()
+  return (
+    <Form form={form} component={false}>
+      <EditableContext.Provider value={form}>
+        <tr {...props} />
+      </EditableContext.Provider>
+    </Form>
+  )
+}
+
+interface EditableCellProps {
+  title: React.ReactNode;
+  editable: boolean;
+  children: React.ReactNode;
+  dataIndex: keyof ContractTree;
+  record: ContractTree;
+  handleSave: (dataIndex: keyof ContractTree, value: string, record: ContractTree) => void;
+}
+
+const EditableCell: React.FC<EditableCellProps> = ({
+  title,
+  editable,
+  children,
+  dataIndex,
+  record,
+  handleSave,
+  ...restProps
+}) => {
+  const [ editing, setEditing ] = useState(false)
+  const inputRef = useRef<Input>(null)
+  const form = useContext(EditableContext)!
+
+
+  useEffect(() => {
+    if (editing) {
+      inputRef.current!.focus()
+    }
+  }, [ editing ])
+
+  const toggleEdit = () => {
+    setEditing(!editing)
+    if (dataIndex === 'code') {
+      form.setFieldsValue({ [dataIndex]: record.serial })
+    } else {
+      form.setFieldsValue({ [dataIndex]: record[dataIndex] })
+    }
+  }
+
+  const save = async () => {
+    try {
+      const values = await form.validateFields()
+
+      toggleEdit()
+      handleSave(dataIndex, values[dataIndex], record)
+    } catch (errInfo) {
+      console.log('Save failed:', errInfo)
+    }
+  }
+
+  let childNode = children
+
+  if (editable) {
+    childNode = editing ? (
+      <Form.Item
+        style={{ margin: 0 }}
+        name={dataIndex}
+      >
+        {
+          dataIndex === 'code' ?
+          <Input size="small" ref={inputRef} onPressEnter={save} onBlur={save} addonBefore={record.attribution} autoComplete="off"/>
+          :
+          <Input size="small" ref={inputRef} onPressEnter={save} onBlur={save} autoComplete="off"/>
+
+        }
+      </Form.Item>
+    ) : (
+      <div className="editable-cell-value-wrap" style={{ paddingRight: 24 }} onDoubleClick={toggleEdit}>
+        {children}
+      </div>
+    )
+  }
+
+  return <td {...restProps}>{childNode}</td>
+}
+
+
+export {
+  EditableRow,
+  EditableCell
+}

+ 19 - 0
src/pages/Contract/Content/Income/components/TableContent/index.scss

@@ -0,0 +1,19 @@
+.editable-cell {
+  position: relative;
+}
+
+.editable-cell-value-wrap {
+  min-height: 28px;
+  padding: 5px 12px;
+  cursor: pointer;
+}
+
+.editable-cell-value-wrap:hover {
+  padding: 4px 11px;
+  border: 1px solid #d9d9d9;
+  border-radius: 4px;
+}
+
+[data-theme='dark'] .editable-row:hover .editable-cell-value-wrap {
+  border: 1px solid #434343;
+}

+ 99 - 87
src/pages/Contract/Content/Income/components/TableContent/index.tsx

@@ -1,34 +1,47 @@
 import Authorization from '@/components/Authorization'
 import { ZhSubmitButton } from '@/components/Button'
 import OssUploadModal from '@/components/OssUpload'
-import { contractReturnStore, tenderStore } from '@/store/mobx'
-import { iIncomeTree, iShowTemplateState, iTemplateState } from '@/types/contract'
+import { contractPaidStore, contractReturnStore, tenderStore } from '@/store/mobx'
+import { ContractTree, iShowTemplateState, iTemplateState } from '@/types/contract'
 import { iFile } from '@/types/file'
 import { apiSaveFileInfo } from '@/utils/common/api'
 import { contractConsts } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
 import { formatMoney } from '@/utils/util'
-import { Button, Input, message, Radio, Table, Tabs } from 'antd'
+import { Button, message, Radio, Table, Tabs } from 'antd'
 import Modal from 'antd/lib/modal/Modal'
 import { RadioChangeEvent } from 'antd/lib/radio'
 import { ColumnsType } from 'antd/lib/table'
 import { observer } from 'mobx-react'
-import React, { FocusEvent, KeyboardEvent, useEffect, useRef, useState } from 'react'
-import { apiGetIncome, apiResfulContractTree, apiUpdateName, apiUpdateSerial } from '../../api'
-import { apiContractIncome, apiSetTemplate } from '../Modal/api'
+import React, { useEffect, useState } from 'react'
+import { apiGetIncome, apiUpdateContractName, apiUpdateSerial } from '../../api'
+import { apiContractTree, apiSetTemplate } from '../Modal/api'
 import Detail from '../Tabs/Detail'
 import File from '../Tabs/File'
 import Receivable from '../Tabs/Receivable'
+import { EditableCell, EditableRow } from './EditableTable'
 import styles from './index.module.scss'
+import './index.scss'
+
+
+type EditableTableProps = Parameters<typeof Table>[0];
+type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
+
 interface iTableContentPorps {
   changeModalType: (type: string) => void
-  row: iIncomeTree
-  setRow: (record: iIncomeTree) => void
+  row: ContractTree
+  setRow: (record: ContractTree) => void
   history: any
+  type: 'income' | 'expenditure'
 }
 
+interface HandleLabelProps {
+  id: string
+  bidsectionId: string
+  name?: string
+}
 
-const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, history }) => {
+const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, history, type }) => {
 
   const [ sectionTemplate, setSectionTemplate ] = useState<iShowTemplateState>({
     isShow: false,
@@ -70,7 +83,7 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
   }, [])
   const initData = async () => {
 
-    const data = await apiContractIncome(tenderStore.bid)
+    const data = await apiContractTree(type, tenderStore.bid)
     if (data.code === consts.RET_CODE.SUCCESS) {
       if (data.isTemplate && data.isTemplate === 1) {
         setSectionTemplate({
@@ -91,36 +104,21 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
       handleRowClick(row.id, row.bidsectionId)
     }
   }
-  interface HandleLabelProps {
-    id: string
-    bidsectionId: string
-    name?: string
-  }
 
-  const handleNewLabel = async (type: string, payload: HandleLabelProps) => {
-    let RET_CODE: number = -1
-    if (type === 'create') {
-      payload.name = inputEl.current?.state.value
-      const { code = -1 } = await apiResfulContractTree('add', payload)
-      RET_CODE = code
-    }
-    if (type === 'edit') {
-      const name = inputEl.current?.state.value
-      const { code = -1 } = await apiUpdateName(payload.id, payload.bidsectionId, name)
-      RET_CODE = code
-    }
-    if (RET_CODE === consts.RET_CODE.SUCCESS) {
+
+  const handleUpdateContractName = async (payload: object) => {
+    const { code = -1 } = await apiUpdateContractName(payload)
+    if (code === consts.RET_CODE.SUCCESS) {
       contractReturnStore.resetTree(tenderStore.tender.bidsectionId)
     }
   }
 
-  const codeChange = async (row: iIncomeTree, value: string) => {
+  const codeChange = async (value: string, row: ContractTree) => {
     const { code = -1 } = await apiUpdateSerial(row.id, row.bidsectionId, value)
     if (code === consts.RET_CODE.SUCCESS) {
       initData()
     }
   }
-  const inputEl = useRef<Input>(null)
   const modalColumns: ColumnsType<iTemplateState> = [
     {
       title: '项目节',
@@ -139,49 +137,34 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
     }
   ]
 
-  const TableColumns: ColumnsType<iIncomeTree> = [
+  const tableColumns: (ColumnTypes[number] & { editable?: boolean; dataIndex: string })[] = [
     {
       title: '编号',
       dataIndex: 'code',
       width: '20%',
-      // eslint-disable-next-line react/display-name
-      render: (text: string, row: iIncomeTree) => {
-        if (row.isEdit) {
-          return (
-            <Input
-              defaultValue={row.serial}
-              addonBefore={row.attribution}
-              size="small"
-              style={{ width: 80 }}
-              onPressEnter={(e: KeyboardEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
-              onBlur={(e: FocusEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
-            />)
-        } else {
-          return <span>{row.code}</span>
-        }
-        // return <span>{row.code}</span>
-      }
+      editable: true
     },
     {
       title: '项目名称',
       dataIndex: 'name',
       width: '20%',
-      render: (text: any, record: iIncomeTree) => {
-        if (record.isEdit || record.isNew) {
-          const type = record.isEdit ? 'edit' : 'create'
-          return (
-            <Input
-              defaultValue={record.name}
-              size="small"
-              type="text"
-              ref={inputEl}
-              onPressEnter={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
-              onBlur={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
-            />)
-        } else {
-          return <span>{text}</span>
-        }
-      }
+      editable: true
+      // render: (text: any, record: iIncomeTree) => {
+      //   if (record.isEdit || record.isNew) {
+      //     const type = record.isEdit ? 'edit' : 'create'
+      //     return (
+      //       <Input
+      //         defaultValue={record.name}
+      //         size="small"
+      //         type="text"
+      //         ref={inputEl}
+      //         onPressEnter={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
+      //         onBlur={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
+      //       />)
+      //   } else {
+      //     return <span>{text}</span>
+      //   }
+      // }
     },
     {
       title: '合同名称',
@@ -199,7 +182,7 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
       align: 'right',
       width: '10%',
       // eslint-disable-next-line react/display-name
-      render: (text: any, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : null
+      render: (text: any, record: any) => record.contractCode ? <span>{formatMoney(text)}</span> : null
     },
     {
       title: '回款金额',
@@ -207,14 +190,14 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
       align: 'right',
       width: '10%',
       // eslint-disable-next-line react/display-name
-      render: (text: any, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : null
+      render: (text: any, record: any) => record.contractCode ? <span>{formatMoney(text)}</span> : null
     },
     {
       title: '状态',
       dataIndex: 'contractStatus',
       width: '10%',
       // eslint-disable-next-line react/display-name
-      render: (_: any, record: iIncomeTree) => record.contractCode ? <span className={contractConsts[record.contractStatus].className}>{contractConsts[record.contractStatus].text}</span> : null
+      render: (_: any, record: any) => record.contractCode ? <span className={contractConsts[record.contractStatus].className}>{contractConsts[record.contractStatus].text}</span> : null
     }
 
   ]
@@ -258,32 +241,29 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
     }
   }
 
-  const onClickRow = (record: iIncomeTree) => {
+  const onClickRow = (record: any) => {
     return {
       onClick() {
-        handleRowClick(record.id, record.bidsectionId, record.isEdit, record.isNew)
-      },
-      onDoubleClick() {
-        contractReturnStore.rowChange(row.id)
+        handleRowClick(record.id, record.bidsectionId)
       }
     }
   }
 
   // 行点击回调
-  const handleRowClick = async (id: string, bid: string, isEdit?: boolean, isNew?: boolean) => {
-    if (!isEdit && !isNew) {
-      const { code = -1, section = {}, contract: newContract = {} } = await apiGetIncome(id, bid)
-      if (code === consts.RET_CODE.SUCCESS) {
-        setRow(section)
-        contractReturnStore.updateContract(newContract)
-      }
+  const handleRowClick = async (id: string, bid: string) => {
+    const { code = -1, section = {}, contract: newContract = {} } = await apiGetIncome(id, bid, type)
+    if (code === consts.RET_CODE.SUCCESS) {
+      setRow(section)
+      type === 'income' && (contractReturnStore.updateContract(newContract))
+      type === 'expenditure' && (contractPaidStore.updateContract(newContract))
     }
   }
-  const handleRowClass = (record: iIncomeTree) => {
-    return record.id === row.id ? 'ant-table-row-selected' : ''
+  const handleRowClass = (record: any) => {
+    return record.id === row.id ? 'ant-table-row-selected editable-row' : ''
   }
   const tabOnClick = (key: string) => {
-    contractReturnStore.changeUpdate(key)
+    type === 'income' && (contractReturnStore.changeUpdate(key))
+    type === 'expenditure' && (contractPaidStore.changeUpdate(key))
   }
 
   // 阿里oss上传弹窗
@@ -292,10 +272,41 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
     const { code = -1 } = await apiSaveFileInfo(fileList, consts.DATA_TYPE.CONTRACT_RETURN, row.contractId)
     if (code === consts.RET_CODE.SUCCESS) {
       setVisible(false)
-      contractReturnStore.changeUpdate('3')
+      type === 'income' && (contractReturnStore.changeUpdate('3'))
+      type === 'expenditure' && (contractPaidStore.changeUpdate('3'))
     }
   }
 
+  const components = {
+    body: {
+      row: EditableRow,
+      cell: EditableCell
+    }
+  }
+
+  const handleSave = (dataIndex: keyof ContractTree, value: string, row: ContractTree) => {
+    if (dataIndex === 'code') {
+      codeChange(value, row)
+    } else {
+      handleUpdateContractName({ id: row.id, bidsectionId: row.bidsectionId, treeType: type === 'income' ? 0 : 1, name: value })
+    }
+
+  }
+  const _tableColumns = tableColumns.map(col => {
+    if (!col.editable) {
+      return col
+    }
+    return {
+      ...col,
+      onCell: (record: ContractTree) => ({
+        record,
+        editable: col.editable,
+        dataIndex: col.dataIndex,
+        title: col.title,
+        handleSave
+      })
+    }
+  })
   return sectionTemplate.isShow ?
     <Modal
       visible={sectionTemplate.isShow}
@@ -361,12 +372,13 @@ const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, h
       <div className={styles.spreadSheets}>
         {
           contractReturnStore.showTable ?
-            <Table<iIncomeTree>
-              dataSource={contractReturnStore.tree}
-              columns={TableColumns}
+            <Table
+              components={components}
+              dataSource={type === 'income' ? contractReturnStore.tree : contractPaidStore.tree}
+              columns={_tableColumns as ColumnTypes}
               bordered
               pagination={false}
-              rowKey={record => record.id}
+              // rowKey={record => record.id}
               defaultExpandAllRows={true}
               onRow={onClickRow}
               rowClassName={handleRowClass}

+ 13 - 10
src/pages/Contract/Content/Income/index.tsx

@@ -4,7 +4,7 @@ import RuleModal from '@/components/RuleModal'
 import SvgIcon from '@/components/SvgIcon'
 import { apiSaveRule } from '@/pages/Safe/Content/List/api'
 import { contractReturnStore, tenderStore } from '@/store/mobx'
-import { iIncomeTree, iModalProps } from '@/types/contract'
+import { ContractTree, iModalProps } from '@/types/contract'
 import { contractTreeBaseId } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
 import { Button, message, Tooltip } from 'antd'
@@ -14,6 +14,7 @@ import ContractModal from './components/Modal'
 import TableContent from './components/TableContent'
 import Authorization from '@/components/Authorization'
 import { RouteComponentProps } from 'react-router'
+import { ContractType } from '@/store/mobx/contractReturn'
 
 interface iModal {
   visible: boolean
@@ -22,7 +23,6 @@ interface iModal {
 
 
 const Income: React.FC<RouteComponentProps> = (props) => {
-  console.log(props)
 
   const { history } = props
   const [ modalObj, setModalObj ] = useState<iModalProps>({
@@ -31,13 +31,13 @@ const Income: React.FC<RouteComponentProps> = (props) => {
     confirmLoading: false,
     contractType: 'income'
   })
-  const [ row, setRow ] = useState<iIncomeTree>({
+  const [ row, setRow ] = useState<ContractTree>({
     elderBrother: false,
     isEnd: false,
     attribsortution: 0,
     attribution: '',
     bidsectionId: '',
-    children: undefined,
+    children: [],
     code: '',
     contractCode: '',
     contractId: '',
@@ -89,10 +89,7 @@ const Income: React.FC<RouteComponentProps> = (props) => {
     })
   }
   const treeResfulApiHandler = async (type: string, payload: any) => {
-    if (type === 'add') {
-      return contractReturnStore.addRowTree(payload.id)
-    }
-    const { code = -1, section = {} } = await apiResfulContractTree(type, payload)
+    const { code = -1, section = {} } = await apiResfulContractTree(type, payload, consts.CONTRACT_TREE.RETURN)
     if (code === consts.RET_CODE.SUCCESS) {
       contractReturnStore.resetTree(tenderStore.bid)
       if (type !== 'add' && type !== 'del') {
@@ -130,7 +127,7 @@ const Income: React.FC<RouteComponentProps> = (props) => {
               row.id ?
                 <>
                   <Tooltip title="添加子项">
-                    <Button type="text" icon={<SvgIcon type="xxh-plus" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('add', { id: row.id, bidsectionId: row.bidsectionId })} />
+                    <Button type="text" icon={<SvgIcon type="xxh-plus" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('add', { id: row.id, bidsectionId: row.bidsectionId, name: '' })} />
                   </Tooltip>
                   {
                     !row.children?.length ?
@@ -187,7 +184,13 @@ const Income: React.FC<RouteComponentProps> = (props) => {
           }
         </Slot>
       </Header>
-      <TableContent changeModalType={changeModalType} row={row} setRow={(record: iIncomeTree) => setRow({ ...row, ...record })} history={history} />
+      <TableContent
+        changeModalType={changeModalType}
+        row={row}
+        setRow={(record: ContractTree) => setRow({ ...row, ...record })}
+        history={history}
+        type={ContractType.INCOME}
+      />
       <RuleModal
         type={consts.RULE.CONTRACT_RETURN}
         title="合同管理编号设置"

+ 411 - 411
src/pages/Contract/Content/Spending/components/TableContent/index.tsx

@@ -1,432 +1,432 @@
-import { ZhSubmitButton } from '@/components/Button'
-import OssUploadModal from '@/components/OssUpload'
-import { contractPaidStore, tenderStore } from '@/store/mobx'
-import { iIncomeTree, iShowTemplateState, iTemplateState } from '@/types/contract'
-import { iFile } from '@/types/file'
-import { apiSaveFileInfo } from '@/utils/common/api'
-import { contractConsts } from '@/utils/common/constStatus'
-import consts from '@/utils/consts'
-import { Button, Input, message, Radio, Table, Tabs } from 'antd'
-import Modal from 'antd/lib/modal/Modal'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import { ColumnsType } from 'antd/lib/table'
-import { observer } from 'mobx-react'
-import React, { FocusEvent, KeyboardEvent, useEffect, useRef, useState } from 'react'
-import { apiSetTemplate } from '../../../Income/components/Modal/api'
-import { apiGetExpenditure, apiResfulContractTree, apiUpdateName, apiUpdateSerial } from '../../api'
-import { apiContractExpenditure } from './api'
-import Detail from '../Tabs/Detail'
-import File from '../Tabs/File'
-import Receivable from '../Tabs/Receivable'
-import styles from './index.module.scss'
-import { formatMoney } from '@/utils/util'
-interface iTableContentPorps {
-  changeModalType: (type: string) => void
-  row: iIncomeTree
-  setRow: (record: iIncomeTree) => void
-  history: any
-}
+// import { ZhSubmitButton } from '@/components/Button'
+// import OssUploadModal from '@/components/OssUpload'
+// import { contractPaidStore, tenderStore } from '@/store/mobx'
+// import { ContractTree, iShowTemplateState, iTemplateState } from '@/types/contract'
+// import { iFile } from '@/types/file'
+// import { apiSaveFileInfo } from '@/utils/common/api'
+// import { contractConsts } from '@/utils/common/constStatus'
+// import consts from '@/utils/consts'
+// import { Button, Input, message, Radio, Table, Tabs } from 'antd'
+// import Modal from 'antd/lib/modal/Modal'
+// import { RadioChangeEvent } from 'antd/lib/radio'
+// import { ColumnsType } from 'antd/lib/table'
+// import { observer } from 'mobx-react'
+// import React, { FocusEvent, KeyboardEvent, useEffect, useRef, useState } from 'react'
+// import { apiSetTemplate } from '../../../Income/components/Modal/api'
+// import { apiGetExpenditure, apiResfulContractTree, apiUpdateName, apiUpdateSerial } from '../../api'
+// import { apiContractExpenditure } from './api'
+// import Detail from '../Tabs/Detail'
+// import File from '../Tabs/File'
+// import Receivable from '../Tabs/Receivable'
+// import styles from './index.module.scss'
+// import { formatMoney } from '@/utils/util'
+// interface iTableContentPorps {
+//   changeModalType: (type: string) => void
+//   row: ContractTree
+//   setRow: (record: ContractTree) => void
+//   history: any
+// }
 
 
-const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, history }) => {
-  const [ sectionTemplate, setSectionTemplate ] = useState<iShowTemplateState>({
-    isShow: false,
-    template: '',
-    loading: false
-  })
-  const [ tempalte, setTempalte ] = useState<{ template1: iTemplateState, template2: iTemplateState }>({
-    template1: {
-      attribution: '',
-      children: undefined,
-      depth: 0,
-      id: 0,
-      isEnd: false,
-      leaf: false,
-      name: '',
-      parentId: 0,
-      serial: ''
-    },
-    template2: {
-      attribution: '',
-      children: undefined,
-      depth: 0,
-      id: 0,
-      isEnd: false,
-      leaf: false,
-      name: '',
-      parentId: 0,
-      serial: ''
-    }
-  })
+// const GCsheet: React.FC<iTableContentPorps> = ({ changeModalType, row, setRow, history }) => {
+//   const [ sectionTemplate, setSectionTemplate ] = useState<iShowTemplateState>({
+//     isShow: false,
+//     template: '',
+//     loading: false
+//   })
+//   const [ tempalte, setTempalte ] = useState<{ template1: iTemplateState, template2: iTemplateState }>({
+//     template1: {
+//       attribution: '',
+//       children: undefined,
+//       depth: 0,
+//       id: 0,
+//       isEnd: false,
+//       leaf: false,
+//       name: '',
+//       parentId: 0,
+//       serial: ''
+//     },
+//     template2: {
+//       attribution: '',
+//       children: undefined,
+//       depth: 0,
+//       id: 0,
+//       isEnd: false,
+//       leaf: false,
+//       name: '',
+//       parentId: 0,
+//       serial: ''
+//     }
+//   })
 
-  // 阿里oss弹窗控制器
-  const [ visible, setVisible ] = useState<boolean>(false)
+//   // 阿里oss弹窗控制器
+//   const [ visible, setVisible ] = useState<boolean>(false)
 
-  const { TabPane } = Tabs
+//   const { TabPane } = Tabs
 
-  useEffect(() => {
-    initData()
-  }, [])
-  const initData = async () => {
-    const data = await apiContractExpenditure(tenderStore.bid)
-    if (data.code === consts.RET_CODE.SUCCESS) {
-      if (data.isTemplate && data.isTemplate === 1) {
-        setSectionTemplate({
-          ...sectionTemplate,
-          isShow: true
-        })
-        setTempalte({
-          ...tempalte,
-          template1: data.sectionTemplate1,
-          template2: data.sectionTemplate2
-        })
-      } else {
-        contractPaidStore.updateTree(data.sectionTree.children)
-      }
-    }
-    if (row.id) {
-      handleRowClick(row.id, row.bidsectionId)
-    }
-  }
-  interface iLabelHandlerProps {
-    id: string
-    bidsectionId: string
-    name?: string
-  }
+//   useEffect(() => {
+//     initData()
+//   }, [])
+//   const initData = async () => {
+//     const data = await apiContractExpenditure(tenderStore.bid)
+//     if (data.code === consts.RET_CODE.SUCCESS) {
+//       if (data.isTemplate && data.isTemplate === 1) {
+//         setSectionTemplate({
+//           ...sectionTemplate,
+//           isShow: true
+//         })
+//         setTempalte({
+//           ...tempalte,
+//           template1: data.sectionTemplate1,
+//           template2: data.sectionTemplate2
+//         })
+//       } else {
+//         contractPaidStore.updateTree(data.sectionTree.children)
+//       }
+//     }
+//     if (row.id) {
+//       handleRowClick(row.id, row.bidsectionId)
+//     }
+//   }
+//   interface iLabelHandlerProps {
+//     id: string
+//     bidsectionId: string
+//     name?: string
+//   }
 
-  const handleNewLabel = async (type: string, payload: iLabelHandlerProps) => {
-    let RET_CODE: number = -1
-    if (type === 'create') {
-      payload.name = inputEl.current?.state.value
-      const { code = -1 } = await apiResfulContractTree('add', payload)
-      RET_CODE = code
-    }
-    if (type === 'edit') {
-      const name = inputEl.current?.state.value
-      const { code = -1 } = await apiUpdateName(payload.id, payload.bidsectionId, name)
-      RET_CODE = code
-    }
-    if (RET_CODE === consts.RET_CODE.SUCCESS) {
-      contractPaidStore.resetTree(tenderStore.tender.bidsectionId)
-    }
-  }
+//   const handleNewLabel = async (type: string, payload: iLabelHandlerProps) => {
+//     let RET_CODE: number = -1
+//     if (type === 'create') {
+//       payload.name = inputEl.current?.state.value
+//       const { code = -1 } = await apiResfulContractTree('add', payload)
+//       RET_CODE = code
+//     }
+//     if (type === 'edit') {
+//       const name = inputEl.current?.state.value
+//       const { code = -1 } = await apiUpdateName(payload.id, payload.bidsectionId, name)
+//       RET_CODE = code
+//     }
+//     if (RET_CODE === consts.RET_CODE.SUCCESS) {
+//       contractPaidStore.resetTree(tenderStore.tender.bidsectionId)
+//     }
+//   }
 
-  const codeChange = async (row: iIncomeTree, value: string) => {
-    const { code = -1 } = await apiUpdateSerial(row.id, row.bidsectionId, value)
-    if (code === consts.RET_CODE.SUCCESS) {
-      initData()
-    }
-  }
-  const inputEl = useRef<Input>(null)
-  const modalColumns: ColumnsType<iTemplateState> = [
-    {
-      title: '项目节',
-      dataIndex: 'serial',
-      width: '30%',
-      // eslint-disable-next-line react/display-name
-      render: (text: string, row: iTemplateState) => {
-        const { attribution = '', serial = '' } = row
-        return <span>{`${attribution}${serial}`}</span>
-      }
-    },
-    {
-      title: '名称',
-      dataIndex: 'name',
-      width: '70%'
-    }
-  ]
+//   const codeChange = async (row: ContractTree, value: string) => {
+//     const { code = -1 } = await apiUpdateSerial(row.id, row.bidsectionId, value)
+//     if (code === consts.RET_CODE.SUCCESS) {
+//       initData()
+//     }
+//   }
+//   const inputEl = useRef<Input>(null)
+//   const modalColumns: ColumnsType<iTemplateState> = [
+//     {
+//       title: '项目节',
+//       dataIndex: 'serial',
+//       width: '30%',
+//       // eslint-disable-next-line react/display-name
+//       render: (text: string, row: iTemplateState) => {
+//         const { attribution = '', serial = '' } = row
+//         return <span>{`${attribution}${serial}`}</span>
+//       }
+//     },
+//     {
+//       title: '名称',
+//       dataIndex: 'name',
+//       width: '70%'
+//     }
+//   ]
 
-  const TableColumns: ColumnsType<iIncomeTree> = [
-    {
-      title: '编号',
-      dataIndex: 'code',
-      width: '15%',
-      // eslint-disable-next-line react/display-name
-      render: (text: string, row: iIncomeTree) => {
-        if (row.isEdit) {
-          return (
-            <Input
-              defaultValue={row.serial}
-              addonBefore={row.attribution}
-              size="small"
-              style={{ width: 80 }}
-              onPressEnter={(e: KeyboardEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
-              onBlur={(e: FocusEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
-            />)
-        } else {
-          return <span>{row.code}</span>
-        }
-        // return <span>{row.code}</span>
-      }
-    },
-    {
-      title: '项目名称',
-      dataIndex: 'name',
-      width: '25%',
-      render: (text: any, record: iIncomeTree) => {
-        if (record.isEdit || record.isNew) {
-          const type = record.isEdit ? 'edit' : 'create'
-          return (
-            <Input
-              defaultValue={record.name}
-              size="small"
-              type="text"
-              ref={inputEl}
-              onPressEnter={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
-              onBlur={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
-            />)
-        } else {
-          return <span>{text}</span>
-        }
-      }
-    },
-    {
-      title: '合同名称',
-      dataIndex: 'contractName',
-      width: '15%'
-    },
-    {
-      title: '合同编号',
-      dataIndex: 'contractCode',
-      width: '15%'
-    },
-    {
-      title: '合同金额',
-      dataIndex: 'contractPrice',
-      align: 'right',
-      width: '10%',
-      // eslint-disable-next-line react/display-name
-      render: (text: any, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : ''
-    },
-    {
-      title: '支出金额',
-      dataIndex: 'contractPaid',
-      align: 'right',
-      width: '10%',
-      // eslint-disable-next-line react/display-name
-      render: (text: string, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : ''
-    },
-    {
-      title: '状态',
-      dataIndex: 'contractStatus',
-      width: '10%',
-      // eslint-disable-next-line react/display-name
-      render: (_: any, record: iIncomeTree) => record.contractCode ? <span className={contractConsts[record.contractStatus].className}>{contractConsts[record.contractStatus].text}</span> : ''
-    }
+//   const TableColumns: ColumnsType<iIncomeTree> = [
+//     {
+//       title: '编号',
+//       dataIndex: 'code',
+//       width: '15%',
+//       // eslint-disable-next-line react/display-name
+//       render: (text: string, row: iIncomeTree) => {
+//         if (row.isEdit) {
+//           return (
+//             <Input
+//               defaultValue={row.serial}
+//               addonBefore={row.attribution}
+//               size="small"
+//               style={{ width: 80 }}
+//               onPressEnter={(e: KeyboardEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
+//               onBlur={(e: FocusEvent<HTMLInputElement>) => codeChange(row, e.currentTarget.value)}
+//             />)
+//         } else {
+//           return <span>{row.code}</span>
+//         }
+//         // return <span>{row.code}</span>
+//       }
+//     },
+//     {
+//       title: '项目名称',
+//       dataIndex: 'name',
+//       width: '25%',
+//       render: (text: any, record: iIncomeTree) => {
+//         if (record.isEdit || record.isNew) {
+//           const type = record.isEdit ? 'edit' : 'create'
+//           return (
+//             <Input
+//               defaultValue={record.name}
+//               size="small"
+//               type="text"
+//               ref={inputEl}
+//               onPressEnter={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
+//               onBlur={() => handleNewLabel(type, { id: type === 'edit' ? record.id : record.parentId, bidsectionId: record.bidsectionId })}
+//             />)
+//         } else {
+//           return <span>{text}</span>
+//         }
+//       }
+//     },
+//     {
+//       title: '合同名称',
+//       dataIndex: 'contractName',
+//       width: '15%'
+//     },
+//     {
+//       title: '合同编号',
+//       dataIndex: 'contractCode',
+//       width: '15%'
+//     },
+//     {
+//       title: '合同金额',
+//       dataIndex: 'contractPrice',
+//       align: 'right',
+//       width: '10%',
+//       // eslint-disable-next-line react/display-name
+//       render: (text: any, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : ''
+//     },
+//     {
+//       title: '支出金额',
+//       dataIndex: 'contractPaid',
+//       align: 'right',
+//       width: '10%',
+//       // eslint-disable-next-line react/display-name
+//       render: (text: string, record: iIncomeTree) => record.contractCode ? <span>{formatMoney(text)}</span> : ''
+//     },
+//     {
+//       title: '状态',
+//       dataIndex: 'contractStatus',
+//       width: '10%',
+//       // eslint-disable-next-line react/display-name
+//       render: (_: any, record: iIncomeTree) => record.contractCode ? <span className={contractConsts[record.contractStatus].className}>{contractConsts[record.contractStatus].text}</span> : ''
+//     }
 
-  ]
+//   ]
 
-  // modal 确认 - 回调
-  const handleModalConfirm = async () => {
-    setSectionTemplate({
-      ...sectionTemplate,
-      loading: true
-    })
-    if (!sectionTemplate.template) {
-      setSectionTemplate({
-        ...sectionTemplate,
-        loading: false
-      })
-      return message.error('请选择项目节模板')
-    }
-    const { code = -1 } = await apiSetTemplate(sectionTemplate.template, tenderStore.tender.bidsectionId, 1)
-    if (code === consts.RET_CODE.SUCCESS) {
-      await initData()
-    }
-    setSectionTemplate({
-      ...sectionTemplate,
-      loading: false,
-      isShow: false
-    })
-  }
+//   // modal 确认 - 回调
+//   const handleModalConfirm = async () => {
+//     setSectionTemplate({
+//       ...sectionTemplate,
+//       loading: true
+//     })
+//     if (!sectionTemplate.template) {
+//       setSectionTemplate({
+//         ...sectionTemplate,
+//         loading: false
+//       })
+//       return message.error('请选择项目节模板')
+//     }
+//     const { code = -1 } = await apiSetTemplate(sectionTemplate.template, tenderStore.tender.bidsectionId, 1)
+//     if (code === consts.RET_CODE.SUCCESS) {
+//       await initData()
+//     }
+//     setSectionTemplate({
+//       ...sectionTemplate,
+//       loading: false,
+//       isShow: false
+//     })
+//   }
 
 
-  // modal 关闭 - 回调
-  const handleModalCancel = () => {
-    history.push('/console/contract/content/summary')
-  }
+//   // modal 关闭 - 回调
+//   const handleModalCancel = () => {
+//     history.push('/console/contract/content/summary')
+//   }
 
 
-  // 模板选择radio切换回调
-  const handleRadioEvent = (e: RadioChangeEvent) => {
-    if (e.target.checked) {
-      setSectionTemplate({
-        ...sectionTemplate,
-        template: e.target.value
-      })
-    }
-  }
+//   // 模板选择radio切换回调
+//   const handleRadioEvent = (e: RadioChangeEvent) => {
+//     if (e.target.checked) {
+//       setSectionTemplate({
+//         ...sectionTemplate,
+//         template: e.target.value
+//       })
+//     }
+//   }
 
-  const onClickRow = (record: iIncomeTree) => {
-    return {
-      onClick() {
-        handleRowClick(record.id, record.bidsectionId, record.isEdit, record.isNew)
-      },
-      onDoubleClick() {
-        contractPaidStore.rowChange(row.id)
-      }
-    }
-  }
+//   const onClickRow = (record: iIncomeTree) => {
+//     return {
+//       onClick() {
+//         handleRowClick(record.id, record.bidsectionId, record.isEdit, record.isNew)
+//       },
+//       onDoubleClick() {
+//         contractPaidStore.rowChange(row.id)
+//       }
+//     }
+//   }
 
-  // 行点击回调
-  const handleRowClick = async (id: string, bid: string, isEdit?: boolean, isNew?: boolean) => {
-    if (!isEdit && !isNew) {
-      const { code = -1, section = {}, contract: newContract = {} } = await apiGetExpenditure(id, bid)
-      if (code === consts.RET_CODE.SUCCESS) {
-        setRow(section)
-        contractPaidStore.updateContract(newContract)
-      }
-    }
-  }
-  const handleRowClass = (record: iIncomeTree) => {
-    return record.id === row.id ? 'ant-table-row-selected' : ''
-  }
-  const tabOnClick = (key: string) => {
-    contractPaidStore.changeUpdate(key)
-  }
+//   // 行点击回调
+//   const handleRowClick = async (id: string, bid: string, isEdit?: boolean, isNew?: boolean) => {
+//     if (!isEdit && !isNew) {
+//       const { code = -1, section = {}, contract: newContract = {} } = await apiGetExpenditure(id, bid)
+//       if (code === consts.RET_CODE.SUCCESS) {
+//         setRow(section)
+//         contractPaidStore.updateContract(newContract)
+//       }
+//     }
+//   }
+//   const handleRowClass = (record: iIncomeTree) => {
+//     return record.id === row.id ? 'ant-table-row-selected' : ''
+//   }
+//   const tabOnClick = (key: string) => {
+//     contractPaidStore.changeUpdate(key)
+//   }
 
-  // 阿里oss上传弹窗
-  const onShow = (show: boolean) => setVisible(show)
-  const onCreate = async (fileList: iFile[]) => {
-    const { code = -1 } = await apiSaveFileInfo(fileList, consts.DATA_TYPE.CONTRACT_PAID, row.contractId)
-    if (code === consts.RET_CODE.SUCCESS) {
-      setVisible(false)
-      contractPaidStore.changeUpdate('3')
-    }
-  }
+//   // 阿里oss上传弹窗
+//   const onShow = (show: boolean) => setVisible(show)
+//   const onCreate = async (fileList: iFile[]) => {
+//     const { code = -1 } = await apiSaveFileInfo(fileList, consts.DATA_TYPE.CONTRACT_PAID, row.contractId)
+//     if (code === consts.RET_CODE.SUCCESS) {
+//       setVisible(false)
+//       contractPaidStore.changeUpdate('3')
+//     }
+//   }
 
-  return sectionTemplate.isShow ?
-    <Modal
-      visible={sectionTemplate.isShow}
-      maskClosable={false}
-      title="选择合同项目节模板"
-      okText="确定"
-      confirmLoading={sectionTemplate.loading}
-      cancelText="关闭"
-      onCancel={handleModalCancel}
-      closable={false}
-      keyboard={false}
-      onOk={() => handleModalConfirm()}
-      width='70vw'
-    >
-      <div className={styles.modalWarnText}>默认项目节无法修改,可自行增加维护子节点</div>
-      <div className={styles.modalTemplateContent}>
-        <div className={[ styles.leftTemplate, sectionTemplate.template == '1' ? styles.active : '' ].join(' ')}>
-          <div className="pi-pd-20">
-            <Radio value="1" checked={sectionTemplate.template === '1'} onChange={(e: RadioChangeEvent) => handleRadioEvent(e)}><span className="pi-gray">项目节模板1</span></Radio>
-          </div>
-          <div className={styles.projectTable}>
-            {
-              tempalte.template1?.children && tempalte.template1?.children.length ?
-                <Table
-                  dataSource={tempalte.template1?.children}
-                  columns={modalColumns}
-                  pagination={false}
-                  bordered
-                  scroll={{ y: '300px' }}
-                  rowKey={record => record.id}
-                  defaultExpandAllRows={true}
-                /> : ''
-            }
-          </div>
+//   return sectionTemplate.isShow ?
+//     <Modal
+//       visible={sectionTemplate.isShow}
+//       maskClosable={false}
+//       title="选择合同项目节模板"
+//       okText="确定"
+//       confirmLoading={sectionTemplate.loading}
+//       cancelText="关闭"
+//       onCancel={handleModalCancel}
+//       closable={false}
+//       keyboard={false}
+//       onOk={() => handleModalConfirm()}
+//       width='70vw'
+//     >
+//       <div className={styles.modalWarnText}>默认项目节无法修改,可自行增加维护子节点</div>
+//       <div className={styles.modalTemplateContent}>
+//         <div className={[ styles.leftTemplate, sectionTemplate.template == '1' ? styles.active : '' ].join(' ')}>
+//           <div className="pi-pd-20">
+//             <Radio value="1" checked={sectionTemplate.template === '1'} onChange={(e: RadioChangeEvent) => handleRadioEvent(e)}><span className="pi-gray">项目节模板1</span></Radio>
+//           </div>
+//           <div className={styles.projectTable}>
+//             {
+//               tempalte.template1?.children && tempalte.template1?.children.length ?
+//                 <Table
+//                   dataSource={tempalte.template1?.children}
+//                   columns={modalColumns}
+//                   pagination={false}
+//                   bordered
+//                   scroll={{ y: '300px' }}
+//                   rowKey={record => record.id}
+//                   defaultExpandAllRows={true}
+//                 /> : ''
+//             }
+//           </div>
 
-        </div>
-        <div className={[ styles.rightTemplate, sectionTemplate.template == '2' ? styles.active : '' ].join(' ')}>
-          <div className="pi-pd-20 pi-gray">
-            <Radio value="2" checked={sectionTemplate.template === '2'} onChange={(e: RadioChangeEvent) => handleRadioEvent(e)}><span className="pi-gray">项目节模板2</span></Radio>
-          </div>
-          <div className={styles.projectTable}>
-            {
-              tempalte.template2?.children && tempalte.template2?.children.length ?
-                <Table
-                  dataSource={tempalte.template2?.children}
-                  columns={modalColumns}
-                  bordered
-                  pagination={false}
-                  scroll={{ y: '300px' }}
-                  rowKey={record => record.id}
-                  defaultExpandAllRows={true}
-                />
-                : ''
-            }
+//         </div>
+//         <div className={[ styles.rightTemplate, sectionTemplate.template == '2' ? styles.active : '' ].join(' ')}>
+//           <div className="pi-pd-20 pi-gray">
+//             <Radio value="2" checked={sectionTemplate.template === '2'} onChange={(e: RadioChangeEvent) => handleRadioEvent(e)}><span className="pi-gray">项目节模板2</span></Radio>
+//           </div>
+//           <div className={styles.projectTable}>
+//             {
+//               tempalte.template2?.children && tempalte.template2?.children.length ?
+//                 <Table
+//                   dataSource={tempalte.template2?.children}
+//                   columns={modalColumns}
+//                   bordered
+//                   pagination={false}
+//                   scroll={{ y: '300px' }}
+//                   rowKey={record => record.id}
+//                   defaultExpandAllRows={true}
+//                 />
+//                 : ''
+//             }
 
-          </div>
-        </div>
-      </div>
-    </Modal>
-    :
-    <div className={styles.spreadContent}>
-      <div className={styles.spreadSheets}>
-        {
-          contractPaidStore.showTable ?
-            <Table<iIncomeTree>
-              dataSource={contractPaidStore.tree}
-              columns={TableColumns}
-              bordered
-              pagination={false}
-              rowKey={record => record.id}
-              defaultExpandAllRows={true}
-              onRow={onClickRow}
-              rowClassName={handleRowClass}
-              style={{ height: '100%', overflowY: 'scroll' }}
-            />
-            : ''
-        }
-      </div>
-      <div className={styles.extraControl}>
-        <Tabs
-          type="card"
-          size="small"
-          defaultActiveKey="1"
-          onTabClick={(key: string) => tabOnClick(key)}
-          tabBarExtraContent={{
-            right:
-              <div className="pi-mg-right-5 pi-flex-row">
-                {
-                  contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.checking ?
-                    <>
-                      <Button type="primary" size="small" onClick={() => changeModalType('return')} >添加支出</Button>
-                    </>
-                    : null
-                }
-                {
-                  contractPaidStore.contract.id && contractPaidStore.contract.status !== contractConsts.status.closed ?
-                    <>
-                      <Button type="primary" size="small" onClick={() => changeModalType('update')} className="pi-mg-left-5">编辑合同</Button>
-                      <Button type="primary" size="small" onClick={() => setVisible(true)} className="pi-mg-left-5">上传文件</Button>
-                    </>
-                    : null
-                }
-                {
-                  contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.willClose ?
-                    <Button type="primary" size="small" danger className="pi-mg-left-5" onClick={() => changeModalType('close')}>关闭合同</Button>
-                    : null
-                }
-                {
-                  contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.closed ?
-                    <ZhSubmitButton type="primary" size="small" danger className="pi-mg-left-5" onClick={() => changeModalType('unlock')}>解锁合同</ZhSubmitButton>
-                    : null
-                }
-              </div>
-          }}>
-          <TabPane key="1" tab="合同详情">
-            <Detail {...contractPaidStore.contract} />
-          </TabPane>
-          <TabPane key="2" tab="合同支出">
-            <Receivable updateTreeAndContract={initData}/>
-          </TabPane>
-          <TabPane key="3" tab="合同文件">
-            <File />
-          </TabPane>
-        </Tabs>
-      </div>
-      <OssUploadModal
-        visible={visible}
-        onCancel={() => setVisible(false)}
-        onCreate={onCreate}
-        onShow={onShow}
-      />
-    </div>
-}
+//           </div>
+//         </div>
+//       </div>
+//     </Modal>
+//     :
+//     <div className={styles.spreadContent}>
+//       <div className={styles.spreadSheets}>
+//         {
+//           contractPaidStore.showTable ?
+//             <Table<iIncomeTree>
+//               dataSource={contractPaidStore.tree}
+//               columns={TableColumns}
+//               bordered
+//               pagination={false}
+//               rowKey={record => record.id}
+//               defaultExpandAllRows={true}
+//               onRow={onClickRow}
+//               rowClassName={handleRowClass}
+//               style={{ height: '100%', overflowY: 'scroll' }}
+//             />
+//             : ''
+//         }
+//       </div>
+//       <div className={styles.extraControl}>
+//         <Tabs
+//           type="card"
+//           size="small"
+//           defaultActiveKey="1"
+//           onTabClick={(key: string) => tabOnClick(key)}
+//           tabBarExtraContent={{
+//             right:
+//               <div className="pi-mg-right-5 pi-flex-row">
+//                 {
+//                   contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.checking ?
+//                     <>
+//                       <Button type="primary" size="small" onClick={() => changeModalType('return')} >添加支出</Button>
+//                     </>
+//                     : null
+//                 }
+//                 {
+//                   contractPaidStore.contract.id && contractPaidStore.contract.status !== contractConsts.status.closed ?
+//                     <>
+//                       <Button type="primary" size="small" onClick={() => changeModalType('update')} className="pi-mg-left-5">编辑合同</Button>
+//                       <Button type="primary" size="small" onClick={() => setVisible(true)} className="pi-mg-left-5">上传文件</Button>
+//                     </>
+//                     : null
+//                 }
+//                 {
+//                   contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.willClose ?
+//                     <Button type="primary" size="small" danger className="pi-mg-left-5" onClick={() => changeModalType('close')}>关闭合同</Button>
+//                     : null
+//                 }
+//                 {
+//                   contractPaidStore.contract.id && contractPaidStore.contract.status === contractConsts.status.closed ?
+//                     <ZhSubmitButton type="primary" size="small" danger className="pi-mg-left-5" onClick={() => changeModalType('unlock')}>解锁合同</ZhSubmitButton>
+//                     : null
+//                 }
+//               </div>
+//           }}>
+//           <TabPane key="1" tab="合同详情">
+//             <Detail {...contractPaidStore.contract} />
+//           </TabPane>
+//           <TabPane key="2" tab="合同支出">
+//             <Receivable updateTreeAndContract={initData}/>
+//           </TabPane>
+//           <TabPane key="3" tab="合同文件">
+//             <File />
+//           </TabPane>
+//         </Tabs>
+//       </div>
+//       <OssUploadModal
+//         visible={visible}
+//         onCancel={() => setVisible(false)}
+//         onCreate={onCreate}
+//         onShow={onShow}
+//       />
+//     </div>
+// }
 
-export default observer(GCsheet)
+// export default observer(GCsheet)

+ 67 - 62
src/pages/Contract/Content/Spending/index.tsx

@@ -5,35 +5,37 @@ import RuleModal from '@/components/RuleModal'
 import SvgIcon from '@/components/SvgIcon'
 import { apiSaveRule } from '@/pages/Safe/Content/List/api'
 import { contractPaidStore, tenderStore } from '@/store/mobx'
-import { iIncomeTree, iModalProps } from '@/types/contract'
+import { ContractTree, iModalProps } from '@/types/contract'
 import { contractTreeBaseId } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
 import { Button, message, Tooltip } from 'antd'
 import React, { useState } from 'react'
-import { apiResfulContract, apiResfulContractTree } from './api'
+import { apiResfulContract } from './api'
 import ContractModal from '@/pages/Contract/Content/Income/components/Modal'
-import TableContent from './components/TableContent'
+import TableContent from '../Income/components/TableContent'
 import { RouteComponentProps } from 'react-router'
+import { ContractType } from '@/store/mobx/contractReturn'
+import { apiResfulContractTree } from '../Income/api'
 
 interface iModal {
   visible: boolean
   loading: boolean
 }
 
-const Expenditure:React.FC<RouteComponentProps> = ({ history }) => {
+const Expenditure: React.FC<RouteComponentProps> = ({ history }) => {
   const [ modalObj, setModalObj ] = useState<iModalProps>({
     type: '',
     visible: false,
     confirmLoading: false,
     contractType: 'spending'
   })
-  const [ row, setRow ] = useState<iIncomeTree>({
+  const [ row, setRow ] = useState<ContractTree>({
     elderBrother: false,
     isEnd: false,
     attribsortution: 0,
     attribution: '',
     bidsectionId: '',
-    children: undefined,
+    children: [],
     code: '',
     contractCode: '',
     contractId: '',
@@ -84,11 +86,8 @@ const Expenditure:React.FC<RouteComponentProps> = ({ history }) => {
     })
   }
   const treeResfulApiHandler = async (type: string, payload: any) => {
-    if (type === 'add') {
-      return contractPaidStore.addRowTree(payload.id)
-    }
-    const { code = -1, section = {} } = await apiResfulContractTree(type, payload)
-    if ( code === consts.RET_CODE.SUCCESS) {
+    const { code = -1, section = {} } = await apiResfulContractTree(type, payload, consts.CONTRACT_TREE.PAID)
+    if (code === consts.RET_CODE.SUCCESS) {
       contractPaidStore.resetTree(tenderStore.bid)
       if (type !== 'add' && type !== 'del') {
         setRow({ ...row, ...section })
@@ -123,51 +122,51 @@ const Expenditure:React.FC<RouteComponentProps> = ({ history }) => {
           <div className="pi-flex-row">
             {
               row.id ?
-              <>
-                <Tooltip title="添加子项">
-                  <Button type="text" icon={<SvgIcon type="xxh-plus" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('add', { id: row.id, bidsectionId: row.bidsectionId })} />
-                </Tooltip>
-                {
-                  !row.children?.length ?
-                  <Tooltip title="删除">
-                    <Button type="text" icon={<SvgIcon type="xxh-times" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('del', { id: row.id, bidsectionId: row.bidsectionId })} />
-                  </Tooltip>
-                  : <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-times" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
-                }
-                {
-                  row.parentId && row.parentId !== contractTreeBaseId ?
-                  <Tooltip title="升级">
-                    <Button type="text" icon={<SvgIcon type="xxh-arrow-left" style={{ color: '#007bff', fontSize: 12 }} onClick={() => treeResfulApiHandler('depth', { id: row.id, bidsectionId: row.bidsectionId, operation: 'upDepth' })} />} />
-                  </Tooltip>
-                  :
-                  <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-left" style={{ color: '#9a9a9a', fontSize: 12 }}/></span>
-                }
-                {
-                  row.elderBrother ?
-                  <Tooltip title="降级">
-                    <Button type="text" icon={<SvgIcon type="xxh-arrow-right" style={{ color: '#007bff', fontSize: 12 }}/>} onClick={() => treeResfulApiHandler('depth', { id: row.id, bidsectionId: row.bidsectionId, operation: 'downDepth' })}  />
-                  </Tooltip>
-                  :
-                  <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-right" style={{ color: '#9a9a9a', fontSize: 12 }}/></span>
-                }
-                {
-                  row.elderBrother ?
-                  <Tooltip title="上移">
-                    <Button type="text" icon={<SvgIcon type="xxh-arrow-up" style={{ color: '#007bff', fontSize: 12 }}/>} onClick={() => treeResfulApiHandler('serial', { id: row.id, bidsectionId: row.bidsectionId, operation: 'upSerial' })}  disabled={!row.elderBrother} />
-                  </Tooltip>
-                  :
-                  <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-up" style={{ color: '#9a9a9a', fontSize: 12 }}/></span>
-                }
-                {
-                  !row.isEnd ?
-                  <Tooltip title="下移">
-                    <Button type="text" icon={<SvgIcon type="xxh-arrow-down" style={{ color: '#007bff', fontSize: 12 }}/>} onClick={() => treeResfulApiHandler('serial', { id: row.id, bidsectionId: row.bidsectionId, operation: 'downSerial' })} disabled={row.isEnd} />
+                <>
+                  <Tooltip title="添加子项">
+                    <Button type="text" icon={<SvgIcon type="xxh-plus" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('add', { id: row.id, bidsectionId: row.bidsectionId })} />
                   </Tooltip>
-                  :
-                  <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-down" style={{ color: '#9a9a9a', fontSize: 12 }}/></span>
-                }
-              </>
-              : ''
+                  {
+                    !row.children?.length ?
+                      <Tooltip title="删除">
+                        <Button type="text" icon={<SvgIcon type="xxh-times" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('del', { id: row.id, bidsectionId: row.bidsectionId })} />
+                      </Tooltip>
+                      : <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-times" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
+                  }
+                  {
+                    row.parentId && row.parentId !== contractTreeBaseId ?
+                      <Tooltip title="升级">
+                        <Button type="text" icon={<SvgIcon type="xxh-arrow-left" style={{ color: '#007bff', fontSize: 12 }} onClick={() => treeResfulApiHandler('depth', { id: row.id, bidsectionId: row.bidsectionId, operation: 'upDepth' })} />} />
+                      </Tooltip>
+                      :
+                      <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-left" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
+                  }
+                  {
+                    row.elderBrother ?
+                      <Tooltip title="降级">
+                        <Button type="text" icon={<SvgIcon type="xxh-arrow-right" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('depth', { id: row.id, bidsectionId: row.bidsectionId, operation: 'downDepth' })} />
+                      </Tooltip>
+                      :
+                      <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-right" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
+                  }
+                  {
+                    row.elderBrother ?
+                      <Tooltip title="上移">
+                        <Button type="text" icon={<SvgIcon type="xxh-arrow-up" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('serial', { id: row.id, bidsectionId: row.bidsectionId, operation: 'upSerial' })} disabled={!row.elderBrother} />
+                      </Tooltip>
+                      :
+                      <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-up" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
+                  }
+                  {
+                    !row.isEnd ?
+                      <Tooltip title="下移">
+                        <Button type="text" icon={<SvgIcon type="xxh-arrow-down" style={{ color: '#007bff', fontSize: 12 }} />} onClick={() => treeResfulApiHandler('serial', { id: row.id, bidsectionId: row.bidsectionId, operation: 'downSerial' })} disabled={row.isEnd} />
+                      </Tooltip>
+                      :
+                      <span className="pi-width-32 pi-height-32 pi-pd-tb-4 pi-flex-row-center"><SvgIcon type="xxh-arrow-down" style={{ color: '#9a9a9a', fontSize: 12 }} /></span>
+                  }
+                </>
+                : ''
             }
           </div>
         </Slot>
@@ -175,14 +174,20 @@ const Expenditure:React.FC<RouteComponentProps> = ({ history }) => {
           <Button type="ghost" size="small" icon={<SvgIcon type="xxh-cog" />} className="pi-mg-right-3" style={{ color: '#007bff' }} onClick={() => setRuleModal({ ...ruleModal, visible: true })}>设置</Button>
           {
             showCBtn ?
-            <Authorization type="contract" auth="add">
-              <Button type="primary" size="small" onClick={() => setModalObj({ ...modalObj, type: 'create', visible: true })}>新建支出合同</Button>
-            </Authorization>
-            : ""
+              <Authorization type="contract" auth="add">
+                <Button type="primary" size="small" onClick={() => setModalObj({ ...modalObj, type: 'create', visible: true })}>新建支出合同</Button>
+              </Authorization>
+              : ""
           }
         </Slot>
       </Header>
-      <TableContent changeModalType={changeModalType} row={row} setRow={(record: iIncomeTree) => setRow({ ...row, ...record })} history={history}/>
+      <TableContent
+        changeModalType={changeModalType}
+        row={row}
+        setRow={(record: ContractTree) => setRow({ ...row, ...record })}
+        history={history}
+        type={ContractType.EXPENDITURE}
+      />
       <RuleModal
         type={consts.RULE.CONTRACT_PAID}
         title="合同管理编号设置"
@@ -190,8 +195,8 @@ const Expenditure:React.FC<RouteComponentProps> = ({ history }) => {
         onCreate={onRuleCreate}
         loading={ruleModal.loading}
         onCancel={() => setRuleModal({ ...ruleModal, visible: false })}
-       />
-      <ContractModal row={row} modalObj={modalObj} onConfirm={onCreate} onCancel={ () => setModalObj({ ...modalObj, visible: false })} reload={(type) => toggleReloadModal(type)} />
+      />
+      <ContractModal row={row} modalObj={modalObj} onConfirm={onCreate} onCancel={() => setModalObj({ ...modalObj, visible: false })} reload={(type) => toggleReloadModal(type)} />
     </div>
   )
 }

+ 4 - 4
src/pages/Contract/List/index.tsx

@@ -2,7 +2,7 @@ import Header from '@/components/Header'
 import Slot from '@/components/Header/slot'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
-import { ContractTree } from '@/types/contract'
+import { ContractListTree } from '@/types/contract'
 import consts from '@/utils/consts'
 import { CaretDownOutlined } from '@ant-design/icons'
 import { useAutoTable, useContractTree, useTableExpand } from '@/utils/common/customHooks'
@@ -38,13 +38,13 @@ const List: React.FC<{}> = () => {
     handleIntoBidsection("contract", id, name)
   }
 
-  const columns: ColumnsType<ContractTree> = [
+  const columns: ColumnsType<ContractListTree> = [
     {
       title: '名称',
       dataIndex: 'name',
       key: 'name',
       width: '25%',
-      render: (text: string, record: ContractTree) => {
+      render: (text: string, record: ContractListTree) => {
         if (record.isfolder) {
           return (
             <div className="pi-vertical-baseline">
@@ -129,7 +129,7 @@ const List: React.FC<{}> = () => {
         </Slot>
       </Header>
       <div className={[ styles.tableContent, 'wrap-content' ].join(' ')}>
-        <Table<ContractTree>
+        <Table<ContractListTree>
           columns={columns}
           loading={loading}
           dataSource={tree.children}

+ 4 - 4
src/pages/Quality/List/index.tsx

@@ -2,7 +2,7 @@ import Header from '@/components/Header'
 import Slot from '@/components/Header/slot'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
-import { ContractTree } from '@/types/contract'
+import { ContractListTree } from '@/types/contract'
 import { apiContractList } from '@/utils/common/api'
 import { useAutoTable, useContractTree, useTableExpand } from '@/utils/common/customHooks'
 import consts from '@/utils/consts'
@@ -37,13 +37,13 @@ const List: React.FC<RouteComponentProps> = () => {
     handleIntoBidsection("quality", id, name)
 
   }
-  const columns: ColumnsType<ContractTree> = [
+  const columns: ColumnsType<ContractListTree> = [
     {
       title: '名称',
       dataIndex: 'name',
       key: 'name',
       width: '40%',
-      render: (text: string, record: ContractTree) => {
+      render: (text: string, record: ContractListTree) => {
         if (record.isfolder) {
           return (
             <div className="pi-vertical-baseline">
@@ -111,7 +111,7 @@ const List: React.FC<RouteComponentProps> = () => {
         </Slot>
       </Header>
       <div className={[ styles.tableContent, 'wrap-content' ].join(' ')}>
-        <Table<ContractTree>
+        <Table<ContractListTree>
           loading={loading}
           columns={columns}
           dataSource={tree.children}

+ 4 - 4
src/pages/Safe/List/index.tsx

@@ -3,7 +3,7 @@ import { useAutoTable, useContractTree, useTableExpand } from '@/utils/common/cu
 import Slot from '@/components/Header/slot'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
-import { ContractTree } from '@/types/contract'
+import { ContractListTree } from '@/types/contract'
 import consts from '@/utils/consts'
 import { CaretDownOutlined } from '@ant-design/icons'
 import { Button, Dropdown, Menu, Table } from 'antd'
@@ -36,13 +36,13 @@ const List: React.FC<RouteComponentProps> = () => {
     tenderStore.saveTenderInfo({ bidsectionId: id, name })
     handleIntoBidsection("safe", id, name)
   }
-  const columns: ColumnsType<ContractTree> = [
+  const columns: ColumnsType<ContractListTree> = [
     {
       title: '名称',
       dataIndex: 'name',
       key: 'name',
       width: '40%',
-      render: (text: string, record: ContractTree) => {
+      render: (text: string, record: ContractListTree) => {
         if (record.isfolder) {
           return (
             <div className="pi-vertical-baseline">
@@ -110,7 +110,7 @@ const List: React.FC<RouteComponentProps> = () => {
         </Slot>
       </Header>
       <div className={[ styles.tableContent, 'wrap-content' ].join(' ')}>
-        <Table<ContractTree>
+        <Table<ContractListTree>
           columns={columns}
           loading={loading}
           dataSource={tree.children}

+ 7 - 6
src/store/mobx/contractPaid/index.ts

@@ -1,11 +1,12 @@
-import { apiContractExpenditure } from "@/pages/Contract/Content/Spending/components/TableContent/api"
-import { iContractState, iIncomeTree } from "@/types/contract"
+import { apiContractTree } from "@/pages/Contract/Content/Income/components/Modal/api"
+import { iContractState, ContractTree } from "@/types/contract"
 import consts from "@/utils/consts"
 import { action, computed, observable } from "mobx"
-import { lookupNode, nodeCheck } from "../contractReturn"
+import { ContractType, lookupNode, nodeCheck } from "../contractReturn"
+
 class Contract {
 
-  @observable tree: iIncomeTree[] = []
+  @observable tree: ContractTree[] = []
   @observable contract: iContractState = {
     bidsectionId: "",
     code: "",
@@ -34,12 +35,12 @@ class Contract {
     this.shouldUpdate = i
 
   }
-  @action updateTree(tree: iIncomeTree[]) {
+  @action updateTree(tree: ContractTree[]) {
     this.tree = tree
   }
 
   @action resetTree(id: string) {
-    apiContractExpenditure(id).then(({ code = -1, sectionTree = {} }) => {
+    apiContractTree(ContractType.EXPENDITURE, id).then(({ code = -1, sectionTree = {} }) => {
       if (code === consts.RET_CODE.SUCCESS && Object.keys(sectionTree).length) {
         this.tree = sectionTree.children
       }

+ 16 - 11
src/store/mobx/contractReturn/index.ts

@@ -1,5 +1,5 @@
-import { apiContractIncome } from "@/pages/Contract/Content/Income/components/Modal/api"
-import { iContractState, iIncomeTree } from "@/types/contract"
+import { apiContractTree } from "@/pages/Contract/Content/Income/components/Modal/api"
+import { iContractState, ContractTree } from "@/types/contract"
 import consts from "@/utils/consts"
 import { action, computed, observable } from "mobx"
 const initData = [ {
@@ -27,9 +27,14 @@ const initData = [ {
   serial: 0,
   templateNumber: 0
 } ]
+
+export enum ContractType {
+  INCOME = 'income',
+  EXPENDITURE = 'expenditure'
+}
 class Contract {
 
-  @observable tree: iIncomeTree[] = []
+  @observable tree: ContractTree[] = []
   @observable contract: iContractState = {
     bidsectionId: "",
     code: "",
@@ -58,12 +63,12 @@ class Contract {
     this.shouldUpdate = i
 
   }
-  @action updateTree(tree: iIncomeTree[]) {
+  @action updateTree(tree: ContractTree[]) {
     this.tree = tree
   }
 
   @action resetTree(id: string) {
-    apiContractIncome(id).then(({ code = -1, sectionTree = {} }) => {
+    apiContractTree(ContractType.INCOME, id).then(({ code = -1, sectionTree = {} }) => {
       if (code === consts.RET_CODE.SUCCESS && Object.keys(sectionTree).length) {
         this.tree = sectionTree.children
       }
@@ -90,14 +95,14 @@ class Contract {
   }
 }
 
-export function lookupNode(id: string, tree: iIncomeTree[]) {
-  return tree.map((item:iIncomeTree) => {
+export function lookupNode(id: string, tree: ContractTree[]) {
+  return tree.map((item:ContractTree) => {
     item.isEdit = false
     if (item.id === id) {
       if (Array.isArray(item.children)) {
-        item.children.push({ ...initData[0], isNew: true, code: item.code + `-${item.children.length + 1 }`, parentId: item.id, bidsectionId: item.bidsectionId, attribution: item.code + '-', serial: 1 })
+        item.children.push({ ...initData[0], isNew: true, code: item.code + `-${item.children.length + 1 }`, parentId: item.id, bidsectionId: item.bidsectionId, attribution: item.code + '-', serial: 1, children: [] })
       } else {
-        item.children = [ { ...initData[0], isNew: true, code: item.code + '-1', parentId: item.id, bidsectionId: item.bidsectionId, attribution: item.code + '-', serial: 1 } ]
+        item.children = [ { ...initData[0], isNew: true, code: item.code + '-1', parentId: item.id, bidsectionId: item.bidsectionId, attribution: item.code + '-', serial: 1, children: [] } ]
       }
       return item
     } else if(item.children && item.children.length) {
@@ -108,8 +113,8 @@ export function lookupNode(id: string, tree: iIncomeTree[]) {
 }
 
 // 项目节被选中更改isEdit的值
-export function nodeCheck(id: string, tree: iIncomeTree[]) {
-  return tree.map((item: iIncomeTree) => {
+export function nodeCheck(id: string, tree: ContractTree[]) {
+  return tree.map((item: ContractTree) => {
     item.isEdit = false
     if (item.id === id) {
       item.isEdit = true

+ 4 - 4
src/types/contract.d.ts

@@ -1,6 +1,6 @@
-export interface ContractTree {
+export interface ContractListTree {
   bidsectionId: string
-  children: ContractTree[] | undefined
+  children: ContractListTree[]
   childsTotal: number
   contracts: number
   contractsIncome: string
@@ -28,13 +28,13 @@ export interface ContractTree {
   safeTotal: number
 }
 
-export interface iIncomeTree {
+export interface ContractTree {
   elderBrother: boolean
   isEnd: boolean
   attribsortution: number
   attribution: string
   bidsectionId: string
-  children: iIncomeTree[] | undefined
+  children: ContractTree[]
   code: string
   contractCode: string
   contractId: string

+ 9 - 9
src/utils/common/customHooks.ts

@@ -1,11 +1,11 @@
 /** 自定义hooks库 */
 import { useState, useEffect } from 'react'
-import { ContractTree } from '@/types/contract'
+import { ContractListTree } from '@/types/contract'
 import { ListModal } from '@/types/safe'
 
 /** 合同树的自定义hook */
-export const useContractTree = (): [ContractTree, (newTree: ContractTree) => void] => {
-  const [ tree, setTree ] = useState<ContractTree>({
+export const useContractTree = (): [ContractListTree, (newTree: ContractListTree) => void] => {
+  const [ tree, setTree ] = useState<ContractListTree>({
     bidsectionId: '',
     children: [],
     childsTotal: 0,
@@ -34,21 +34,21 @@ export const useContractTree = (): [ContractTree, (newTree: ContractTree) => voi
     safeRectificationFinish: 0,
     safeTotal: 0
   })
-  const onChange = (newTree: ContractTree) => {
+  const onChange = (newTree: ContractListTree) => {
     setTree({ ...tree, ...newTree })
   }
   return [ tree, onChange ]
 }
 
 /** 树列表展开收起自定义hook */
-export const useTableExpand = (tree: ContractTree): [string[], (expanded: boolean, record?: ContractTree) => void] => {
+export const useTableExpand = (tree: ContractListTree): [string[], (expanded: boolean, record?: ContractListTree) => void] => {
   const [ ids, setIds ] = useState<Array<string>>([])
   useEffect(() => {
-    const newIds = expandTree(tree.children as ContractTree[])
+    const newIds = expandTree(tree.children as ContractListTree[])
 
     setIds(newIds)
   }, [ tree ])
-  const onChange = (expanded: boolean, record?: ContractTree) => {
+  const onChange = (expanded: boolean, record?: ContractListTree) => {
     // 点击图标的展开收起
     if (record) {
       if (expanded) {
@@ -68,10 +68,10 @@ export const useTableExpand = (tree: ContractTree): [string[], (expanded: boolea
       }
     }
   }
-  function expandTree(data: ContractTree[]): string[] {
+  function expandTree(data: ContractListTree[]): string[] {
     let idArr: Array<string> = []
 
-    data.forEach((item: ContractTree) => {
+    data.forEach((item: ContractListTree) => {
       if (!!item.isfolder && item.children?.length) {
         idArr.push(item.id)
         const childIds = expandTree(item.children)