You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

362 lines
12 KiB
TypeScript

import React, { useEffect, useRef, useState } from 'react';
import { DrawerForm, ProFormInstance, ProFormText, ProFormUploadButton, ProFormRadio, ProForm } from '@ant-design/pro-components';
import { message } from 'antd';
import Upload, { RcFile } from 'antd/es/upload';
import AdvancedEditor from '@/components/TinyMCEEditor/AdvancedEditor';
import { fullConfig } from '@/components/TinyMCEEditor/config';
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.PbcFashionTrend_>;
export type UpdateFormProps = {
onCancel: (flag?: boolean, formVals?: FormValueType) => void;
onSubmit: (values: FormValueType) => Promise<void>;
updateModalVisible: boolean;
values: Partial<API.PbcFashionTrend_>;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const formRef = useRef<ProFormInstance>();
const [pbcType, setPbcType] = useState<number>(1);
const [videoThumbnail, setVideoThumbnail] = useState<string>("");
useEffect(() => {
setPbcType(props.values.pbcType || 1)
setVideoThumbnail(props.values.pbcThumbNail || "")
}, [props.values.pbcId]);
// 生成视频缩略图的函数
const generateVideoThumbnail = async (videoUrl: string) => {
try {
// 创建视频元素
const video = document.createElement('video');
video.crossOrigin = 'anonymous';
video.src = videoUrl;
video.muted = true;
// 监听视频加载完成事件
await new Promise((resolve, reject) => {
video.onloadeddata = resolve;
video.onerror = reject;
// 设置超时
setTimeout(reject, 5000);
});
// 播放视频并暂停在第一帧
video.currentTime = 0;
await new Promise(resolve => {setTimeout(resolve, 200)});
// 创建canvas并绘制视频帧
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext('2d');
ctx?.drawImage(video, 0, 0, canvas.width, canvas.height);
// 将canvas转为blob
const blob = await new Promise<Blob>((resolve) => {
canvas.toBlob((b) => resolve(b as Blob), 'image/jpeg', 0.95);
});
// 创建FormData并上传
const formData = new FormData();
formData.append('file', blob, 'thumbnail.jpg');
// 发送请求上传缩略图
const response = await fetch(`${process.env.BASE_URL}/oss/imgUpload`, {
method: 'POST',
headers: {
authorization: localStorage.getItem('token') ?? '',
},
body: formData,
});
const result = await response.json();
if (result.retcode) {
setVideoThumbnail(result.data);
}
} catch (error) {
console.error('生成视频缩略图失败:', error);
}
};
return (
<DrawerForm
width={640}
title={props.values.pbcId ? '编辑流行趋势' : '新增流行趋势'}
open={props.updateModalVisible}
formRef={formRef}
onFinish={async (value: any) => {
let pbcPicAddress = ""
let pbcThumbNail = "https://oss-xfc.popshejie.com/pop-b2b2c/pdf_fac16828-ea35-4034-9ad8-263605611960.png"
if (value.pbcType === 1 && value.pbcImage.length > 0) {
pbcThumbNail = value.pbcImage[0].url || value.pbcImage[0].response.data;
pbcPicAddress = value.pbcImage.map((e: any) => {
return e.url || e.response.data;
}).join(',');
} else if (value.pbcType === 2 && value.pbcVideo.length > 0) {
pbcPicAddress = value.pbcVideo[0].url || value.pbcVideo[0].response.data;
pbcThumbNail = videoThumbnail;
} else if (value.pbcType === 3 && value.pbcFile.length > 0) {
pbcPicAddress = value.pbcFile[0].url || value.pbcFile[0].response.data;
if (value.pbcThumbNail.length > 0) {
pbcThumbNail = value.pbcThumbNail[0].url || value.pbcThumbNail[0].response.data;
}
}
return props.onSubmit({ ...value, pbcPicAddress, pbcThumbNail, pbcContent: value.pbcType === 3 ? '预览文件' : value.pbcContent, pbcId: props.values.pbcId })
}}
drawerProps={{
destroyOnHidden: true,
}}
initialValues={{
pbcTitle: props.values.pbcTitle,
pbcType: props.values.pbcType || 1,
pbcImage: props.values.pbcType === 1 && props.values.pbcPicAddress ? props.values.pbcPicAddress.split(',').map((e, index) => {
return {
uid: '-' + index,
name: e.substring(e.lastIndexOf('/') + 1),
status: 'done',
url: e,
}
}) : [],
pbcVideo: props.values.pbcType === 2 && props.values.pbcPicAddress ? [{
uid: '-1',
name: props.values.pbcPicAddress.substring(props.values.pbcPicAddress.lastIndexOf('/') + 1),
status: 'done',
url: props.values.pbcPicAddress,
}] : [],
pbcFile: props.values.pbcType === 3 && props.values.pbcPicAddress ? [{
uid: '-1',
name: props.values.pbcPicAddress.substring(props.values.pbcPicAddress.lastIndexOf('/') + 1),
status: 'done',
url: props.values.pbcPicAddress,
}] : [],
pbcThumbNail: props.values.pbcType === 3 && props.values.pbcThumbNail ? [{
uid: '-1',
name: props.values.pbcThumbNail.substring(props.values.pbcThumbNail.lastIndexOf('/') + 1),
status: 'done',
url: props.values.pbcThumbNail,
}] : [],
pbcContent: props.values.pbcContent
}}
onOpenChange={(visible) => {
formRef.current?.resetFields();
if (!visible) {
props.onCancel();
}
}}
>
<ProFormText
placeholder={'请输入标题'}
label="标题"
rules={[
{
required: true,
message: '标题为必填项',
},
]}
width="md"
name="pbcTitle"
/>
<ProFormRadio.Group
name="pbcType"
label="类型"
options={[
{
label: '图片',
value: 1,
},
{
label: '视频',
value: 2,
},
{
label: '文件',
value: 3,
},
]}
rules={[
{
required: true,
message: '请选择类型',
},
]}
fieldProps={{
onChange: (e) => {
setPbcType(e.target.value)
formRef.current?.setFieldValue('pbcImage', []);
formRef.current?.setFieldValue('pbcThumbNail', []);
formRef.current?.setFieldValue('pbcVideo', []);
formRef.current?.setFieldValue('pbcFile', []);
},
}}
/>
{pbcType === 3 ? <ProFormUploadButton
label="缩略图"
name="pbcThumbNail"
max={1}
fieldProps={{
name: 'file',
accept: 'image/*',
multiple: true,
headers: {
authorization: localStorage.getItem('token') ?? '',
},
onChange: (info: any) => {
switch (info.file.status) {
case 'done':
if (info.file.response.retcode === 0) {
message.error(info.file.response.retmsg);
formRef.current?.setFieldValue('pbcThumbNail', [])
}
break;
default:
break;
}
},
action: process.env.BASE_URL + '/oss/imgUpload',
beforeUpload(file: RcFile) {
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('图片大小不能超过10MB!');
}
return isLt10M || Upload.LIST_IGNORE;
},
onPreview: async (file) => {
if (file.uid.includes('-')) {
window.open(file.url);
}
if (file.response && file.response.retcode) {
window.open(file.response.data);
}
},
listType: 'picture-card',
}}
rules={[
{ required: true, message: '请上传缩略图' },
]}
/> : null}
{pbcType === 1 ? <ProFormUploadButton
label="上传图片"
name="pbcImage"
max={9}
fieldProps={{
name: 'file',
accept: 'image/*',
multiple: true,
headers: {
authorization: localStorage.getItem('token') ?? '',
},
onChange: (info: any) => {
switch (info.file.status) {
case 'done':
if (info.file.response.retcode === 0) {
message.error(info.file.response.retmsg);
formRef.current?.setFieldValue('pbcImage', [])
}
break;
default:
break;
}
},
action: process.env.BASE_URL + '/oss/imgUpload',
beforeUpload(file: RcFile) {
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('图片大小不能超过10MB!');
}
return isLt10M || Upload.LIST_IGNORE;
},
onPreview: async (file) => {
if (file.uid.includes('-')) {
window.open(file.url);
}
if (file.response && file.response.retcode) {
window.open(file.response.data);
}
},
listType: 'picture-card',
}}
rules={[
{ required: true, message: '请上传图片' },
]}
/> :
<ProFormUploadButton
label={pbcType === 2 ? "上传视频" : "上传文件"}
name={pbcType === 2 ? "pbcVideo" : "pbcFile"}
max={1}
fieldProps={{
name: 'file',
accept: pbcType === 2 ? 'video/mp4' : '.pdf',
multiple: true,
headers: {
authorization: localStorage.getItem('token') ?? '',
},
onChange: (info: any) => {
switch (info.file.status) {
case 'done':
if (info.file.response.retcode === 0) {
message.error(info.file.response.retmsg);
if (pbcType === 2) {
formRef.current?.setFieldValue('pbcVideo', [])
} else {
formRef.current?.setFieldValue('pbcFile', [])
}
} else if (info.file.response && info.file.response.retcode && pbcType === 2) {
// 视频上传成功后,获取视频首帧作为缩略图
const videoUrl = info.file.response.data;
generateVideoThumbnail(videoUrl);
}
break;
default:
break;
}
},
action: process.env.BASE_URL + '/oss/imgUpload',
beforeUpload(file: RcFile) {
const isLt300M = file.size / 1024 / 1024 < 300;
if (!isLt300M) {
message.error(`${pbcType === 2 ? '视频' : '文件'}大小不能超过300MB!`);
}
return isLt300M || Upload.LIST_IGNORE;
},
onPreview: async (file) => {
if (file.uid === '-1') {
window.open(file.url);
}
if (file.response && file.response.retcode) {
window.open(file.response.data);
}
},
listType: 'picture-card',
}}
rules={[
{ required: true, message: `请上传${pbcType === 2 ? '视频' : '文件'}'` },
]}
/>}
{pbcType !== 3 ? <ProForm.Item
name="pbcContent"
label="趋势内容"
rules={[
{
required: true,
message: '趋势内容为必填项',
},
]}
>
<AdvancedEditor
height={500}
placeholder="请输入内容"
customConfig={fullConfig}
/>
</ProForm.Item>:null}
</DrawerForm>
);
};
export default UpdateForm;