123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- import { Button, Card, Form, Input, message, Modal, Radio, Select, Space, TreeSelect, Upload } from "antd"
- import React, { useEffect, useMemo, useState } from "react"
- import '../../tencentAdPutIn/index.less'
- import { useAjax } from "@/Hook/useAjax"
- import { getUserAllApi } from "@/services/operating/account"
- import { RcFile } from "antd/lib/upload"
- import { UploadOutlined } from "@ant-design/icons"
- import style from './index.less'
- import CropperImg from "@/components/FileBoxAD/components/Cropper"
- import { compressAccurately } from "image-conversion"
- import { blobToBase64, dataURLtoFile, videoMessage } from "@/utils/compress"
- import { getImgSize } from "@/utils/utils"
- import request from "umi-request"
- import { getFileUrl } from "@/services/launchAdq/material"
- import getMD5 from "@/components/MD5"
- import { addMaterialApi, getFolderListApi } from "@/services/adqV3/cloudNew"
- import { DataNode } from "antd/lib/tree"
- import { updateTreeData } from "./const"
- interface Props {
- userId: number,
- folderId?: number
- visible?: boolean
- onChange?: () => void
- onClose?: () => void
- }
- /**
- * 上传素材
- * @returns
- */
- const UploadFile: React.FC<Props> = ({ visible, onClose, folderId, userId, onChange }) => {
- /**********************************/
- const [queryForm, setQueryForm] = useState<CLOUDNEW.AddMaterialProps>({ materialType: 'image' })
- const [fileList, setFileList] = useState<any>([])
- const [fileUrl, setFileUrl] = useState<string>('')
- const [previewVisible, setPreviewVisible] = useState<boolean>(false)
- const [visibleCropper, setVisibleCropper] = useState<boolean>(false)
- const [loading, setLoading] = useState<boolean>(false)
- const [treeData, setTreeData] = useState<DataNode[]>([]);
- const getUserAll = useAjax(() => getUserAllApi())
- const addMaterial = useAjax((params) => addMaterialApi(params))
- const getFolderList = useAjax((params) => getFolderListApi(params))
- //请求上传地址
- const getFileUrlAjx = useAjax((params: { type: string, fileType: 'video' | 'image' }) => getFileUrl(params), { manual: true })
- /**********************************/
- useEffect(() => {
- getFolder()
- }, [])
- const getFolder = () => {
- getFolderList.run({}).then(res => {
- setTreeData(() => res?.map((item: { folderName: any; id: any; createBy: number }) => ({
- title: item.folderName,
- value: item.id,
- key: item.id,
- disabled: userId.toString() !== item.createBy.toString()
- })) || [])
- })
- }
- useEffect(() => {
- getUserAll.run()
- }, [])
- const handleOk = async () => {
- if (!folderId && !queryForm?.folderId) {
- message.error('当前不能上传素材,请选择文件夹')
- return
- }
- if (queryForm?.file) {
- let file = queryForm.file
- let fileSize = 0
- if (queryForm.materialType === 'image') {
- fileSize = 409600
- } else {
- fileSize = 524288000
- }
- if (queryForm.materialType === 'image') {
- 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)
- message.warning({
- content: `选择的图片大于${fileSize / 1024}KB,图片已压缩`,
- duration: 3
- })
- file = await dataURLtoFile(newFile, file?.name)
- }
- } else if (queryForm.materialType === 'video') {
- if (file?.size > fileSize) { // 大于100mb进入压缩
- message.error({
- content: `选择的视频大于${fileSize / 1024 / 1024}MB,请重新选择提交`,
- duration: 3
- })
- return
- }
- }
- setLoading(() => true)
- let width = 0
- let height = 0
- let videoDuration = 0
- if (queryForm.materialType === 'image') {
- let imgData = await getImgSize(file)
- width = imgData.width
- height = imgData.height
- } else if (queryForm.materialType === "video") {
- let videoInfo: { width: number, height: number, videoLength: number }[] = await videoMessage([file])
- width = videoInfo[0].width
- height = videoInfo[0].height
- videoDuration = videoInfo[0].videoLength
- }
- /**修改文件名以用户设置的文件title命名*/
- let newFile = new File([file], queryForm?.materialName ? queryForm?.materialName + '.' + file?.name?.split('.')[1] : file?.name, { type: file?.type })
- let formData = new FormData();
- /**向阿里云请求上传地址*/
- getFileUrlAjx.run({ type: newFile.type, fileType: queryForm.materialType }).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: CLOUDNEW.AddMaterialProps = { ...queryForm, width, height, md5: fileMd5, ossUrl: res2?.data?.url, fileSize: newFile?.size, fileMime: newFile.type, aspectRatio: width / height }
- delete obj?.file
- if (!obj?.folderId) obj.folderId = folderId
- if (!obj?.designerId) obj.designerId = userId;
- if (queryForm.materialType === 'video') obj.videoDuration = videoDuration;
- if (!obj?.materialName) obj.materialName = queryForm.file.name;
- if (obj?.materialName && obj.materialName.match(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g))) {
- obj.materialName = obj.materialName.replace(RegExp(/[<>&\\'"/\x08\x09\x0A\x0D\x7F]/g), '')
- }
- obj.materialName = (obj as any).materialName.replace(/\.(jpg|jpeg|gif|png|mp4)$/i, '')
- addMaterial.run(obj).then((res) => {
- setLoading(() => false)
- if (res) {
- message.success('添加成功')
- onChange?.()
- }
- }).catch(() => setLoading(() => false))
- }
- } else {
- message.error('上传失败!')
- }
- }).catch(() => setLoading(() => false))
- }).catch(() => setLoading(() => false))
- } else {
- message.error('请选择素材')
- }
- }
- const getVideo = useMemo(() => {
- if (queryForm?.materialType === 'video') {
- if (queryForm?.file) {
- return <video src={URL.createObjectURL(queryForm?.file)} style={{ width: 200 }} controls />
- } else {
- return null
- }
- } else {
- return null
- }
- }, [queryForm?.file])
- // 下级目录
- const handleUpdateFolder = (parentId: number) => {
- return getFolderListApi({ parentId }).then(res => {
- setTreeData(origin =>
- updateTreeData(origin, parentId, res?.data?.map((item: { folderName: any; id: any; createBy: number }) => ({
- title: item.folderName,
- value: item.id,
- key: item.id,
- disabled: userId.toString() !== item.createBy.toString()
- })) || []),
- );
- })
- }
- return <Modal
- title={<strong>{'上传素材'}</strong>}
- open={visible}
- onCancel={onClose}
- onOk={handleOk}
- className="modalResetCss"
- bodyStyle={{ backgroundColor: '#f1f4fc', maxHeight: 650, overflow: 'hidden', overflowY: 'auto', padding: '10px' }}
- maskClosable={false}
- width={600}
- confirmLoading={loading}
- >
- <Card className="cardResetCss">
- <Form
- labelAlign='left'
- labelCol={{ span: 4 }}
- layout="horizontal"
- colon={false}
- style={{}}
- >
- <Form.Item label={<strong>素材名称</strong>}>
- <Input placeholder="素材名称(不填是上传素材名称)" value={queryForm?.materialName} onChange={(e) => setQueryForm({ ...queryForm, materialName: e.target.value })} />
- </Form.Item>
- <Form.Item label={<strong>设计师</strong>}>
- <Select
- placeholder="请选择设计师(不选默认自己)"
- filterOption={(input, option) =>
- ((option?.label ?? '') as any).toLowerCase().includes(input.toLowerCase())
- }
- value={queryForm?.designerId}
- onChange={(e => setQueryForm({ ...queryForm, designerId: e }))}
- options={getUserAll?.data?.map((item: { nickname: any; userId: any }) => ({ label: item.nickname, value: item.userId }))}
- />
- </Form.Item>
- <Form.Item label={<strong>文件夹</strong>}>
- <TreeSelect
- loading={getFolderList.loading}
- allowClear
- style={{ width: '100%' }}
- value={queryForm?.folderId}
- dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
- placeholder="请选择文件夹(不选择默认当前文件夹)"
- onChange={(e) => {
- setQueryForm({ ...queryForm, folderId: e })
- }}
- loadData={({ value }) => {
- return new Promise<void>(async (resolve) => {
- await handleUpdateFolder(Number(value))
- resolve()
- })
- }}
- treeData={treeData}
- />
- </Form.Item>
- <Form.Item label={<strong>素材类型</strong>}>
- <Radio.Group value={queryForm?.materialType} onChange={(e) => setQueryForm({ ...queryForm, materialType: e.target.value })} buttonStyle="solid">
- <Radio.Button value="image">图片</Radio.Button>
- <Radio.Button value="video">视频</Radio.Button>
- </Radio.Group>
- </Form.Item>
- <Form.Item label={<strong>描述</strong>}>
- <Input.TextArea placeholder="描述" value={queryForm?.description} onChange={(e) => setQueryForm({ ...queryForm, description: e.target.value })} />
- </Form.Item>
- <Form.Item label={<strong>{queryForm?.materialType ? '上传图片' : '上传视频'}</strong>}>
- {queryForm?.materialType === 'image' ? <Space>
- <Upload
- listType="picture-card"
- accept='image/gif,image/jpeg,image/png,image/jpg'
- beforeUpload={(file: RcFile) => {
- return false
- }}
- fileList={fileList}
- onChange={(newFileList: any) => {
- console.log('newFileList-->', newFileList)
- setQueryForm({ ...queryForm, file: newFileList.file })
- setFileList([...newFileList.fileList])
- }}
- onPreview={(file: any) => {
- setPreviewVisible(true)
- setFileUrl(file.thumbUrl)
- }}
- onRemove={() => {
- setQueryForm({ ...queryForm, file: null })
- }}
- >
- {fileList?.length < 1 && '普通上传'}
- </Upload>
- {fileList?.length === 0 && <Upload
- listType="picture-card"
- accept='image/gif,image/jpeg,image/png,image/jpg'
- beforeUpload={(file: RcFile) => {
- return false
- }}
- fileList={fileList}
- onChange={(newFileList: any) => {
- setQueryForm({ ...queryForm, file: newFileList.file })
- setVisibleCropper(true)
- }}
- onRemove={() => {
- setQueryForm({ ...queryForm, file: null })
- }}
- onPreview={(file: any) => {
- setPreviewVisible(true)
- setFileUrl(file.thumbUrl)
- }}
- >
- {fileList?.length < 1 && '裁剪上传'}
- </Upload>}
- </Space> : <>
- <div className={style.file}>
- <Button type='primary'><UploadOutlined />上传视频</Button>
- <input type='file' onChange={(e) => {
- if (e?.target?.files) {
- setQueryForm({ ...queryForm, file: e?.target?.files[0] })
- }
- }} accept="video/*" />
- </div>
- {queryForm?.file && <>
- <p>{queryForm?.file?.name}</p>
- {getVideo}
- </>}
- </>}
- </Form.Item>
- </Form>
- </Card>
- {/* 预览 */}
- <Modal
- open={previewVisible}
- footer={null}
- onCancel={() => {
- setPreviewVisible(false)
- }}
- >
- <img alt="example" style={{ width: '100%' }} src={fileUrl} />
- </Modal>
- {/* 裁剪 */}
- {visibleCropper && <CropperImg visible={visible} onClose={() => setVisibleCropper(false)} file={queryForm.file} onChange={(fileList: any[], file: any) => { setFileList(fileList); setQueryForm({ ...queryForm, file: file }); setVisibleCropper(false) }} />}
- </Modal>
- }
- export default React.memo(UploadFile)
|