|
|
@@ -1,7 +1,11 @@
|
|
|
import React, { useRef, useState } from "react";
|
|
|
-import { Button, Card, message, Progress, Space, Tag } from "antd";
|
|
|
import TcVod from "vod-js-sdk-v6";
|
|
|
+import { toast } from "sonner";
|
|
|
import { vodClient } from "@/client/api";
|
|
|
+import { Button } from "@/client/components/ui/button";
|
|
|
+import { Card, CardContent, CardHeader, CardTitle } from "@/client/components/ui/card";
|
|
|
+import { Progress } from "@/client/components/ui/progress";
|
|
|
+import { Badge } from "@/client/components/ui/badge";
|
|
|
|
|
|
interface UploadTask {
|
|
|
file: File;
|
|
|
@@ -38,7 +42,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
const { signature } = await response.json();
|
|
|
return signature;
|
|
|
} catch (error) {
|
|
|
- message.error("获取上传签名失败");
|
|
|
+ toast.error("获取上传签名失败");
|
|
|
throw error;
|
|
|
}
|
|
|
};
|
|
|
@@ -65,7 +69,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
// 开始上传
|
|
|
const startUpload = async () => {
|
|
|
if (!selectedVideo) {
|
|
|
- message.warning("请先选择视频文件");
|
|
|
+ toast.warning("请先选择视频文件");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -139,7 +143,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
)
|
|
|
);
|
|
|
|
|
|
- message.success("视频上传成功");
|
|
|
+ toast.success("视频上传成功");
|
|
|
|
|
|
// 调用成功回调
|
|
|
if (onUploadSuccess) {
|
|
|
@@ -155,7 +159,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
task.file === newTask.file ? { ...task, status: "error" } : task
|
|
|
)
|
|
|
);
|
|
|
- message.error("视频上传失败");
|
|
|
+ toast.error("视频上传失败");
|
|
|
|
|
|
// 调用错误回调
|
|
|
if (onUploadError) {
|
|
|
@@ -173,34 +177,37 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
const renderStatusTag = (status: UploadTask["status"]) => {
|
|
|
switch (status) {
|
|
|
case "pending":
|
|
|
- return <Tag color="default">等待上传</Tag>;
|
|
|
+ return <Badge variant="outline">等待上传</Badge>;
|
|
|
case "uploading":
|
|
|
- return <Tag color="processing">上传中</Tag>;
|
|
|
+ return <Badge variant="secondary">上传中</Badge>;
|
|
|
case "success":
|
|
|
- return <Tag color="success">上传成功</Tag>;
|
|
|
+ return <Badge variant="default">上传成功</Badge>;
|
|
|
case "error":
|
|
|
- return <Tag color="error">上传失败</Tag>;
|
|
|
+ return <Badge variant="destructive">上传失败</Badge>;
|
|
|
case "canceled":
|
|
|
- return <Tag color="warning">已取消</Tag>;
|
|
|
+ return <Badge variant="outline">已取消</Badge>;
|
|
|
default:
|
|
|
- return <Tag color="default">未知状态</Tag>;
|
|
|
+ return <Badge variant="outline">未知状态</Badge>;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
return (
|
|
|
- <Card title="视频上传" className="mb-4">
|
|
|
- <Space direction="vertical" style={{ width: "100%" }}>
|
|
|
- <div>
|
|
|
+ <Card className="mb-6">
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle>视频上传</CardTitle>
|
|
|
+ </CardHeader>
|
|
|
+ <CardContent className="space-y-4">
|
|
|
+ <div className="flex flex-wrap items-center gap-3">
|
|
|
<input
|
|
|
type="file"
|
|
|
ref={videoInputRef}
|
|
|
onChange={handleVideoSelect}
|
|
|
accept="video/*"
|
|
|
- style={{ display: "none" }}
|
|
|
+ className="hidden"
|
|
|
/>
|
|
|
<Button
|
|
|
onClick={() => videoInputRef.current?.click()}
|
|
|
- type="primary"
|
|
|
+ variant="default"
|
|
|
>
|
|
|
{selectedVideo ? selectedVideo.name : "选择视频文件"}
|
|
|
</Button>
|
|
|
@@ -210,48 +217,46 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
ref={coverInputRef}
|
|
|
onChange={handleCoverSelect}
|
|
|
accept="image/*"
|
|
|
- style={{ display: "none", marginLeft: 16 }}
|
|
|
+ className="hidden"
|
|
|
/>
|
|
|
<Button
|
|
|
onClick={() => coverInputRef.current?.click()}
|
|
|
- style={{ marginLeft: 16 }}
|
|
|
+ variant="outline"
|
|
|
>
|
|
|
{selectedCover ? selectedCover.name : "选择封面(可选)"}
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
- type="primary"
|
|
|
onClick={startUpload}
|
|
|
disabled={!selectedVideo}
|
|
|
- style={{ marginLeft: 16 }}
|
|
|
>
|
|
|
开始上传
|
|
|
</Button>
|
|
|
</div>
|
|
|
|
|
|
- <div style={{ marginTop: 24 }}>
|
|
|
+ <div className="space-y-4">
|
|
|
{uploadTasks.map((task, index) => (
|
|
|
- <div key={index} style={{ marginBottom: 16 }}>
|
|
|
- <div style={{ marginBottom: 8 }}>
|
|
|
- <span style={{ marginRight: 8 }}>{task.file.name}</span>
|
|
|
+ <div key={index} className="border rounded-lg p-4">
|
|
|
+ <div className="flex items-center gap-2 mb-3">
|
|
|
+ <span className="font-medium">{task.file.name}</span>
|
|
|
{renderStatusTag(task.status)}
|
|
|
{task.status === "uploading" && task.cancel && (
|
|
|
<Button
|
|
|
- type="link"
|
|
|
- danger
|
|
|
+ variant="ghost"
|
|
|
+ size="sm"
|
|
|
onClick={task.cancel}
|
|
|
- style={{ marginLeft: 8 }}
|
|
|
+ className="text-destructive hover:text-destructive"
|
|
|
>
|
|
|
取消上传
|
|
|
</Button>
|
|
|
)}
|
|
|
</div>
|
|
|
{task.status === "uploading" && (
|
|
|
- <Progress percent={task.progress} status="active" />
|
|
|
+ <Progress value={task.progress} className="w-full" />
|
|
|
)}
|
|
|
{task.fileId && (
|
|
|
- <div style={{ marginTop: 8 }}>
|
|
|
- <div>File ID: {task.fileId}</div>
|
|
|
+ <div className="space-y-2 text-sm mt-3">
|
|
|
+ <div className="font-medium">File ID: {task.fileId}</div>
|
|
|
{task.videoUrl && (
|
|
|
<div>
|
|
|
视频地址:{" "}
|
|
|
@@ -259,6 +264,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
href={task.videoUrl}
|
|
|
target="_blank"
|
|
|
rel="noreferrer"
|
|
|
+ className="text-primary hover:underline break-all"
|
|
|
>
|
|
|
{task.videoUrl}
|
|
|
</a>
|
|
|
@@ -271,6 +277,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
href={task.coverUrl}
|
|
|
target="_blank"
|
|
|
rel="noreferrer"
|
|
|
+ className="text-primary hover:underline break-all"
|
|
|
>
|
|
|
{task.coverUrl}
|
|
|
</a>
|
|
|
@@ -281,7 +288,7 @@ export const VodUpload: React.FC<VodUploadProps> = ({
|
|
|
</div>
|
|
|
))}
|
|
|
</div>
|
|
|
- </Space>
|
|
|
+ </CardContent>
|
|
|
</Card>
|
|
|
);
|
|
|
};
|