feat: 完善短剧管理后台功能,新增编辑、详情展示优化
1. 重构接口类型定义,新增创建/更新短剧和剧集的载荷类型 2. 新增表单数据转换工具,规范化表单提交参数 3. 优化短剧列表展示,新增封面图和更清晰的集数统计 4. 新增短剧和剧集的编辑弹窗功能 5. 修复测试文件导入路径和README标题 6. 优化角色管理页面的表单提示样式
This commit is contained in:
@@ -1,11 +1,21 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button, Card, Descriptions, InputNumber, Message, Space } from "@arco-design/web-react";
|
||||
import { Button, Card, Descriptions, Form, Grid, Input, InputNumber, InputTag, Message, Modal, Select, Space, Switch } from "@arco-design/web-react";
|
||||
import { IconArrowLeft, IconRefresh } from "@arco-design/web-react/icon";
|
||||
import { dramaApi, mediaApi } from "../../api";
|
||||
import { toDramaPayload, toEpisodePayload } from "../formPayload";
|
||||
import type { Drama, DramaDetailPageProps, Episode } from "../interface";
|
||||
import { EpisodeTable } from "./EpisodeTable";
|
||||
|
||||
const { Row, Col } = Grid;
|
||||
|
||||
const STATUS_OPTIONS = [
|
||||
{ value: "draft", label: "草稿" },
|
||||
{ value: "scheduled", label: "定时发布" },
|
||||
{ value: "published", label: "已发布" },
|
||||
{ value: "offline", label: "已下线" },
|
||||
];
|
||||
|
||||
const PUBLISH_STATUS_LABEL: Record<string, string> = {
|
||||
draft: "草稿",
|
||||
scheduled: "定时发布",
|
||||
@@ -20,6 +30,8 @@ export function DramaDetail({ dramaId }: DramaDetailPageProps) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [episodeCount, setEpisodeCount] = useState(1);
|
||||
const [uploadingEpisodeId, setUploadingEpisodeId] = useState<number | null>(null);
|
||||
const [editVisible, setEditVisible] = useState(false);
|
||||
const [updatingDrama, setUpdatingDrama] = useState(false);
|
||||
|
||||
const loadDetail = async () => {
|
||||
setLoading(true);
|
||||
@@ -49,6 +61,18 @@ export function DramaDetail({ dramaId }: DramaDetailPageProps) {
|
||||
await loadDetail();
|
||||
};
|
||||
|
||||
const updateDrama = async (values: Partial<Drama>) => {
|
||||
setUpdatingDrama(true);
|
||||
try {
|
||||
await dramaApi.updateDrama(dramaId, toDramaPayload(values));
|
||||
Message.success("短剧信息已更新");
|
||||
setEditVisible(false);
|
||||
await loadDetail();
|
||||
} finally {
|
||||
setUpdatingDrama(false);
|
||||
}
|
||||
};
|
||||
|
||||
const uploadEpisodeVideo = async (episode: Episode, file: File) => {
|
||||
setUploadingEpisodeId(episode.id);
|
||||
try {
|
||||
@@ -76,6 +100,12 @@ export function DramaDetail({ dramaId }: DramaDetailPageProps) {
|
||||
await loadDetail();
|
||||
};
|
||||
|
||||
const updateEpisode = async (episode: Episode, values: Partial<Episode>) => {
|
||||
await dramaApi.updateDramaEpisode(dramaId, episode.id, toEpisodePayload(values));
|
||||
Message.success("剧集信息已更新");
|
||||
await loadDetail();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="page-stack">
|
||||
<Card
|
||||
@@ -92,6 +122,9 @@ export function DramaDetail({ dramaId }: DramaDetailPageProps) {
|
||||
<Button icon={<IconRefresh />} onClick={loadDetail}>
|
||||
刷新
|
||||
</Button>
|
||||
<Button disabled={!drama} onClick={() => setEditVisible(true)}>
|
||||
编辑短剧
|
||||
</Button>
|
||||
<Button onClick={() => updateDramaStatus("draft")}>设为草稿</Button>
|
||||
<Button type="primary" onClick={() => updateDramaStatus("published")}>
|
||||
上架短剧
|
||||
@@ -135,8 +168,104 @@ export function DramaDetail({ dramaId }: DramaDetailPageProps) {
|
||||
uploadingEpisodeId={uploadingEpisodeId}
|
||||
onUploadVideo={uploadEpisodeVideo}
|
||||
onPublishEpisode={publishEpisode}
|
||||
onUpdateEpisode={updateEpisode}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
{drama && (
|
||||
<Modal title="编辑短剧" visible={editVisible} onCancel={() => setEditVisible(false)} footer={null} style={{ width: 720 }}>
|
||||
<Form
|
||||
key={drama.id}
|
||||
layout="vertical"
|
||||
onSubmit={updateDrama}
|
||||
initialValues={{
|
||||
title: drama.title,
|
||||
type: drama.type,
|
||||
status: drama.status,
|
||||
coverUrl: drama.coverUrl,
|
||||
description: drama.description,
|
||||
tags: drama.tags,
|
||||
region: drama.region,
|
||||
language: drama.language,
|
||||
year: drama.year,
|
||||
sortOrder: drama.sortOrder,
|
||||
isRecommended: drama.isRecommended,
|
||||
totalEpisodes: drama.totalEpisodes || 1,
|
||||
}}
|
||||
>
|
||||
<Form.Item label="标题" field="title" rules={[{ required: true }]}>
|
||||
<Input placeholder="请输入短剧标题" />
|
||||
</Form.Item>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item label="类型" field="type" rules={[{ required: true }]}>
|
||||
<Input placeholder="请输入类型" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item label="状态" field="status">
|
||||
<Select>
|
||||
{STATUS_OPTIONS.map((option) => (
|
||||
<Select.Option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Form.Item label="封面地址" field="coverUrl" rules={[{ required: true }]}>
|
||||
<Input placeholder="请输入封面图片 URL" />
|
||||
</Form.Item>
|
||||
<Form.Item label="简介" field="description">
|
||||
<Input.TextArea placeholder="请输入短剧简介" autoSize={{ minRows: 2, maxRows: 4 }} />
|
||||
</Form.Item>
|
||||
<Form.Item label="标签" field="tags">
|
||||
<InputTag placeholder="输入后回车添加标签" allowClear />
|
||||
</Form.Item>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Item label="地区" field="region">
|
||||
<Input placeholder="如 中国" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="语言" field="language">
|
||||
<Input placeholder="如 zh-CN" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="年份" field="year">
|
||||
<InputNumber min={1900} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Item label="排序权重" field="sortOrder">
|
||||
<InputNumber style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="剧集总数" field="totalEpisodes" rules={[{ required: true }]}>
|
||||
<InputNumber min={1} max={500} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="推荐" field="isRecommended" triggerPropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="modal-actions">
|
||||
<Button onClick={() => setEditVisible(false)}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={updatingDrama}>
|
||||
保存
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user