import React, { Component } from 'react' import { Button, Card, Form, Input, message as Message, Popconfirm, Select, Tag, Tooltip, Upload, } from 'antd' import { AntIcon, Auth, Container, PhotoPreview, QueryTable, QueryTableActions } from 'components' import { api } from 'common/api' import auth from 'components/authorized/handler' import { isEqual } from 'lodash' import getDictData from 'util/dic' import { toCamelCase } from 'util/format' import { ArrayBufferToBase64, GetFileName, PreviewFileArrayBuffer } from 'util/file' /** * 注释段[\/**\/]为必须要改 */ /** * 配置页面所需接口函数 */ const apiAction = { page: api.sysFileInfoPage, delete: api.sysFileInfoDelete, } /** * 用于弹窗标题 * [必要] */ const name = '/**/' /** * 统一配置权限标识 * [必要] */ const authName = 'sysFileInfo' export default class index extends Component { state = { codes: { fileStorageLocation: [], }, uploading: false, } // 表格实例 table = React.createRef() photoPreview = React.createRef() columns = [ { title: '文件名称', dataIndex: 'fileOriginName', width: 300, ellipsis: { showTitle: false, }, sorter: true, render: text => {text}, }, { title: '文件后缀', dataIndex: 'fileSuffix', width: 120, sorter: true, render: text => {text}, }, { title: '文件大小', dataIndex: 'fileSizeKb', width: 120, sorter: true, render: text => ( <> {text} KB ), }, { title: '存储位置', dataIndex: 'fileLocation', width: 120, sorter: true, render: text => this.bindCodeValue(text, 'file_storage_location'), }, { title: '文件仓库', dataIndex: 'fileBucket', width: 200, ellipsis: { showTitle: false, }, sorter: true, render: text => {text}, }, { title: '唯一标识id', dataIndex: 'fileObjectName', width: 250, ellipsis: { showTitle: false, }, sorter: true, render: text => {text}, }, { title: '上传时间', dataIndex: 'createdTime', width: 200, sorter: true, defaultSortOrder: 'descend', }, ] /** * 构造函数,在渲染前动态添加操作字段等 * @param {*} props */ constructor(props) { super(props) const flag = auth({ [authName]: 'delete' }) if (flag) { this.columns.push({ title: '操作', width: 150, dataIndex: 'actions', render: (text, record) => ( this.onFileDownload(record)}>下载 this.onDelete(record)} > 删除 {['png', 'jpeg', 'jpg', 'gif', 'tif', 'bmp'].includes( record.fileSuffix ) && this.onFilePreview(record)}>预览} ), }) } } /** * 阻止外部组件引发的渲染,提升性能 * 可自行添加渲染条件 * [必要] * @param {*} props * @param {*} state * @returns */ shouldComponentUpdate(props, state) { return !isEqual(this.state, state) } /** * 加载字典数据,之后开始加载表格数据 * 如果必须要加载字典数据,可直接对表格设置autoLoad=true */ componentDidMount() { const { onLoading, onLoadData } = this.table.current onLoading() getDictData('file_storage_location').then(codes => { this.setState({ codes }, () => { onLoadData() }) }) } /** * 调用加载数据接口,可在调用前对query进行处理 * [异步,必要] * @param {*} params * @param {*} query * @returns */ loadData = async (params, query) => { const { data } = await apiAction.page({ ...params, ...query, }) return data } /** * 绑定字典数据 * @param {*} code * @param {*} name * @returns */ bindCodeValue(code, name) { name = toCamelCase(name) const codes = this.state.codes[name] if (codes) { const c = codes.find(p => p.code == code) if (c) { return c.value } } return null } /** * 打开新增/编辑弹窗 * @param {*} modal * @param {*} record */ onOpen(modal, record) { modal.current.open({ record, }) } /** * 对表格上的操作进行统一处理 * [异步] * @param {*} action * @param {*} successMessage */ async onAction(action, successMessage) { const { onLoading, onLoaded, onReloadData } = this.table.current onLoading() try { if (action) { await action } if (successMessage) { Message.success(successMessage) } onReloadData() } catch { onLoaded() } } /** * 删除 * @param {*} record */ onDelete(record) { this.onAction(apiAction.delete(record), '删除成功') } //#region 自定义方法 async onFileUpload({ file }) { this.setState({ uploading: true }) const table = this.table.current table.onLoading() const fd = new FormData() fd.append('file', file) try { await api.sysFileInfoUpload(fd) table.onReloadData() } catch { table.onLoaded() } finally { this.setState({ uploading: false }) } } async onFilePreview({ id }) { const key = Math.random().toString(16).slice(2) const hide = Message.loading({ key, content: '正在获取文件...', duration: 0, }) const file = await PreviewFileArrayBuffer(id) if (file) { const base64 = await ArrayBufferToBase64(file) var img = new Image() img.onload = () => { const items = [ { src: base64, w: img.naturalWidth, h: img.naturalHeight, }, ] this.photoPreview.current.initPhotoSwipe(items) hide() } img.onerror = () => { Message.error({ key, content: '获取文件失败', }) } img.src = base64 } else { Message.error({ key, content: '获取文件失败', }) } } async onFileDownload({ id }) { const key = Math.random().toString(16).slice(2) const hide = Message.loading({ key, content: '正在获取文件...', duration: 0, }) try { const { data, headers } = await api.sysFileInfoDownload({ id }) const url = window.URL.createObjectURL(data) const fileName = GetFileName(headers['content-disposition']) const a = document.createElement('a') a.href = url a.download = fileName a.click() window.URL.revokeObjectURL(url) a.remove() hide() } catch { Message.error({ key, content: '下载文件失败', }) } } //#endregion render() { const { codes, uploading } = this.state return (
} operator={ this.onFileUpload(e)} fileList={[]}> } />
) } }