feat: 添加短剧筛选功能和自定义Panel容器组件
1. 新增DramaQuery类型扩展分页查询参数,支持标题、状态、类型筛选 2. 重构usePageData hook,支持自定义查询类型和筛选状态管理 3. 新建Panel通用容器组件替代原生Card 4. 为短剧管理页面添加搜索筛选UI和逻辑 5. 统一所有页面的分页查询默认参数 6. 调整布局样式优化后台管理界面展示
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Button, Card, Form, Grid, Input, InputNumber, InputTag, Message, Modal, Select, Switch, Table, Tag } from "@arco-design/web-react";
|
||||
import { IconPlus } from "@arco-design/web-react/icon";
|
||||
import { Button, Form, Grid, Input, InputNumber, InputTag, Message, Modal, Select, Space, Switch, Table, Tag } from "@arco-design/web-react";
|
||||
import { IconPlus, IconSearch, IconRefresh } from "@arco-design/web-react/icon";
|
||||
import { dramaApi } from "../../api";
|
||||
import type { DramaQuery } from "../../api/interface";
|
||||
import { usePageData } from "../../hooks/usePageData";
|
||||
import { Panel } from "../../components/Panel";
|
||||
import { toDramaPayload } from "../formPayload";
|
||||
import type { Drama, StatusOption } from "../interface";
|
||||
|
||||
@@ -23,11 +25,27 @@ const PUBLISH_STATUS_LABEL: Record<string, string> = {
|
||||
offline: "已下线",
|
||||
};
|
||||
|
||||
const INITIAL_QUERY: DramaQuery = { page: 1, pageSize: 20 };
|
||||
|
||||
export function DramaList() {
|
||||
const navigate = useNavigate();
|
||||
const { data, loading, reload, changePage } = usePageData<Drama>(dramaApi.listDramas);
|
||||
const { data, loading, reload, changePage, setFilter } = usePageData<Drama, DramaQuery>(dramaApi.listDramas, INITIAL_QUERY);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [filterTitle, setFilterTitle] = useState("");
|
||||
const [filterStatus, setFilterStatus] = useState<string | undefined>(undefined);
|
||||
const [filterType, setFilterType] = useState("");
|
||||
|
||||
const handleSearch = () => {
|
||||
setFilter({ title: filterTitle || undefined, status: filterStatus, type: filterType || undefined });
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setFilterTitle("");
|
||||
setFilterStatus(undefined);
|
||||
setFilterType("");
|
||||
setFilter({ title: undefined, status: undefined, type: undefined });
|
||||
};
|
||||
|
||||
const createDrama = async (values: Partial<Drama>) => {
|
||||
setCreating(true);
|
||||
@@ -43,15 +61,59 @@ export function DramaList() {
|
||||
|
||||
return (
|
||||
<div className="page-stack">
|
||||
<Card
|
||||
className="section-card"
|
||||
title="短剧管理"
|
||||
extra={
|
||||
<Button type="primary" icon={<IconPlus />} onClick={() => setVisible(true)}>
|
||||
新增短剧
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Panel title="短剧管理">
|
||||
<Row gutter={16} className="mb-0">
|
||||
<Col span={6}>
|
||||
<div className="text-[13px] text-muted mb-1.5">短剧标题</div>
|
||||
<Input
|
||||
placeholder="搜索短剧标题"
|
||||
value={filterTitle}
|
||||
onChange={setFilterTitle}
|
||||
allowClear
|
||||
/>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<div className="text-[13px] text-muted mb-1.5">状态</div>
|
||||
<Select
|
||||
placeholder="全部状态"
|
||||
value={filterStatus}
|
||||
onChange={setFilterStatus}
|
||||
allowClear
|
||||
>
|
||||
{STATUS_OPTIONS.map((option) => (
|
||||
<Select.Option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<div className="text-[13px] text-muted mb-1.5">类型</div>
|
||||
<Input
|
||||
placeholder="搜索类型"
|
||||
value={filterType}
|
||||
onChange={setFilterType}
|
||||
allowClear
|
||||
/>
|
||||
</Col>
|
||||
<Col span={10}>
|
||||
<div className="text-[13px] mb-1.5"> </div>
|
||||
<Space>
|
||||
<Button type="primary" icon={<IconSearch />} onClick={handleSearch}>
|
||||
查询
|
||||
</Button>
|
||||
<Button icon={<IconRefresh />} onClick={handleReset}>
|
||||
重置
|
||||
</Button>
|
||||
<Button type="primary" status="success" icon={<IconPlus />} onClick={() => setVisible(true)}>
|
||||
新增短剧
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</Panel>
|
||||
|
||||
<Panel>
|
||||
<Table
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
@@ -64,11 +126,11 @@ export function DramaList() {
|
||||
}}
|
||||
columns={[
|
||||
{ title: "ID", dataIndex: "id", width: 80 },
|
||||
{ title: "封面图", dataIndex: "coverUrl", width: 120, render: (value) => (value ? <img src={value} alt="封面图" style={{ width: 100, height: 100, objectFit: "cover" }} /> : null) },
|
||||
{ title: "封面图", dataIndex: "coverUrl", width: 120, render: (value) => (value ? <img src={value} alt="封面图" className="rounded-lg object-cover" style={{ width: 80, height: 80 }} /> : null) },
|
||||
{ title: "标题", dataIndex: "title" },
|
||||
{ title: "地区", dataIndex: "region", width: 120 },
|
||||
{ title: "类型", dataIndex: "type", width: 140 },
|
||||
{ title: "已发布 / 总集数", dataIndex: "totalEpisodes", width: 180, render: (_, record) => `${record.publishedEpisodes}(已发布)/共${record.totalEpisodes}集` },
|
||||
{ title: "已发布 / 总集数", dataIndex: "totalEpisodes", width: 180, render: (_, record) => `${record.publishedEpisodes || 0}(已发布)/共${record.totalEpisodes || 0}集` },
|
||||
{
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
@@ -92,81 +154,82 @@ export function DramaList() {
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Modal title="创建短剧" visible={visible} onCancel={() => setVisible(false)} footer={null} style={{ width: 640 }}>
|
||||
<Form layout="vertical" onSubmit={createDrama} initialValues={{ status: "draft", isRecommended: false, sortOrder: 0, 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 placeholder="请选择状态">
|
||||
{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 placeholder="如 2026" min={1900} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Item label="排序权重" field="sortOrder">
|
||||
<InputNumber placeholder="数值越大越靠前" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="剧集总数" field="totalEpisodes" rules={[{ required: true }]}>
|
||||
<InputNumber min={1} max={500} placeholder="创建剧集占位" 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={() => setVisible(false)}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={creating}>
|
||||
创建
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
</Card>
|
||||
</Panel>
|
||||
|
||||
<Modal title="创建短剧" visible={visible} onCancel={() => setVisible(false)} footer={null} style={{ width: 640 }}>
|
||||
<Form layout="vertical" onSubmit={createDrama} initialValues={{ status: "draft", isRecommended: false, sortOrder: 0, 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 placeholder="请选择状态">
|
||||
{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 placeholder="如 2026" min={1900} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<Form.Item label="排序权重" field="sortOrder">
|
||||
<InputNumber placeholder="数值越大越靠前" style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item label="剧集总数" field="totalEpisodes" rules={[{ required: true }]}>
|
||||
<InputNumber min={1} max={500} placeholder="创建剧集占位" 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={() => setVisible(false)}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={creating}>
|
||||
创建
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user