index.js 6.99 KB
Newer Older
1
import React, { useEffect, useState } from 'react'
田翔's avatar
田翔 committed
2
import styles from './index.less'
3 4
import { Upload, Button, message } from 'antd'
import { UploadOutlined, FileOutlined } from '@ant-design/icons'
5
import FileViewer from 'react-file-viewer'
6
import { uploadFileUrl, downloadFileUrl } from '../../../../apis/process'
田翔's avatar
田翔 committed
7
import { filenameVerification } from '../../../../utils'
8
import Drag from '../../../components/Drag'
田翔's avatar
田翔 committed
9 10

const accepts = {
田翔's avatar
田翔 committed
11
  '全部': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg', '.docx', '.xlsx', '.pdf', '.mp4', '.mp3'],
田翔's avatar
田翔 committed
12
  '图片': ['.bmp', '.gif', '.jpeg', 'tiff', '.png', '.svg', '.jpg'],
田翔's avatar
田翔 committed
13
  '文档': ['.docx', '.xlsx', '.pdf'],
田翔's avatar
田翔 committed
14 15 16 17
  '视频': ['.mp4'],
  '音频': ['.mp3'],
}

田翔's avatar
田翔 committed
18 19 20 21 22 23 24 25 26 27 28 29
const getFileType = (fileName) => {
  if (fileName) {
    //图片
    if (fileName.includes('jpg')) {
      return 'jpg'
    }
    if (fileName.includes('png')) {
      return 'png'
    }
    if (fileName.includes('svg')) {
      return 'svg'
    }
30 31 32
    if (fileName.includes('jpeg')) {
      return 'jpeg'
    }
田翔's avatar
田翔 committed
33 34 35 36 37 38 39 40 41 42
    //文档
    if (fileName.includes('docx')) {
      return 'docx'
    }
    if (fileName.includes('xlsx')) {
      return 'xlsx'
    }
    if (fileName.includes('pdf')) {
      return 'pdf'
    }
田翔's avatar
田翔 committed
43 44 45
    if (fileName.includes('pptx')) {
      return 'pptx'
    }
田翔's avatar
田翔 committed
46 47 48 49 50 51 52 53 54 55 56 57
    //音频
    if (fileName.includes('mp3')) {
      return 'mp3'
    }
    //视频
    if (fileName.includes('mp4')) {
      return 'mp4'
    }
  }
  return null
}

田翔's avatar
田翔 committed
58 59
const FileUpload = (props) => {

60
  const site = window.globalConfig?.userInfo?.site || window.globalConfig?.userInfo?.LocalSite
田翔's avatar
田翔 committed
61
  const { addons, value, schema, onChange } = props
62
  const { disabled, fileType, presetValue, placeholder, preview, download } = schema
田翔's avatar
田翔 committed
63

64
  const [showList, setShowList] = useState([])
田翔's avatar
田翔 committed
65 66
  const [visible, setVisible] = useState(false)
  const [showFile, setShowFile] = useState({ fileType: '', filePath: '' })
田翔's avatar
田翔 committed
67
  const [imgVisible, setImgVisible] = useState(false)
田翔's avatar
田翔 committed
68

69 70
  const showType = fileType === '图片' ? 'picture-card' : 'picture'

田翔's avatar
田翔 committed
71 72 73
  const option = {
    name: 'file',
    action: `${window.location.origin}${uploadFileUrl}`,
田翔's avatar
田翔 committed
74
    listType: showType,
田翔's avatar
田翔 committed
75
    withCredentials: true,
田翔's avatar
田翔 committed
76 77 78 79
    showUploadList: {
      showRemoveIcon: !disabled,
      showDownloadIcon: download,
    },
田翔's avatar
田翔 committed
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
    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) {
105
        file.url = `${downloadFileUrl}?filePath=${file.response.data}${site ? `&_site=${site}` : ''}`
田翔's avatar
田翔 committed
106 107 108 109 110 111 112
        file.sourcePath = file.response.data;
        message.success('上传成功!')
      } else if (file.status === 'done' && file.response.code !== 0) {
        file.status = 'error';
        message.error('上传失败!')
      }
      if (Array.isArray(fileList)) {
113
        setShowList(fileList)
田翔's avatar
田翔 committed
114 115 116
      } else {
        setShowList()
      }
117 118 119
      if (file.status === 'done') {
        onChange(fileList.map(v => v.sourcePath).join(','))
      }
田翔's avatar
田翔 committed
120 121
    },
    onPreview: (file) => {
田翔's avatar
田翔 committed
122
      if (!preview) return message.info('该附件禁止预览')
田翔's avatar
田翔 committed
123
      let fileType = getFileType(file.name)
田翔's avatar
田翔 committed
124 125 126
      if (fileType) {
        setShowFile({ name: file.name, fileType: fileType, filePath: file.url })
        setVisible(true)
田翔's avatar
田翔 committed
127 128
      } else {
        message.info('不支持该类型预览')
田翔's avatar
田翔 committed
129 130 131 132 133 134
      }
    }
  }

  const iconRender = (file, listType) => {
    if (listType !== 'text') {
田翔's avatar
田翔 committed
135 136 137 138 139
      let fileType = getFileType(file.name)
      if (fileType) {
        return <div className={styles.iconImg} type={fileType}></div>
      } else {
        return <div className={styles.iconImg} type={'通用'}></div>
田翔's avatar
田翔 committed
140 141 142 143 144
      }
    }
    return <FileOutlined />
  }

