style: 统一项目代码风格与中文文本规范
本次提交完成以下调整: 1. 在main.tsx中添加Arco Design适配React19的适配器导入,修复命令式组件兼容问题 2. 全项目替换单引号为双引号,统一代码格式化风格 3. 重构所有JSX组件的多行写法,拆分复杂属性提升可读性 4. 修正部分组件的代码缩进与换行规范
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@@ -16,36 +16,38 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
Tag,
|
Tag,
|
||||||
} from '@arco-design/web-react';
|
} from "@arco-design/web-react";
|
||||||
import { IconArrowLeft, IconPlus, IconRefresh } from '@arco-design/web-react/icon';
|
import {
|
||||||
import type { ApiResponse, Drama, Episode, UploadTask } from '../api/types';
|
IconArrowLeft,
|
||||||
import { api } from '../api/client';
|
IconPlus,
|
||||||
import { usePageData } from '../hooks/usePageData';
|
IconRefresh,
|
||||||
|
} from "@arco-design/web-react/icon";
|
||||||
|
import type { ApiResponse, Drama, Episode, UploadTask } from "../api/types";
|
||||||
|
import { api } from "../api/client";
|
||||||
|
import { usePageData } from "../hooks/usePageData";
|
||||||
|
|
||||||
const { Row, Col } = Grid;
|
const { Row, Col } = Grid;
|
||||||
|
|
||||||
const TYPE_OPTIONS = ['revenge', 'romance', 'action'];
|
|
||||||
|
|
||||||
const STATUS_OPTIONS: { value: string; label: string }[] = [
|
const STATUS_OPTIONS: { value: string; label: string }[] = [
|
||||||
{ value: 'draft', label: '草稿' },
|
{ value: "draft", label: "草稿" },
|
||||||
{ value: 'scheduled', label: '定时发布' },
|
{ value: "scheduled", label: "定时发布" },
|
||||||
{ value: 'published', label: '已发布' },
|
{ value: "published", label: "已发布" },
|
||||||
{ value: 'offline', label: '已下线' },
|
{ value: "offline", label: "已下线" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const REVIEW_STATUS_LABEL: Record<string, string> = {
|
const REVIEW_STATUS_LABEL: Record<string, string> = {
|
||||||
not_submitted: '未提交',
|
not_submitted: "未提交",
|
||||||
pending: '待审核',
|
pending: "待审核",
|
||||||
reviewing: '审核中',
|
reviewing: "审核中",
|
||||||
approved: '已通过',
|
approved: "已通过",
|
||||||
rejected: '已拒绝',
|
rejected: "已拒绝",
|
||||||
};
|
};
|
||||||
|
|
||||||
const PUBLISH_STATUS_LABEL: Record<string, string> = {
|
const PUBLISH_STATUS_LABEL: Record<string, string> = {
|
||||||
draft: '草稿',
|
draft: "草稿",
|
||||||
scheduled: '定时发布',
|
scheduled: "定时发布",
|
||||||
published: '已发布',
|
published: "已发布",
|
||||||
offline: '已下线',
|
offline: "已下线",
|
||||||
};
|
};
|
||||||
|
|
||||||
function DramasPage() {
|
function DramasPage() {
|
||||||
@@ -60,15 +62,15 @@ function DramasPage() {
|
|||||||
|
|
||||||
function DramaListPage() {
|
function DramaListPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data, loading, reload } = usePageData<Drama>('/api/admin/v1/dramas');
|
const { data, loading, reload } = usePageData<Drama>("/api/admin/v1/dramas");
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [creating, setCreating] = useState(false);
|
const [creating, setCreating] = useState(false);
|
||||||
|
|
||||||
const createDrama = async (values: Partial<Drama>) => {
|
const createDrama = async (values: Partial<Drama>) => {
|
||||||
setCreating(true);
|
setCreating(true);
|
||||||
try {
|
try {
|
||||||
await api.post('/api/admin/v1/dramas', values);
|
await api.post("/api/admin/v1/dramas", values);
|
||||||
Message.success('短剧创建成功');
|
Message.success("短剧创建成功");
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
await reload();
|
await reload();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -77,23 +79,80 @@ function DramaListPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="section-card" title="短剧管理" extra={<Button type="primary" icon={<IconPlus />} onClick={() => setVisible(true)}>新增短剧</Button>}>
|
<Card
|
||||||
<Table rowKey="id" loading={loading} data={data.list} pagination={{ total: data.pagination.total, pageSize: data.pagination.pageSize }} columns={[
|
className="section-card"
|
||||||
{ title: 'ID', dataIndex: 'id', width: 80 },
|
title="短剧管理"
|
||||||
{ title: '标题', dataIndex: 'title' },
|
extra={
|
||||||
{ title: '地区', dataIndex: 'region', width: 120 },
|
<Button
|
||||||
{ title: '类型', dataIndex: 'type', width: 140 },
|
type="primary"
|
||||||
{ title: '总集数', dataIndex: 'totalEpisodes', width: 100 },
|
icon={<IconPlus />}
|
||||||
{ title: '已发布', dataIndex: 'publishedEpisodes', width: 100 },
|
onClick={() => setVisible(true)}
|
||||||
{ title: '状态', dataIndex: 'status', width: 120, render: (status) => <Tag color={status === 'published' ? 'green' : 'gray'}>{PUBLISH_STATUS_LABEL[String(status)] || String(status)}</Tag> },
|
>
|
||||||
{ title: '推荐', dataIndex: 'isRecommended', width: 100, render: (value) => value ? <Tag color="arcoblue">是</Tag> : <Tag>否</Tag> },
|
新增短剧
|
||||||
{ title: '操作', width: 120, render: (_, record) => <Button type="text" onClick={() => navigate(`/dramas/${record.id}`)}>详情</Button> },
|
</Button>
|
||||||
]} />
|
}
|
||||||
<Modal title="创建短剧" visible={visible} onCancel={() => setVisible(false)} footer={null} style={{ width: 640 }}>
|
>
|
||||||
|
<Table
|
||||||
|
rowKey="id"
|
||||||
|
loading={loading}
|
||||||
|
data={data.list}
|
||||||
|
pagination={{
|
||||||
|
total: data.pagination.total,
|
||||||
|
pageSize: data.pagination.pageSize,
|
||||||
|
}}
|
||||||
|
columns={[
|
||||||
|
{ title: "ID", dataIndex: "id", width: 80 },
|
||||||
|
{ title: "标题", dataIndex: "title" },
|
||||||
|
{ title: "地区", dataIndex: "region", width: 120 },
|
||||||
|
{ title: "类型", dataIndex: "type", width: 140 },
|
||||||
|
{ title: "总集数", dataIndex: "totalEpisodes", width: 100 },
|
||||||
|
{ title: "已发布", dataIndex: "publishedEpisodes", width: 100 },
|
||||||
|
{
|
||||||
|
title: "状态",
|
||||||
|
dataIndex: "status",
|
||||||
|
width: 120,
|
||||||
|
render: (status) => (
|
||||||
|
<Tag color={status === "published" ? "green" : "gray"}>
|
||||||
|
{PUBLISH_STATUS_LABEL[String(status)] || String(status)}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "推荐",
|
||||||
|
dataIndex: "isRecommended",
|
||||||
|
width: 100,
|
||||||
|
render: (value) =>
|
||||||
|
value ? <Tag color="arcoblue">是</Tag> : <Tag>否</Tag>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 120,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
onClick={() => navigate(`/dramas/${record.id}`)}
|
||||||
|
>
|
||||||
|
详情
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
title="创建短剧"
|
||||||
|
visible={visible}
|
||||||
|
onCancel={() => setVisible(false)}
|
||||||
|
footer={null}
|
||||||
|
style={{ width: 640 }}
|
||||||
|
>
|
||||||
<Form
|
<Form
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
onSubmit={createDrama}
|
onSubmit={createDrama}
|
||||||
initialValues={{ status: 'draft', isRecommended: false, sortOrder: 0 }}
|
initialValues={{
|
||||||
|
status: "draft",
|
||||||
|
isRecommended: false,
|
||||||
|
sortOrder: 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Form.Item label="标题" field="title" rules={[{ required: true }]}>
|
<Form.Item label="标题" field="title" rules={[{ required: true }]}>
|
||||||
<Input placeholder="请输入短剧标题" />
|
<Input placeholder="请输入短剧标题" />
|
||||||
@@ -101,24 +160,33 @@ function DramaListPage() {
|
|||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item label="类型" field="type" rules={[{ required: true }]}>
|
<Form.Item label="类型" field="type" rules={[{ required: true }]}>
|
||||||
<Select placeholder="选择或输入类型" allowCreate>
|
<Input placeholder="请输入类型" />
|
||||||
{TYPE_OPTIONS.map((type) => <Select.Option key={type} value={type}>{type}</Select.Option>)}
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item label="状态" field="status">
|
<Form.Item label="状态" field="status">
|
||||||
<Select placeholder="请选择状态">
|
<Select placeholder="请选择状态">
|
||||||
{STATUS_OPTIONS.map((option) => <Select.Option key={option.value} value={option.value}>{option.label}</Select.Option>)}
|
{STATUS_OPTIONS.map((option) => (
|
||||||
|
<Select.Option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Form.Item label="封面地址" field="coverUrl" rules={[{ required: true }]}>
|
<Form.Item
|
||||||
|
label="封面地址"
|
||||||
|
field="coverUrl"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
<Input placeholder="请输入封面图片 URL" />
|
<Input placeholder="请输入封面图片 URL" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="简介" field="description">
|
<Form.Item label="简介" field="description">
|
||||||
<Input.TextArea placeholder="请输入短剧简介" autoSize={{ minRows: 2, maxRows: 4 }} />
|
<Input.TextArea
|
||||||
|
placeholder="请输入短剧简介"
|
||||||
|
autoSize={{ minRows: 2, maxRows: 4 }}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="标签" field="tags">
|
<Form.Item label="标签" field="tags">
|
||||||
<InputTag placeholder="输入后回车添加标签" allowClear />
|
<InputTag placeholder="输入后回车添加标签" allowClear />
|
||||||
@@ -136,25 +204,38 @@ function DramaListPage() {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item label="年份" field="year">
|
<Form.Item label="年份" field="year">
|
||||||
<InputNumber placeholder="如 2026" min={1900} style={{ width: '100%' }} />
|
<InputNumber
|
||||||
|
placeholder="如 2026"
|
||||||
|
min={1900}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item label="排序权重" field="sortOrder">
|
<Form.Item label="排序权重" field="sortOrder">
|
||||||
<InputNumber placeholder="数值越大越靠前" style={{ width: '100%' }} />
|
<InputNumber
|
||||||
|
placeholder="数值越大越靠前"
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Form.Item label="推荐" field="isRecommended" triggerPropName="checked">
|
<Form.Item
|
||||||
|
label="推荐"
|
||||||
|
field="isRecommended"
|
||||||
|
triggerPropName="checked"
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<div className="modal-actions">
|
<div className="modal-actions">
|
||||||
<Button onClick={() => setVisible(false)}>取消</Button>
|
<Button onClick={() => setVisible(false)}>取消</Button>
|
||||||
<Button type="primary" htmlType="submit" loading={creating}>创建</Button>
|
<Button type="primary" htmlType="submit" loading={creating}>
|
||||||
|
创建
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
@@ -168,14 +249,18 @@ function DramaDetailPage({ dramaId }: { dramaId: number }) {
|
|||||||
const [episodes, setEpisodes] = useState<Episode[]>([]);
|
const [episodes, setEpisodes] = useState<Episode[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [episodeCount, setEpisodeCount] = useState(1);
|
const [episodeCount, setEpisodeCount] = useState(1);
|
||||||
const [uploadingEpisodeId, setUploadingEpisodeId] = useState<number | null>(null);
|
const [uploadingEpisodeId, setUploadingEpisodeId] = useState<number | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
const loadDetail = async () => {
|
const loadDetail = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const [dramaResponse, episodeResponse] = await Promise.all([
|
const [dramaResponse, episodeResponse] = await Promise.all([
|
||||||
api.get<ApiResponse<Drama>>(`/api/admin/v1/dramas/${dramaId}`),
|
api.get<ApiResponse<Drama>>(`/api/admin/v1/dramas/${dramaId}`),
|
||||||
api.get<ApiResponse<{ list: Episode[] }>>(`/api/admin/v1/dramas/${dramaId}/episodes?pageSize=200`),
|
api.get<ApiResponse<{ list: Episode[] }>>(
|
||||||
|
`/api/admin/v1/dramas/${dramaId}/episodes?pageSize=200`,
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
setDrama(dramaResponse.data.data);
|
setDrama(dramaResponse.data.data);
|
||||||
setEpisodeCount(dramaResponse.data.data.totalEpisodes || 1);
|
setEpisodeCount(dramaResponse.data.data.totalEpisodes || 1);
|
||||||
@@ -190,29 +275,37 @@ function DramaDetailPage({ dramaId }: { dramaId: number }) {
|
|||||||
}, [dramaId]);
|
}, [dramaId]);
|
||||||
|
|
||||||
const configureEpisodes = async () => {
|
const configureEpisodes = async () => {
|
||||||
await api.post(`/api/admin/v1/dramas/${dramaId}/episodes/batch`, { episodeCount });
|
await api.post(`/api/admin/v1/dramas/${dramaId}/episodes/batch`, {
|
||||||
Message.success('剧集数量已更新');
|
episodeCount,
|
||||||
|
});
|
||||||
|
Message.success("剧集数量已更新");
|
||||||
await loadDetail();
|
await loadDetail();
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateDramaStatus = async (status: string) => {
|
const updateDramaStatus = async (status: string) => {
|
||||||
await api.patch(`/api/admin/v1/dramas/${dramaId}`, { status });
|
await api.patch(`/api/admin/v1/dramas/${dramaId}`, { status });
|
||||||
Message.success('短剧状态已更新');
|
Message.success("短剧状态已更新");
|
||||||
await loadDetail();
|
await loadDetail();
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadEpisodeVideo = async (episode: Episode, file: File) => {
|
const uploadEpisodeVideo = async (episode: Episode, file: File) => {
|
||||||
setUploadingEpisodeId(episode.id);
|
setUploadingEpisodeId(episode.id);
|
||||||
try {
|
try {
|
||||||
const task = await api.post<ApiResponse<UploadTask>>('/api/admin/v1/media/upload-tasks', {
|
const task = await api.post<ApiResponse<UploadTask>>(
|
||||||
episodeId: episode.id,
|
"/api/admin/v1/media/upload-tasks",
|
||||||
fileName: file.name,
|
{
|
||||||
contentType: file.type || 'video/mp4',
|
episodeId: episode.id,
|
||||||
fileSize: file.size,
|
fileName: file.name,
|
||||||
});
|
contentType: file.type || "video/mp4",
|
||||||
await api.patch(`/api/admin/v1/media/upload-tasks/${task.data.data.jobId}/complete`, {});
|
fileSize: file.size,
|
||||||
await api.post('/api/admin/v1/media/review-status/sync', {});
|
},
|
||||||
Message.success('视频上传并审核通过');
|
);
|
||||||
|
await api.patch(
|
||||||
|
`/api/admin/v1/media/upload-tasks/${task.data.data.jobId}/complete`,
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
await api.post("/api/admin/v1/media/review-status/sync", {});
|
||||||
|
Message.success("视频上传并审核通过");
|
||||||
await loadDetail();
|
await loadDetail();
|
||||||
} finally {
|
} finally {
|
||||||
setUploadingEpisodeId(null);
|
setUploadingEpisodeId(null);
|
||||||
@@ -221,10 +314,10 @@ function DramaDetailPage({ dramaId }: { dramaId: number }) {
|
|||||||
|
|
||||||
const publishEpisode = async (episode: Episode) => {
|
const publishEpisode = async (episode: Episode) => {
|
||||||
await api.patch(`/api/admin/v1/episodes/${episode.id}`, {
|
await api.patch(`/api/admin/v1/episodes/${episode.id}`, {
|
||||||
publishStatus: 'published',
|
publishStatus: "published",
|
||||||
status: 'published',
|
status: "published",
|
||||||
});
|
});
|
||||||
Message.success('剧集已发布');
|
Message.success("剧集已发布");
|
||||||
await loadDetail();
|
await loadDetail();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -233,70 +326,150 @@ function DramaDetailPage({ dramaId }: { dramaId: number }) {
|
|||||||
<Card
|
<Card
|
||||||
className="section-card"
|
className="section-card"
|
||||||
loading={loading && !drama}
|
loading={loading && !drama}
|
||||||
title={<Space><Button icon={<IconArrowLeft />} onClick={() => navigate('/dramas')} />短剧详情</Space>}
|
title={
|
||||||
extra={<Space>
|
<Space>
|
||||||
<Button icon={<IconRefresh />} onClick={loadDetail}>刷新</Button>
|
<Button
|
||||||
<Button onClick={() => updateDramaStatus('draft')}>设为草稿</Button>
|
icon={<IconArrowLeft />}
|
||||||
<Button type="primary" onClick={() => updateDramaStatus('published')}>上架短剧</Button>
|
onClick={() => navigate("/dramas")}
|
||||||
</Space>}
|
/>
|
||||||
|
短剧详情
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
extra={
|
||||||
|
<Space>
|
||||||
|
<Button icon={<IconRefresh />} onClick={loadDetail}>
|
||||||
|
刷新
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => updateDramaStatus("draft")}>设为草稿</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => updateDramaStatus("published")}
|
||||||
|
>
|
||||||
|
上架短剧
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{drama && (
|
{drama && (
|
||||||
<Descriptions
|
<Descriptions
|
||||||
column={3}
|
column={3}
|
||||||
data={[
|
data={[
|
||||||
{ label: '短剧ID', value: drama.id },
|
{ label: "短剧ID", value: drama.id },
|
||||||
{ label: '名称', value: drama.title },
|
{ label: "名称", value: drama.title },
|
||||||
{ label: '地区', value: drama.region || '-' },
|
{ label: "地区", value: drama.region || "-" },
|
||||||
{ label: '类型', value: drama.type },
|
{ label: "类型", value: drama.type },
|
||||||
{ label: '总集数', value: drama.totalEpisodes || 0 },
|
{ label: "总集数", value: drama.totalEpisodes || 0 },
|
||||||
{ label: '已发布集数', value: drama.publishedEpisodes || 0 },
|
{ label: "已发布集数", value: drama.publishedEpisodes || 0 },
|
||||||
{ label: '状态', value: PUBLISH_STATUS_LABEL[drama.status] || drama.status },
|
{
|
||||||
{ label: '封面', value: drama.coverUrl },
|
label: "状态",
|
||||||
{ label: '简介', value: drama.description || '-' },
|
value: PUBLISH_STATUS_LABEL[drama.status] || drama.status,
|
||||||
|
},
|
||||||
|
{ label: "封面", value: drama.coverUrl },
|
||||||
|
{ label: "简介", value: drama.description || "-" },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card className="section-card" title="剧集配置" extra={<Space>
|
<Card
|
||||||
<InputNumber min={1} max={500} value={episodeCount} onChange={(value) => setEpisodeCount(Number(value) || 1)} />
|
className="section-card"
|
||||||
<Button type="primary" onClick={configureEpisodes}>保存集数</Button>
|
title="剧集配置"
|
||||||
</Space>}>
|
extra={
|
||||||
<Table rowKey="id" loading={loading} data={episodes} pagination={false} columns={[
|
<Space>
|
||||||
{ title: '集数', dataIndex: 'episodeNo', width: 80 },
|
<InputNumber
|
||||||
{ title: '标题', dataIndex: 'title' },
|
min={1}
|
||||||
{ title: 'BytePlus VID', dataIndex: 'byteplusVid', width: 180, render: (value) => value || '-' },
|
max={500}
|
||||||
{ title: '尺寸', width: 120, render: (_, record) => record.width && record.height ? `${record.width}x${record.height}` : '-' },
|
value={episodeCount}
|
||||||
{ title: '时长', dataIndex: 'durationSeconds', width: 100, render: (value) => value ? `${value}s` : '-' },
|
onChange={(value) => setEpisodeCount(Number(value) || 1)}
|
||||||
{ title: '审核状态', dataIndex: 'reviewStatus', width: 120, render: (status) => <Tag color={status === 'approved' ? 'green' : 'orange'}>{REVIEW_STATUS_LABEL[String(status)] || String(status)}</Tag> },
|
/>
|
||||||
{ title: '发布状态', dataIndex: 'publishStatus', width: 120, render: (status) => <Tag color={status === 'published' ? 'green' : 'gray'}>{PUBLISH_STATUS_LABEL[String(status)] || String(status)}</Tag> },
|
<Button type="primary" onClick={configureEpisodes}>
|
||||||
{
|
保存集数
|
||||||
title: '操作',
|
</Button>
|
||||||
width: 280,
|
</Space>
|
||||||
render: (_, record) => (
|
}
|
||||||
<Space>
|
>
|
||||||
<Button loading={uploadingEpisodeId === record.id}>
|
<Table
|
||||||
<label>
|
rowKey="id"
|
||||||
上传视频
|
loading={loading}
|
||||||
<input
|
data={episodes}
|
||||||
type="file"
|
pagination={false}
|
||||||
accept="video/*"
|
columns={[
|
||||||
style={{ display: 'none' }}
|
{ title: "集数", dataIndex: "episodeNo", width: 80 },
|
||||||
onChange={(event) => {
|
{ title: "标题", dataIndex: "title" },
|
||||||
const file = event.target.files?.[0];
|
{
|
||||||
if (file) {
|
title: "BytePlus VID",
|
||||||
void uploadEpisodeVideo(record, file);
|
dataIndex: "byteplusVid",
|
||||||
}
|
width: 180,
|
||||||
event.target.value = '';
|
render: (value) => value || "-",
|
||||||
}}
|
},
|
||||||
/>
|
{
|
||||||
</label>
|
title: "尺寸",
|
||||||
</Button>
|
width: 120,
|
||||||
<Button type="text" disabled={record.reviewStatus !== 'approved'} onClick={() => publishEpisode(record)}>发布</Button>
|
render: (_, record) =>
|
||||||
</Space>
|
record.width && record.height
|
||||||
),
|
? `${record.width}x${record.height}`
|
||||||
},
|
: "-",
|
||||||
]} />
|
},
|
||||||
|
{
|
||||||
|
title: "时长",
|
||||||
|
dataIndex: "durationSeconds",
|
||||||
|
width: 100,
|
||||||
|
render: (value) => (value ? `${value}s` : "-"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "审核状态",
|
||||||
|
dataIndex: "reviewStatus",
|
||||||
|
width: 120,
|
||||||
|
render: (status) => (
|
||||||
|
<Tag color={status === "approved" ? "green" : "orange"}>
|
||||||
|
{REVIEW_STATUS_LABEL[String(status)] || String(status)}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "发布状态",
|
||||||
|
dataIndex: "publishStatus",
|
||||||
|
width: 120,
|
||||||
|
render: (status) => (
|
||||||
|
<Tag color={status === "published" ? "green" : "gray"}>
|
||||||
|
{PUBLISH_STATUS_LABEL[String(status)] || String(status)}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
width: 280,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Space>
|
||||||
|
<Button loading={uploadingEpisodeId === record.id}>
|
||||||
|
<label>
|
||||||
|
上传视频
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="video/*"
|
||||||
|
style={{ display: "none" }}
|
||||||
|
onChange={(event) => {
|
||||||
|
const file = event.target.files?.[0];
|
||||||
|
if (file) {
|
||||||
|
void uploadEpisodeVideo(record, file);
|
||||||
|
}
|
||||||
|
event.target.value = "";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
disabled={record.reviewStatus !== "approved"}
|
||||||
|
onClick={() => publishEpisode(record)}
|
||||||
|
>
|
||||||
|
发布
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// 让 Arco 的命令式组件(Message/Notification/Modal.confirm 等)在 React 18/19 下
|
||||||
|
// 使用 react-dom/client 的 createRoot,而非已被移除的 ReactDOM.render。必须在使用 Arco 前引入。
|
||||||
|
import '@arco-design/web-react/es/_util/react-19-adapter';
|
||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import '@arco-design/web-react/dist/css/arco.css';
|
import '@arco-design/web-react/dist/css/arco.css';
|
||||||
|
|||||||
Reference in New Issue
Block a user