/** @tips: 约定:该控件,获取文件路径字符串或上传了文件(即对应编辑时从接口获取的文件链接和新增时获取的对象),都会将符合要求的对象(上传的文件数据或自行拼接的,必须包含status、type、uid等必要字段)转化为字符串 */ /** * @description: 合并老版的文件、可预览文件、录音、视频 * @params: 接收参数 renderTo: Recording/Video/File * @return: {Object} 文件类型返回需要另外处理 * @date: 2021/12/1 * @author: ChenLong * @待解决问题: 为什么list不直接返回url,而要把file对象变成对象字符串? */ /** @tips: 上传业务为:1.通过上传接口,上传文件,获取上传的链接;2.将文件链接存储到服务器,获取存储的地址;3.提交地址 */ /** * @description: 完成 1.文件名校验;2.编辑界面的文件加载及显示的能力;3.不同类型文件的判断 * @date: 2021/12/2 */ /** * @description: 合并图片/可预览图片到文件上传中 * @date: 2021/12/6 */ /** * @description: 文件类型单独处理。文件类型返回的是文件对象的字符串,使用JSON.parse解析之后,取url值即可,拼成用逗号分割的字符串即可。这部分修改在入口文件内 * @description: 需要判断值是文件对象的字符串,约定:文件类必须会有 status: 'done' * @date: 2021/12/8 */ /** @tips: 裁剪功能在前端框架内无法正常工作,暂不提供裁剪功能 */ // 自定义Form Render组件 import React, { useState, useEffect } from 'react'; import { Upload, Button, Modal, message } from 'antd'; import { UploadOutlined, DownloadOutlined } from '@ant-design/icons'; import './fileUpload.less'; import { downloadFunc, filenameVerification } from '../../utils/utils'; import { uploadFileUrl, downloadFileUrl } from '../../../api/service/workflow'; const videoTypeArray = ['.mp4']; const audioTypeArray = ['.mp4']; const fileTypeArray = []; const imageTypeArray = ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg']; const FileUpload = ({ value, onChange, schema }) => { const _isRecordingOrVideo = ['Recording', 'Video', 'Image'].includes(schema.renderTo); const _isVideo = schema.renderTo === 'Video'; const _isAudio = schema.renderTo === 'Recording'; const _isImage = schema.renderTo === 'Image'; const [previewTitle, setPreviewTitle] = useState(''); const [previewVisible, setPreviewVisible] = useState(false); const [previewUrl, setPreviewUrl] = useState(''); const [showList, setShowList] = useState(''); const file = value || schema.default; const option = { name: 'file', action: `${window.location.origin}${uploadFileUrl}`, listType: _isRecordingOrVideo ? 'picture-card' : 'picture', withCredentials: true, beforeUpload(file, fileList) { /** @tips: 解决提交文件中存在特殊字符的问题 */ let _continueUpload = true; let _msg = { type: 'success', content: '上传成功!', }; fileList.forEach((item) => { let _msgObject = filenameVerification(item); if (_msgObject.type === 'error') { _continueUpload = false; _msg = { type: 'error', content: '上传失败!文件名不符合规则!', }; } }); _msg.type === 'error' ? message[_msg.type](_msg.content) : ''; return _continueUpload; }, onChange: ({ file, fileList, event }) => { // 检验名字,名字不通过不允许显示 if (filenameVerification(file).type === 'error') return false; // 返回的链接在file.response内;不设置url,预览图表不可点击 if (file.status === 'done' && file.response.code === 0) { file.url = `${downloadFileUrl}?filePath=${file.response.data}`; file.sourcePath = file.response.data; message.success('上传成功!'); } else if (file.status === 'done' && file.response.code !== 0) { file.status = 'error'; message.error('上传失败!'); } onChange((fileList && fileList.length && JSON.stringify(fileList)) || ''); setShowList(JSON.stringify(fileList)); }, onPreview(file) { if (_isRecordingOrVideo) { setPreviewVisible(true); setPreviewUrl(file.url); } }, previewFile(file) {}, onDownload(file) { downloadFunc(file.url, file.name, '_self'); }, }; const handleCancel = () => { setPreviewVisible(false); setPreviewTitle(''); }; /** * @description: 返回文件类型限定值 * @params: {Array} typeArray: Video | Recording | File * @date: 2021/12/2 * @author: ChenLong */ const returnFileTypeString = (type) => { let _obj = { Video: videoTypeArray, Recording: audioTypeArray, File: fileTypeArray, Image: imageTypeArray, }; return _obj[type].join(','); }; useEffect(() => { let fileList = []; (file || '').split(',').forEach((item, index) => { if (item && filenameVerification({ name: item }, true).type !== 'error') { // @Tips: 直接过滤掉名字中有异常字符的文件 let _obj = { uid: index + '_' + Math.random(), value: item, name: item.split('\\').reverse()[0], type: schema.renderTo === 'Image' ? 'image' : 'file', status: 'done', url: `${downloadFileUrl}?filePath=${item}`, sourcePath: item, }; if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}`; fileList.push(_obj); } }); // onChange(fileList.length && JSON.stringify(fileList) || ''); setShowList(JSON.stringify(fileList)); }, []); useEffect(() => { if (value) { let fileList = []; (file || '').split(',').forEach((item, index) => { if (item && filenameVerification({ name: item }, true).type !== 'error') { // @Tips: 直接过滤掉名字中有异常字符的文件 let _obj = { uid: index + '_' + Math.random(), value: item, name: item.split('\\').reverse()[0], type: schema.renderTo === 'Image' ? 'image' : 'file', status: 'done', url: `${downloadFileUrl}?filePath=${item}`, sourcePath: item, }; if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}`; fileList.push(_obj); } }); // onChange(fileList.length && JSON.stringify(fileList) || ''); setShowList(JSON.stringify(fileList)); } }, [value]); return ( <> {/** @tips: 裁剪功能无法正常工作,暂不提供 */} {/* <ImgCrop beforeCrop={(file) => { let _returnObj = filenameVerification(file); if (_returnObj.type === 'error') { message.error(_returnObj.content); return false; } return schema.renderTo === 'Image'; }} rotate locale={'zh-cn'} modalTitle={'编辑图片'} modalOk={'确定'} modalCancel={'取消'}>*/} <Upload disabled={schema.disabled} {...option} fileList={showList ? JSON.parse(showList) : []} multiple style={{ width: '100%' }} className={_isRecordingOrVideo ? 'formUploadVideoOrRecording' : 'formUpload'} showUploadList={{ showPreviewIcon: _isRecordingOrVideo, showDownloadIcon: true, downloadIcon: <DownloadOutlined />, }} accept={returnFileTypeString(schema.renderTo)} > {!_isRecordingOrVideo ? ( <Button disabled={schema.disabled} icon={<UploadOutlined />}> Upload </Button> ) : ( '+ Upload' )} </Upload> {/* </ImgCrop>*/} <Modal style={{ width: '30%' }} bodyStyle={{ textAlign: 'center' }} visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel} > {_isVideo ? ( <video width={'100%'} height={'100%'} controls autoPlay src={previewUrl} /> ) : ( '' )} {_isAudio ? <audio controls autoPlay src={previewUrl} /> : ''} {_isImage ? <img width={'100%'} height={'100%'} src={previewUrl} alt="缩略图" /> : ''} </Modal> </> ); }; export default FileUpload;