|
@@ -6,13 +6,14 @@ import http from "../../../../../http";
|
|
|
import styles from "./index.module.css";
|
|
|
import type { UploadFile, UploadProps } from "antd/es/upload/interface";
|
|
|
import { getAccessToken } from "../../../../../http/sso";
|
|
|
-import { adFileUpload, getTempStsToken } from "../../../../../http/api";
|
|
|
+import { adFileUpload, getTempStsToken, uploadPublishVideo } from "../../../../../http/api";
|
|
|
|
|
|
interface UploadVideoModalProps {
|
|
|
visible: boolean;
|
|
|
onClose: () => void;
|
|
|
onOk?: (videoInfo: any) => void;
|
|
|
isLoading?: boolean;
|
|
|
+ videoInfo?: any;
|
|
|
}
|
|
|
|
|
|
interface UploadStatus {
|
|
@@ -22,7 +23,6 @@ interface UploadStatus {
|
|
|
errType?: string;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
interface UploadCreds {
|
|
|
host: string;
|
|
|
hosts: string[];
|
|
@@ -38,12 +38,12 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
visible,
|
|
|
onClose,
|
|
|
onOk,
|
|
|
- isLoading = false
|
|
|
+ isLoading = false,
|
|
|
+ videoInfo
|
|
|
}) => {
|
|
|
// 视频文件状态
|
|
|
const [videoFile, setVideoFile] = useState<File & { localUrl?: string } | null>(null);
|
|
|
const [videoUploadProgress, setVideoUploadProgress] = useState(0);
|
|
|
- const [videoUploadSpeed, setVideoUploadSpeed] = useState('0Mb/s');
|
|
|
const [videoUploadStatus, setVideoUploadStatus] = useState<UploadStatus>({
|
|
|
isUploading: false,
|
|
|
isUploaded: false,
|
|
@@ -68,6 +68,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
|
|
|
// 表单引用
|
|
|
const [form] = Form.useForm();
|
|
|
+ const [isEditMode, setIsEditMode] = useState(false);
|
|
|
|
|
|
// 视频预览
|
|
|
const [videoPreviewOpen, setVideoPreviewOpen] = useState(false);
|
|
@@ -78,13 +79,12 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
// 重置视频文件状态
|
|
|
setVideoFile(null);
|
|
|
setVideoUploadProgress(0);
|
|
|
- setVideoUploadSpeed('0Mb/s');
|
|
|
setVideoUploadStatus({
|
|
|
isUploading: false,
|
|
|
isUploaded: false,
|
|
|
isError: false
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 重置封面文件状态
|
|
|
setCoverFileList([]);
|
|
|
setCoverUploadStatus({
|
|
@@ -92,12 +92,13 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
isUploaded: false,
|
|
|
isError: false
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 重置OSS状态
|
|
|
setVideoCreds(null);
|
|
|
setVideoUploader(null);
|
|
|
setVideoUrl('');
|
|
|
-
|
|
|
+ setIsEditMode(false);
|
|
|
+
|
|
|
if (speedTimer) {
|
|
|
clearInterval(speedTimer);
|
|
|
setSpeedTimer(null);
|
|
@@ -114,13 +115,62 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
}
|
|
|
};
|
|
|
}, [speedTimer, videoUploader]);
|
|
|
-
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (videoFile) {
|
|
|
startVideoUpload(videoFile);
|
|
|
}
|
|
|
}, [videoFile]);
|
|
|
|
|
|
+ // 当videoInfo发生变化时,初始化表单和状态
|
|
|
+ useEffect(() => {
|
|
|
+ if (visible && videoInfo) {
|
|
|
+ setIsEditMode(true);
|
|
|
+ setVideoUploadProgress(100);
|
|
|
+ // 填充表单数据
|
|
|
+ form.setFieldsValue({
|
|
|
+ title: videoInfo.title,
|
|
|
+ });
|
|
|
+ // 设置视频URL和状态
|
|
|
+ setVideoUrl(videoInfo.videoUrl);
|
|
|
+ setVideoUploadStatus({
|
|
|
+ isUploading: false,
|
|
|
+ isUploaded: true,
|
|
|
+ isError: false
|
|
|
+ });
|
|
|
+ // 设置封面文件
|
|
|
+ if (videoInfo.coverUrl) {
|
|
|
+ setCoverFileList([{
|
|
|
+ uid: '-1',
|
|
|
+ name: videoInfo.coverName || 'cover.jpg',
|
|
|
+ status: 'done',
|
|
|
+ url: videoInfo.coverUrl,
|
|
|
+ response: {
|
|
|
+ data: {
|
|
|
+ fileUrl: videoInfo.coverUrl
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }]);
|
|
|
+ setCoverUploadStatus({
|
|
|
+ isUploading: false,
|
|
|
+ isUploaded: true,
|
|
|
+ isError: false
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 对于编辑模式,我们需要创建一个模拟的videoFile对象来显示视频预览
|
|
|
+ if (videoInfo.videoUrl) {
|
|
|
+ // 提取文件名作为显示名称
|
|
|
+ const fileName = videoInfo.videoName || videoInfo.videoUrl.split('/').pop() || 'video.mp4';
|
|
|
+ setVideoFile({
|
|
|
+ localUrl: videoInfo.videoUrl,
|
|
|
+ name: fileName,
|
|
|
+ type: 'video/mp4',
|
|
|
+ size: 0 // 实际项目中可能需要从服务器获取文件大小
|
|
|
+ } as File & { localUrl?: string });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [visible, videoInfo, form]);
|
|
|
+
|
|
|
// 获取上传凭证
|
|
|
const getSignature = async (fileType: number, uploadId?: string): Promise<UploadCreds> => {
|
|
|
try {
|
|
@@ -130,7 +180,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
}
|
|
|
// 这里需要根据实际API接口调整
|
|
|
const response = await http.post<any>(getTempStsToken, params);
|
|
|
-
|
|
|
+
|
|
|
if (response.code === 0) {
|
|
|
const credsData = response.data;
|
|
|
if (fileType === 2) { // 视频文件
|
|
@@ -172,7 +222,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
|
|
|
try {
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: true, isError: false }));
|
|
|
-
|
|
|
+
|
|
|
// 获取上传凭证
|
|
|
const uploadCreds = await getSignature(2); // 2表示视频文件
|
|
|
setVideoCreds(uploadCreds);
|
|
@@ -181,17 +231,14 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
const uploaderInstance = await initVideoUploader(uploadCreds);
|
|
|
setVideoUploader(uploaderInstance);
|
|
|
|
|
|
- // 开始速度监控
|
|
|
- startSpeedMonitoring(uploaderInstance);
|
|
|
-
|
|
|
// 开始上传
|
|
|
await uploaderInstance.multipartUpload();
|
|
|
-
|
|
|
+
|
|
|
// 上传完成
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: false, isUploaded: true }));
|
|
|
- setVideoUploadSpeed('');
|
|
|
- message.success('视频上传成功');
|
|
|
-
|
|
|
+ if (!isEditMode) {
|
|
|
+ message.success('视频上传成功');
|
|
|
+ }
|
|
|
} catch (error: any) {
|
|
|
console.error('视频上传失败:', error);
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: false, isError: true, errType: 'uploadError' }));
|
|
@@ -203,7 +250,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
const handleCoverUploadChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
|
|
// 只保留最新的文件
|
|
|
setCoverFileList(newFileList.slice(-1));
|
|
|
-
|
|
|
+
|
|
|
// 如果上传成功,更新状态
|
|
|
if (newFileList.length > 0 && newFileList[0].status === 'done') {
|
|
|
setCoverUploadStatus(prev => ({ ...prev, isUploaded: true, isError: false }));
|
|
@@ -225,23 +272,6 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
return true; // 允许上传
|
|
|
};
|
|
|
|
|
|
- // 开始速度监控
|
|
|
- const startSpeedMonitoring = (uploaderInstance: OSSSDK) => {
|
|
|
- const timer = uploaderInstance.getSpeed((speed: string) => {
|
|
|
- setVideoUploadSpeed(speed + 'Mb/s');
|
|
|
- });
|
|
|
- setSpeedTimer(timer);
|
|
|
- };
|
|
|
-
|
|
|
- // 停止速度监控
|
|
|
- const stopSpeedMonitoring = () => {
|
|
|
- if (speedTimer) {
|
|
|
- clearInterval(speedTimer);
|
|
|
- setSpeedTimer(null);
|
|
|
- }
|
|
|
- setVideoUploadSpeed('');
|
|
|
- };
|
|
|
-
|
|
|
// 重试视频上传
|
|
|
const handleVideoRetry = async () => {
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isError: false }));
|
|
@@ -249,20 +279,16 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
if (videoUploader && videoCreds) {
|
|
|
try {
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: true }));
|
|
|
-
|
|
|
+
|
|
|
// 重新获取凭证
|
|
|
const newCreds = await getSignature(2, videoCreds.upload);
|
|
|
setVideoCreds(newCreds);
|
|
|
videoUploader.updateConfig(newCreds);
|
|
|
|
|
|
- // 开始速度监控
|
|
|
- startSpeedMonitoring(videoUploader);
|
|
|
-
|
|
|
// 断点续传
|
|
|
await videoUploader.resumeMultipartUpload();
|
|
|
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: false, isUploaded: true }));
|
|
|
- setVideoUploadSpeed('');
|
|
|
message.success('视频上传成功');
|
|
|
|
|
|
} catch (error) {
|
|
@@ -278,7 +304,6 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
if (videoUploader) {
|
|
|
videoUploader.cancelUpload();
|
|
|
}
|
|
|
- stopSpeedMonitoring();
|
|
|
setVideoUploadStatus(prev => ({ ...prev, isUploading: false }));
|
|
|
message.info('已取消视频上传');
|
|
|
};
|
|
@@ -290,26 +315,40 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ // 表单校验
|
|
|
+ try {
|
|
|
+ await form.validateFields();
|
|
|
+ } catch (error) {
|
|
|
+ message.warning('请填写完整的视频信息');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验封面是否上传
|
|
|
+ if (coverFileList.length === 0 || !coverUploadStatus.isUploaded) {
|
|
|
+ message.warning('请上传视频封面');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
const formData = form.getFieldsValue();
|
|
|
|
|
|
const publishData = {
|
|
|
...formData,
|
|
|
- videoPath: videoCreds?.fileName || videoUrl,
|
|
|
- coverPath: coverFileList.length > 0 ? coverFileList[0].url : '',
|
|
|
+ videoUrl: isEditMode ? videoUrl : (videoCreds?.fileName || videoUrl),
|
|
|
+ coverUrl: coverFileList.length > 0 ? coverFileList[0].response.data.fileUrl : '',
|
|
|
fileExtensions: 'mp4', // 可以根据文件类型动态设置
|
|
|
- };
|
|
|
+ ...(isEditMode && videoInfo?.videoId && { videoId: videoInfo.videoId })
|
|
|
+ };
|
|
|
|
|
|
// 这里需要根据实际API接口调整
|
|
|
- const response = await http.post<any>('/contentPlatform/video/publish', publishData);
|
|
|
-
|
|
|
- if (response.data.code === 0) {
|
|
|
+ const response = await http.post<any>(uploadPublishVideo, publishData);
|
|
|
+ if (response.code === 0) {
|
|
|
message.success('发布成功');
|
|
|
- onOk?.(response.data.data);
|
|
|
+ onOk?.(response.data);
|
|
|
onClose();
|
|
|
resetStates();
|
|
|
} else {
|
|
|
- message.error(response.data.msg || '发布失败');
|
|
|
+ message.error(response.msg || '发布失败');
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('发布失败:', error);
|
|
@@ -346,7 +385,6 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
return false; // 阻止自动上传
|
|
|
};
|
|
|
|
|
|
-
|
|
|
// 删除视频文件
|
|
|
const handleVideoRemove = () => {
|
|
|
setVideoFile(null);
|
|
@@ -356,7 +394,6 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
isUploaded: false,
|
|
|
isError: false
|
|
|
});
|
|
|
- stopSpeedMonitoring();
|
|
|
if (videoUploader) {
|
|
|
videoUploader.cancelUpload();
|
|
|
}
|
|
@@ -409,7 +446,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
}}
|
|
|
footer={null}
|
|
|
width={800}
|
|
|
- title="上传视频"
|
|
|
+ title={isEditMode ? "修改视频" : "上传视频"}
|
|
|
destroyOnHidden
|
|
|
>
|
|
|
<div className={styles['upload-video-modal']}>
|
|
@@ -459,14 +496,13 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
<div style={{ flex: 1 }}>
|
|
|
<div className={styles['progress-info']}>
|
|
|
<span className={styles['file-name']}>{videoFile.name}</span>
|
|
|
- {videoUploadSpeed && <span className={styles['upload-speed']}>{videoUploadSpeed}</span>}
|
|
|
</div>
|
|
|
<Progress
|
|
|
percent={videoUploadProgress}
|
|
|
status={videoUploadStatus.isError ? 'exception' : 'active'}
|
|
|
strokeColor={videoUploadStatus.isError ? '#F2584F' : '#FF4383'}
|
|
|
/>
|
|
|
- <div className={styles['progress-text']}>{getVideoProgressText()}</div>
|
|
|
+ {!isEditMode ? <div className={styles['progress-text']}>{getVideoProgressText()}</div> : null}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -500,7 +536,7 @@ const UploadVideoModal: React.FC<UploadVideoModalProps> = ({
|
|
|
)}
|
|
|
</Upload>
|
|
|
|
|
|
- {getCoverProgressText() && (
|
|
|
+ {!isEditMode && getCoverProgressText() && (
|
|
|
<div className={styles['progress-text']}>{getCoverProgressText()}</div>
|
|
|
)}
|
|
|
</div>
|