fileUpload.js 8.25 KB
Newer Older
陈龙's avatar
陈龙 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
/** @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;