import SvgIcon from '@/components/SvgIcon' import { iFile, iOSSData } from '@/types/file' import { apiGetFileList, apiSaveFileInfo, getSignature } from '@/utils/common/api' import consts from '@/utils/consts' import { dayjsFormat } from '@/utils/util' 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' const { Dragger } = Upload interface iFileModalProps { dataId: string visible: boolean dataType: number onCancel: () => void showUpload?: boolean uploadCallBack?: () => void } interface iFileModalState { id: string filename: string filepath: string accountName: string createTime: string } interface FileTable { data: iFileModalState[] total: number } export default function FileModal(props: iFileModalProps) { const { dataId = "", visible = false, onCancel, dataType = 1, showUpload = false, uploadCallBack } = props const [ files, setFiles ] = useState({ data: [], total: 0 }) const [ fileList, setFileList ] = useState([]) const [ OSSData, setOssData ] = useState({ dir: '', expire: '', host: '', accessId: '', policy: '', signature: '' }) const [ uidArr, setUidArr ] = useState([]) useEffect(() => { if (props.visible) { initOssData() initData() } }, [ visible ]) const initData = async (pageNo: number = 1, pageSize: number = consts.PAGE_SIZE) => { const { code = -1, data = [], total = 0 } = await apiGetFileList(dataType, dataId, pageNo, pageSize) if (code === consts.RET_CODE.SUCCESS) { setFiles({ ...files, data, total }) setFileList([]) setUidArr([]) } } const saveFiles = async (newFileList: iFile[]) => { const { code = -1 } = await apiSaveFileInfo(newFileList, dataType, dataId) if (code === consts.RET_CODE.SUCCESS) { initData() uploadCallBack && uploadCallBack() } } useEffect(() => { if (uidArr.length && uidArr.length === fileList.length) { saveFiles(fileList.filter(file => file.status === 'done').map(file => ({ createTime: new Date(), filepath: file.url, filename: file.name }))) } }, [ uidArr ]) // 上传文件改变时的状态 const onChange = async (info: UploadChangeParam) => { const { status } = info.file // if (status !== 'uploading') { // } if (status === 'done') { setUidArr([ ...uidArr, info.file.uid ]) } else if (status === 'error') { // message.error(`${info.file.name} 上传失败`) } setFileList(info.fileList) } // 初始化、获取签名 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 beforeUpload = async (file: any) => { const { UPLOAD_LIMIT } = consts const isLt30M = file.size / 1024 / 1024 < UPLOAD_LIMIT if (!isLt30M) { file.status = 'error' message.error("上传附件大小限制在30MB") return false } const expire = parseInt(OSSData.expire) * 1000 if (expire < Date.now()) { try { await initOssData() } catch (error) { file.status = 'error' return false } } const reg = new RegExp(consts.UPLOAD_WHITE) if (!reg.test(file.name)) { file.status = 'error' message.error('不支持该类型文件') return false } file.url = OSSData.dir + file.name return Promise.resolve(file) } // 移除文件 const onRemove = (file: any) => { console.log(file) } const columns: ColumnsType = [ { title: "文件名", dataIndex: "filepath", width: 287, onCell: () => { return { style: { maxWidth: 287, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', cursor: 'pointer' } } }, // eslint-disable-next-line react/display-name render: (path: string, record: iFileModalState) => {record.filename} }, { title: "上传人", dataIndex: "accountName" }, { title: "上传时间", dataIndex: "createTime", // eslint-disable-next-line react/display-name render: text => {dayjsFormat(text, "YYYY-MM-DD")} }, { title: "操作", align: "center", // eslint-disable-next-line react/display-name render: (_, record) => } ] return ( onCancel()} size="small">关闭} > { showUpload ?

把文件拖入指定区域,完成上传,同样支持点击上传。

支持单文件/多文件上传。附件大小最大为30MB!

: '' } record.id} bordered pagination={{ hideOnSinglePage: true, size: "small", pageSize: consts.PAGE_SIZE, onChange: (page, pageSize) => initData(page, pageSize), total: files.total }} /> ) }