|
@@ -1,24 +1,289 @@
|
|
|
-import { Modal } from "antd"
|
|
|
-import { RcFile } from "antd/lib/upload"
|
|
|
-import React from "react"
|
|
|
+import { Badge, Button, Modal, Space, Table } from "antd"
|
|
|
+import React, { useEffect, useRef, useState } from "react"
|
|
|
import '../../../../pages/launchSystemV3/tencentAdPutIn/index.less'
|
|
|
+import { compressAccurately } from "image-conversion"
|
|
|
+import { blobToBase64, dataURLtoFile, videoMessage } from "@/utils/compress"
|
|
|
+import { getImgSize } from "@/utils/utils"
|
|
|
+import { useAjax } from "@/Hook/useAjax"
|
|
|
+import { bdSysMediaAdd, getFileUrl } from "@/services/launchAdq/material"
|
|
|
+import request from "umi-request"
|
|
|
+import getMD5 from "@/components/MD5"
|
|
|
|
|
|
interface Props {
|
|
|
- fileList: RcFile[]
|
|
|
+ parentId: any
|
|
|
+ belongUser: any,
|
|
|
+ mediaType?: 'VIDEO' | 'IMG' | 'PAGE',//类型
|
|
|
+ fileList?: FileList
|
|
|
visible?: boolean
|
|
|
onClose?: () => void
|
|
|
+ onChange?: () => void
|
|
|
}
|
|
|
-const UploadsTable: React.FC<Props> = ({ visible, onClose }) => {
|
|
|
+const UploadsTable: React.FC<Props> = ({ fileList, visible, onClose, onChange, mediaType, parentId, belongUser }) => {
|
|
|
|
|
|
+ /*******************************/
|
|
|
+ const [dataSource, setDataSource] = useState<any[]>([])
|
|
|
+ const [loading, setLoading] = useState<boolean>(false)
|
|
|
+ const tableRef = useRef(null);
|
|
|
+
|
|
|
+ //请求上传地址
|
|
|
+ const fileUrl = useAjax((params: { type: string, fileType: 'video' | 'image' }) => getFileUrl(params), { manual: true })
|
|
|
+ const add = useAjax((params) => bdSysMediaAdd(params))
|
|
|
+ /*******************************/
|
|
|
+
|
|
|
+ const scrollToRow = (key: number) => {
|
|
|
+ if (tableRef.current) {
|
|
|
+ const tableBody = (tableRef.current as any).querySelector('.ant-table-body');
|
|
|
+ const row = tableBody.querySelector(`.ant-table-row[data-row-key="${key}"]`);
|
|
|
+
|
|
|
+ if (row) {
|
|
|
+ row.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (fileList?.length) {
|
|
|
+ setDataSource([...Array.from(fileList)].map((file, index) => {
|
|
|
+ let type = 'default'
|
|
|
+ let mediaTypeName = '其它文件'
|
|
|
+ if (file.type.startsWith('image/')) {
|
|
|
+ mediaTypeName = '图片'
|
|
|
+ if (mediaType !== 'IMG') type = 'warning'
|
|
|
+ } else if (file.type.startsWith('video/')) {
|
|
|
+ mediaTypeName = '视频'
|
|
|
+ if (mediaType !== 'VIDEO') type = 'warning'
|
|
|
+ } else {
|
|
|
+ type = 'warning'
|
|
|
+ }
|
|
|
+ return { id: index + 1, file, type, mediaTypeName }
|
|
|
+ }))
|
|
|
+ } else {
|
|
|
+ setDataSource([])
|
|
|
+ }
|
|
|
+ }, [fileList, mediaType])
|
|
|
+
|
|
|
+ // 上传方法
|
|
|
+ const upload = (file: File) => {
|
|
|
+ return new Promise(async (resolve) => {
|
|
|
+ let fileSize: number = 0
|
|
|
+ if (mediaType === 'IMG') {
|
|
|
+ fileSize = 409600
|
|
|
+ } else {
|
|
|
+ fileSize = 524288000
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mediaType === 'IMG') {
|
|
|
+ if (file?.size > fileSize) { // 大于400kb进入压缩
|
|
|
+ let bole = await compressAccurately(file, fileSize / 1024 - 50)
|
|
|
+ if (bole?.size > fileSize) {
|
|
|
+ bole = await compressAccurately(file, fileSize / 1024 - 100)
|
|
|
+ }
|
|
|
+ if (bole?.size > fileSize) {
|
|
|
+ bole = await compressAccurately(file, fileSize / 1024 - 150)
|
|
|
+ }
|
|
|
+ if (bole?.size > fileSize) {
|
|
|
+ bole = await compressAccurately(file, fileSize / 1024 - 200)
|
|
|
+ }
|
|
|
+ let newFile = await blobToBase64(bole)
|
|
|
+ file = await dataURLtoFile(newFile, file?.name)
|
|
|
+ }
|
|
|
+ } else if (mediaType === 'VIDEO') {
|
|
|
+ if (file?.size > fileSize) { // 大于100mb进入压缩
|
|
|
+ return resolve(`选择的视频大于${fileSize / 1024 / 1024}MB,请重新选择提交`)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let width = 0
|
|
|
+ let height = 0
|
|
|
+ if (mediaType === 'IMG') {
|
|
|
+ const imgData = await getImgSize(file as any)
|
|
|
+ width = imgData.width
|
|
|
+ height = imgData.height
|
|
|
+ } else if (mediaType === "VIDEO") {
|
|
|
+ const videoInfo: any = await videoMessage([file as any])
|
|
|
+ width = videoInfo[0].width
|
|
|
+ height = videoInfo[0].height
|
|
|
+ }
|
|
|
+ /**修改文件名以用户设置的文件title命名*/
|
|
|
+ let newFile = new File([file], file?.name, { type: file?.type })
|
|
|
+ let formData = new FormData();
|
|
|
+ fileUrl.run({ type: newFile.type, fileType: mediaType === 'VIDEO' ? 'video' : 'image' }).then(res1 => {
|
|
|
+ Object.keys(res1).forEach((key: string) => {
|
|
|
+ if (key !== 'url') {
|
|
|
+ formData.append(key, res1[key])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ formData.append('file', newFile)
|
|
|
+ /**向阿里云返回的上传地址上传文件*/
|
|
|
+ request(res1?.ossUrl, { method: 'post', body: formData }).then(async (res2: { code: number, data: { url: string } }) => {
|
|
|
+ if (res2.code === 200) {
|
|
|
+ if (res2?.data?.url) {
|
|
|
+ let fileMd5 = await getMD5(newFile)
|
|
|
+ let obj: any = { title: file?.name?.split('.')[0], mediaType, folder: false, parentId, width, height, fileMd5, belongUser: belongUser === '0' ? false : true, url: res2?.data?.url, sort: 0, fileSize: newFile?.size, fileMime: newFile.type }
|
|
|
+ if (mediaType === 'VIDEO') {
|
|
|
+ obj['videoTitle'] = file?.name?.split('.')[0]
|
|
|
+ }
|
|
|
+ if (obj.title.match(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g))) {
|
|
|
+ obj.title = obj.title.replace(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g), '')
|
|
|
+ }
|
|
|
+ obj.title = obj.title.replace(/\.(jpg|jpeg|gif|png)$/i, '')
|
|
|
+ add.run(obj).then((res) => {
|
|
|
+ resolve('')
|
|
|
+ }).catch(() => resolve(`上传失败`))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ resolve(`上传失败`)
|
|
|
+ }
|
|
|
+ }).catch(() => resolve(`上传失败`))
|
|
|
+ }).catch(() => resolve(`上传失败`))
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 点击上传
|
|
|
+ const handleOk = () => {
|
|
|
+ setLoading(true)
|
|
|
+ async function uoload(index: number) {
|
|
|
+ let fileData = dataSource[index]
|
|
|
+ scrollToRow(index)
|
|
|
+ if (fileData?.type === 'default') {
|
|
|
+ setDataSource(data => {
|
|
|
+ const newData = [...data]
|
|
|
+ newData[index].type = 'processing'
|
|
|
+ return newData
|
|
|
+ })
|
|
|
+ let error = await upload(fileData.file)
|
|
|
+ setDataSource(data => {
|
|
|
+ const newData = [...data]
|
|
|
+ newData[index].type = error ? 'error' : 'success'
|
|
|
+ newData[index].error = error
|
|
|
+ return newData
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (dataSource.length > index) {
|
|
|
+ uoload(index + 1)
|
|
|
+ } else { // 上传完成
|
|
|
+ setLoading(false)
|
|
|
+ onChange?.()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ uoload(0)
|
|
|
+ }
|
|
|
|
|
|
return <Modal
|
|
|
- title={<strong>上传预览</strong>}
|
|
|
+ title={<strong>上传{mediaType === 'IMG' ? '图片' : '视频'}预览</strong>}
|
|
|
visible={visible}
|
|
|
- onCancel={onClose}
|
|
|
className='modalResetCss'
|
|
|
- width={900}
|
|
|
+ width={1100}
|
|
|
+ closable={false}
|
|
|
+ maskClosable={false}
|
|
|
+ footer={<Space>
|
|
|
+ {!loading && <Button onClick={onClose}>取消</Button>}
|
|
|
+ <Button type="primary" onClick={handleOk} loading={loading}>上传</Button>
|
|
|
+ </Space>}
|
|
|
>
|
|
|
-
|
|
|
+ <Table
|
|
|
+ dataSource={dataSource}
|
|
|
+ size="small"
|
|
|
+ rowKey={'id'}
|
|
|
+ bordered
|
|
|
+ ref={tableRef}
|
|
|
+ scroll={{ y: 450 }}
|
|
|
+ columns={[
|
|
|
+ {
|
|
|
+ title: '序号',
|
|
|
+ dataIndex: 'id',
|
|
|
+ key: 'id',
|
|
|
+ width: 60,
|
|
|
+ align: 'center',
|
|
|
+ fixed: 'left',
|
|
|
+ render: text => <span style={{ fontSize: 12 }}>{text}</span>
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '上传状态',
|
|
|
+ dataIndex: 'type',
|
|
|
+ key: 'type',
|
|
|
+ width: 130,
|
|
|
+ fixed: 'left',
|
|
|
+ render(value) {
|
|
|
+ switch (value) {
|
|
|
+ case 'success':
|
|
|
+ return <Badge status="success" text={<span style={{ fontSize: 12 }}>上传成功</span>} />
|
|
|
+ case 'processing':
|
|
|
+ return <Badge status="processing" text={<span style={{ fontSize: 12 }}>正在上传...</span>} />
|
|
|
+ case 'error':
|
|
|
+ return <Badge status="error" text={<span style={{ fontSize: 12 }}>上传失败</span>} />
|
|
|
+ case 'error_qx':
|
|
|
+ return <Badge status="error" text={<span style={{ fontSize: 12 }}>取消上传</span>} />
|
|
|
+ case 'warning':
|
|
|
+ return <Badge status="warning" text={<span style={{ fontSize: 12 }}>{`当期只能上传${mediaType === 'IMG' ? '图片' : '视频'}`}</span>} />
|
|
|
+ default:
|
|
|
+ return <Badge status="default" text={<span style={{ fontSize: 12 }}>等待上传</span>} />
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '素材类型',
|
|
|
+ dataIndex: 'mediaTypeName',
|
|
|
+ key: 'mediaTypeName',
|
|
|
+ width: 75,
|
|
|
+ align: 'center',
|
|
|
+ render: text => <span style={{ fontSize: 12 }}>{text}</span>
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '素材名称',
|
|
|
+ dataIndex: 'file',
|
|
|
+ key: 'file',
|
|
|
+ width: 150,
|
|
|
+ render(value, record) {
|
|
|
+ if (record.mediaTypeName === '图片' || record.mediaTypeName === '视频') {
|
|
|
+ return <span style={{ fontSize: 12 }}>{value?.name}</span>
|
|
|
+ }
|
|
|
+ return <span style={{ fontSize: 12 }}>其它文件</span>
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '素材',
|
|
|
+ dataIndex: 'file',
|
|
|
+ key: 'file',
|
|
|
+ width: 230,
|
|
|
+ render(value, record) {
|
|
|
+ if (record.mediaTypeName === '图片') {
|
|
|
+ return <img src={URL.createObjectURL(value)} style={{ height: 100, maxWidth: 200 }} />
|
|
|
+ } else if (record.mediaTypeName === '视频') {
|
|
|
+ return <video src={URL.createObjectURL(value)} style={{ maxWidth: 200, height: 100 }}></video>
|
|
|
+ }
|
|
|
+ return <span style={{ fontSize: 12 }}>其它文件</span>
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '错误信息',
|
|
|
+ dataIndex: 'error',
|
|
|
+ key: 'error',
|
|
|
+ width: 300,
|
|
|
+ render: text => <span style={{ fontSize: 12 }}>{text || '--'}</span>
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ dataIndex: 'cz',
|
|
|
+ key: 'cz',
|
|
|
+ width: 70,
|
|
|
+ align: 'center',
|
|
|
+ fixed: 'right',
|
|
|
+ render(_, record) {
|
|
|
+ if (record.type === 'default') {
|
|
|
+ return <a
|
|
|
+ style={{ fontSize: 12, color: 'red' }}
|
|
|
+ onClick={() => {
|
|
|
+ setDataSource(data => {
|
|
|
+ return data.map(item => item.id === record.id ? { ...item, type: 'error_qx' } : item)
|
|
|
+ })
|
|
|
+ }}
|
|
|
+ >取消上传</a>
|
|
|
+ }
|
|
|
+ return '--'
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ />
|
|
|
</Modal>
|
|
|
}
|
|
|
|