Sfoglia il codice sorgente

feat: 收入合同tabs页面切换优化。

lanjianrong 4 anni fa
parent
commit
b0d145b301

+ 119 - 5
src/components/FileModal/index.tsx

@@ -1,16 +1,24 @@
 import SvgIcon from '@/components/SvgIcon'
+import { apiSaveFileInfo } from '@/pages/Safe/Content/Info/Detail/api'
+import { iFile, iOSSData } from '@/types/file'
 import consts from '@/utils/consts'
 import { dayjsFomrat } from '@/utils/util'
-import { Modal, Table } from 'antd'
+import { InboxOutlined } from '@ant-design/icons'
+import { message, Modal, Table, Upload } from 'antd'
 import { ColumnsType } from 'antd/lib/table'
+import { UploadChangeParam } from 'antd/lib/upload'
+import { UploadFile } from 'antd/lib/upload/interface'
 import React, { useEffect, useState } from 'react'
 import { ZhCloseButton } from '../Button'
+import { getSignature } from '../OssUpload/ali-oss'
 import { apiGetFileList } from './api'
+const { Dragger } = Upload
 interface iFileModalProps {
   dataId: string
   visible: boolean
   dataType: number
   onCancel: () => void
+  showUpload?: boolean
 }
 interface iFileModalState {
   id: string
@@ -20,11 +28,22 @@ interface iFileModalState {
   createTime: string
 }
 export default function FileModal(props: iFileModalProps) {
-  const { dataId = "", visible = false, onCancel, dataType = 1 } = props
+  const { dataId = "", visible = false, onCancel, dataType = 1, showUpload = false } = props
   const [ files, setFiles ] = useState<Array<iFileModalState>>([])
   const [ total, setTotal ] = useState<number>(0)
+  const [ OSSData, setOssData ] = useState<iOSSData>({
+    dir: '',
+    expire: '',
+    host: '',
+    accessId: '',
+    policy: '',
+    signature: ''
+  })
   useEffect(() => {
-    visible && initData()
+    if (props.visible) {
+      initOssData()
+      initData()
+    }
   }, [ visible ])
   const initData = async(pageNo: number = 1, pageSize: number = consts.PAGE_SIZE) => {
     // const { current: pageNo = 1, pageSize = consts.PAGESIZE } = pagination || {}
@@ -34,9 +53,78 @@ export default function FileModal(props: iFileModalProps) {
       setTotal(total)
     }
   }
-  // const onTableChange = (pagination: TablePaginationConfig) => {
+  // 上传文件改变时的状态
+  const onChange = async (info: UploadChangeParam) => {
+    const { status } = info.file
+    if (status !== 'uploading') {
+      // console.log(info.file, info.fileList)
+    }
+    if (status === 'done') {
+      // message.success(`${info.file.name} 上传成功!`)
+      const newFileList: iFile[] = [
+        {
+          createTime: new Date(),
+          filepath: info.file.url,
+          filename: info.file.name
+        }
+      ]
+      const { code = -1 } = await apiSaveFileInfo(newFileList, consts.DATA_TYPE.RETURN, dataId)
+      if (code === consts.RET_CODE.SUCCESS) {
+        initData()
+      }
+    } else if (status === 'error') {
+      message.error(`${info.file.name} 上传失败!`)
+    }
+  }
+  // 初始化、获取签名
+  const initOssData = async () => {
+    try {
+      const { code = -1, data = {} } = await getSignature()
+      if (code === consts.RET_CODE.SUCCESS) {
+        setOssData({ ...OSSData, ...data })
+      } else {
+        message.error("获取签名失败,请联系管理员!")
+
+      }
+    } catch (error) {
+      message.error(error)
+    }
+  }
+
+  // 额外参数、oss签名
+  const getExtraData = (file: UploadFile) => {
+    return {
+      key: file.url,
+      OSSAccessKeyId: OSSData.accessId,
+      policy: OSSData.policy,
+      Signature: OSSData.signature
+    }
+  }
 
-  // }
+  const transformFile = (file: any) => {
+    file.url = OSSData.dir + file.name
+    return file
+  }
+  // 上传前的回调
+  const beforeUpload = (file: any) => {
+    const { UPLOAD_LIMIT } = consts
+    const isLt30M = file.size / 1024 / 1024 < UPLOAD_LIMIT
+    if (!isLt30M) {
+      message.error("上传附件大小限制在30MB!")
+      return false
+    }
+    const expire = parseInt(OSSData.expire) * 1000
+    if (expire < Date.now()) {
+      initOssData()
+      return false
+    }
+    return true
+  }
+
+  // 移除文件
+  const onRemove = (file: any) => {
+    console.log(file)
+  }
   const columns: ColumnsType<iFileModalState> = [
     {
       title: "文件名",
@@ -81,6 +169,32 @@ export default function FileModal(props: iFileModalProps) {
       onCancel={onCancel}
       footer={<ZhCloseButton onClick={() => onCancel()} size="small">关闭</ZhCloseButton>}
       >
+        {
+          showUpload ?
+          <div className="pi-mg-bottom-10">
+            <Dragger
+              name="file"
+              action={OSSData.host}
+              multiple={true}
+              onChange={onChange}
+              beforeUpload={beforeUpload}
+              data={getExtraData}
+              transformFile={transformFile}
+              showUploadList={false}
+              // accept={consts.UPLOAD_WHITE}
+              onRemove={onRemove}
+            >
+                <p className="ant-upload-drag-icon">
+                <InboxOutlined />
+                </p>
+                <p className="ant-upload-text">把文件拖入指定区域,完成上传,同样支持点击上传。</p>
+                <p className="ant-upload-hint">
+                  支持单文件/多文件上传。附件大小最大为30MB!
+                </p>
+            </Dragger>
+          </div>
+          : ''
+        }
       <Table
         dataSource={files}
         columns={columns}

+ 2 - 16
src/components/OssUpload/index.tsx

@@ -1,5 +1,5 @@
 import { ZhCloseButton } from '@/components/Button'
-import { iFile } from '@/types/file'
+import { iFile, iOSSData } from '@/types/file'
 import consts from '@/utils/consts'
 import { InboxOutlined } from '@ant-design/icons'
 import { Button, message, Modal, Upload } from 'antd'
@@ -10,27 +10,13 @@ import React, { useEffect, useState } from 'react'
 import { getSignature } from './ali-oss'
 const { Dragger } = Upload
 
-interface iOSSData {
-  dir: string;
-  expire: string;
-  host: string;
-  accessId: string;
-  policy: string;
-  signature: string;
-}
 interface iUploadModalProps extends ModalProps {
   onCreate: (files: iFile[]) => void
   onShow: (visible: boolean) => void
 }
 const UploadModal:React.FC<iUploadModalProps> = (props) => {
   const { onCreate, onShow, ...otherProps } = props
-  const [ files, setFiles ] = useState<iFile[]>([
-    {
-      createTime: new Date(),
-      filename: '',
-      filepath: ''
-    }
-  ])
+  const [ files, setFiles ] = useState<iFile[]>([])
   const [ fileList, setFileList ] = useState<Array<UploadFile>>([])
   const [ OSSData, setOssData ] = useState<iOSSData>({
     dir: '',

+ 29 - 8
src/pages/Contract/Content/Income/components/Tabs/Receivable/index.tsx

@@ -1,11 +1,13 @@
 import DatePicker from '@/components/DatePicker'
+import FileModal from '@/components/FileModal'
 import { contractStore } from '@/store/mobx'
+import { iFileModal } from '@/types/file'
 import consts from '@/utils/consts'
 import { dayjsFomrat } from '@/utils/util'
 import { DisconnectOutlined } from '@ant-design/icons'
 import { Form, Input, Popconfirm, Table } from 'antd'
 import locale from 'antd/es/date-picker/locale/zh_CN'
-import Modal from 'antd/lib/modal/Modal'
+import { observer } from 'mobx-react'
 import React, { useEffect, useState } from 'react'
 import { apiGetReturns } from './api'
 
@@ -60,15 +62,28 @@ const EditableCell: React.FC<EditableCellProps> = ({
 const Receivable:React.FC<{}> = () => {
   const [ form ] = Form.useForm()
   const [ data, setData ] = useState<Array<iReceivableState>>([])
-  const [ visible, setVisible ] = useState<boolean>(false)
+  const [ id, setId ] = useState<string>('')
+  const [ fileModal, setFileModal ] = useState<iFileModal>({
+    visible: false,
+    dataType: consts.DATA_TYPE.RETURN,
+    dataId: ''
+  })
   const [ editingKey, setEditingKey ] = useState<string>('')
+
   const delConfirm = (key: string) => {
     console.log(key)
   }
 
   useEffect(() => {
-    if (contractStore.contract.id || contractStore.shouldUpdate && contractStore.shouldUpdate === 'return') {
-      initData()
+    if (contractStore.contract.id) {
+      if (contractStore.contract.id !== id) {
+        setId(contractStore.contract.id)
+        initData()
+      } else if (contractStore.shouldUpdate && contractStore.shouldUpdate === '2') {
+        initData()
+        contractStore.shouldUpdate && contractStore.changeUpdate('')
+      }
+
     }
   }, [ contractStore.contract.id, contractStore.shouldUpdate ])
   const initData = async() => {
@@ -155,9 +170,9 @@ const Receivable:React.FC<{}> = () => {
     },
     {
       title: '附件',
-      dataIndex: 'annexes',
+      dataIndex: 'fileCounts',
       // eslint-disable-next-line react/display-name
-      render: (text: number) => <span className="pi-pointer" onClick={() => setVisible(true)}><DisconnectOutlined /> {text}</span>
+      render: (text: number, record: iReceivableState) => <span className="pi-pointer" onClick={() => setFileModal({ ...fileModal, dataId: record.id, visible: true })}><DisconnectOutlined /> {text}</span>
     },
     {
       title: '操作',
@@ -218,8 +233,14 @@ const Receivable:React.FC<{}> = () => {
           >
         </Table>
       </Form>
-      <Modal visible={visible} okText="确认" cancelText="关闭" title="附件" onCancel={() => setVisible(false)}></Modal>
+      <FileModal
+        visible={fileModal.visible}
+        dataType={fileModal.dataType}
+        dataId={fileModal.dataId}
+        onCancel={() => setFileModal({ ...fileModal, visible: false })}
+        showUpload={true}
+      ></FileModal>
     </>
   )
 }
-export default Receivable
+export default observer(Receivable)

+ 2 - 5
src/pages/Safe/Content/List/index.tsx

@@ -4,6 +4,7 @@ import Slot from '@/components/Header/slot'
 import RuleModal from '@/components/RuleModal'
 import SvgIcon from '@/components/SvgIcon'
 import { tenderStore } from '@/store/mobx'
+import { iFileModal } from '@/types/file'
 import { iCreateSafe } from '@/types/safe'
 import { safeStatus } from '@/utils/common/constStatus'
 import consts from '@/utils/consts'
@@ -32,11 +33,7 @@ interface iModal {
   loading: boolean
 }
 
-interface iFileModal {
-  visible: boolean
-  dataType: number
-  dataId: string
-}
+
 const SafeList:React.FC<{}> =() => {
   const [ ruleModal, setRuleModal ] = useState<iModal>({
     visible: false,

+ 14 - 0
src/types/file.d.ts

@@ -3,3 +3,17 @@ export interface iFile {
   filepath?: string
   filename?: string
 }
+
+export interface iFileModal {
+  visible: boolean
+  dataType: number
+  dataId: string
+}
+export interface iOSSData {
+  dir: string;
+  expire: string;
+  host: string;
+  accessId: string;
+  policy: string;
+  signature: string;
+}

+ 1 - 1
src/utils/consts.ts

@@ -13,7 +13,7 @@ export default {
   RULE: { SAFE: 'safeRule', QUALITY: 'qualityRule', CONTRACT: 'contractRule' }, // 编号规则弹窗常量
   UPLOAD_WHITE: "'.json', '.txt','.xls', '.xlsx','.doc', '.docx','.pdf','.ppt', '.pptx','.png', '.jpg', '.jpeg', '.gif', '.bmp', '.cad', '.dwg','.zip', '.rar', '.7z'", // 上传类型-白名单
   UPLOAD_LIMIT: 30, // 上传限制30MB
-  DATA_TYPE: { CONTRACT: 1, QUALITY: 2, SAFE: 3 }, // 附件类型
+  DATA_TYPE: { RETURN: 1, QUALITY: 2, SAFE: 3, CONTRACT: 4 }, // 附件类型
   PAGE_SIZE: 10, // 默认页数
   OSS_PATH: {
     REVIEW: 'https://file-upload.6jlzf.cn/',