145 146 147 148
  const valueToList = (presetValue) => {
    let fileList = []
    if (presetValue) {
      let list = presetValue ? presetValue.split(',') : []
田翔's avatar
田翔 committed
149 150 151 152 153 154 155 156 157
      list.forEach((item, index) => {
        if (item) { // @Tips: 直接过滤掉名字中有异常字符的文件
          let uid = index + '_' + Math.random()
          let _obj = {
            uid: uid,
            value: item,
            name: item.split('\\').reverse()[0],
            type: fileType === '图片' ? 'image/jpeg' : 'file',
            status: 'done',
田翔's avatar
田翔 committed
158 159
            url: `${downloadFileUrl}?filePath=${item}${site ? `&_site=${site}` : ''}`,
            sourcePath: item.url,
田翔's avatar
田翔 committed
160
            originFileObj: { "uid": uid },
田翔's avatar
田翔 committed
161
            "response": { "code": 0, "msg": "Ok", "data": item, "stackTrace": null },
田翔's avatar
田翔 committed
162 163
            "xhr": {},
          };
田翔's avatar
田翔 committed
164
          if (schema.renderTo === 'Image') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}${site ? `&_site=${site}` : ''}`;
田翔's avatar
田翔 committed
165 166 167 168
          fileList.push(_obj);
        }
      })
    }
169 170 171 172 173
    return fileList
  }

  useEffect(() => {
    if (presetValue && !presetValue.includes('拍照相册')) {
田翔's avatar
田翔 committed
174
      addons?.setValue(addons?.dataPath, presetValue || '')
175
      setShowList(valueToList(presetValue))
田翔's avatar
田翔 committed
176
    } else {
田翔's avatar
田翔 committed
177
      addons?.setValue(addons?.dataPath, '')
178 179
    }
  }, [presetValue])
180

田翔's avatar
田翔 committed
181 182 183
  return (
    <div className={styles.uploadBox}>
      <Upload
田翔's avatar
田翔 committed
184
        // disabled={disabled}
田翔's avatar
田翔 committed
185
        accept={accepts[fileType]}
186
        fileList={showList}
田翔's avatar
田翔 committed
187 188 189 190
        className="upload-list-inline"
        iconRender={iconRender}
        {...option}
      >
田翔's avatar
田翔 committed
191 192
        {
          showType !== 'picture-card' ?
田翔's avatar
田翔 committed
193
            (disabled ? null : <Button icon={<UploadOutlined />}>{placeholder || '上传'}</Button>)
田翔's avatar
田翔 committed
194 195
            : (disabled ? null : (placeholder || '+ 上传'))
        }
田翔's avatar
田翔 committed
196
      </Upload>
197
      <Drag
田翔's avatar
田翔 committed
198
        width={'70%'}
田翔's avatar
田翔 committed
199 200 201 202 203
        title={showFile.name}
        visible={visible}
        onCancel={() => setVisible(false)}
        bodyStyle={{ height: 650, overflowY: showFile.fileType.includes('xlsx') ? 'none' : "auto" }}
      >
田翔's avatar
田翔 committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217
        {
          ['jpg', 'png', 'svg', 'jpeg'].includes(showFile.fileType) ? (
            <div style={{ width: '100%', height: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
              <img style={{ maxWidth: '100%', maxHeight: '100%' }} src={window.location.origin + showFile.filePath}></img>
            </div>
          ) : (
            <FileViewer
              className='fileViewer'
              title='123'
              fileType={showFile.fileType}
              filePath={window.location.origin + showFile.filePath}
            />
          )
        }
218
      </Drag>
田翔's avatar
田翔 committed
219 220 221 222 223 224
    </div>
  )

}

export default FileUpload