feat: 完成短剧项目空间与结构化资产创作闭环 (#38)
* feat(canvas): 短剧项目空间 - 建立项目章节与画布关联 MVP * feat(canvas): 短剧项目空间 - 完善项目资产、镜头与流程闭环 Refs #30 * fix(deploy): 本地部署 - 修复前端构建并忽略本地 PostgreSQL 配置 * feat(*): 短剧项目空间 - 完成项目、章节、资产、角色与画布创作闭环 Refs #30 --------- Co-authored-by: ddCat <ddcat666@88.com>
This commit is contained in:
@@ -2,25 +2,29 @@ import { Button, Pagination } from "antd";
|
||||
import { RotateCcw } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import { WorkspaceSignalIcon, type WorkspaceSignalIconVariant } from "@/components/ui/aceternity/workspace-signal-icon";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export function WorkspacePage({ children, className, grid = false }: { children: ReactNode; className?: string; grid?: boolean }) {
|
||||
export function WorkspacePage({ children, className, grid = false, fluid = false }: { children: ReactNode; className?: string; grid?: boolean; fluid?: boolean }) {
|
||||
return (
|
||||
<main className={cn("app-user-content thin-scrollbar h-full overflow-y-auto text-foreground", grid && "app-workspace-grid", className)}>
|
||||
<div className="mx-auto w-full max-w-[1440px] px-4 py-6 sm:px-6 lg:px-8">{children}</div>
|
||||
<div className={fluid ? "h-full w-full" : "w-full px-3 py-3 sm:px-4 sm:py-4 xl:px-5"}>{children}</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
export function PageHeader({ title, description, meta, actions }: { title: string; description?: string; meta?: ReactNode; actions?: ReactNode }) {
|
||||
export function PageHeader({ title, description, meta, actions, icon }: { title: string; description?: string; meta?: ReactNode; actions?: ReactNode; icon?: WorkspaceSignalIconVariant }) {
|
||||
return (
|
||||
<header className="app-page-header flex flex-col gap-4 pb-6 sm:flex-row sm:items-end sm:justify-between">
|
||||
<div className="min-w-0">
|
||||
<div className="flex min-w-0 flex-wrap items-center gap-2.5">
|
||||
<h1 className="truncate text-2xl font-semibold leading-8">{title}</h1>
|
||||
{meta}
|
||||
<header className="app-page-header flex min-h-14 flex-col gap-3 border-b border-border/80 pb-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
{icon ? <WorkspaceSignalIcon variant={icon} /> : null}
|
||||
<div className="min-w-0">
|
||||
<div className="flex min-w-0 flex-wrap items-baseline gap-2.5">
|
||||
<h1 className="truncate text-[22px] font-semibold leading-7">{title}</h1>
|
||||
{meta}
|
||||
</div>
|
||||
{description ? <p className="mt-1 text-xs leading-5 text-foreground/58">{description}</p> : null}
|
||||
</div>
|
||||
{description ? <p className="mt-1.5 text-sm leading-5 text-foreground/62">{description}</p> : null}
|
||||
</div>
|
||||
{actions ? <div className="flex shrink-0 flex-wrap items-center gap-2">{actions}</div> : null}
|
||||
</header>
|
||||
@@ -29,10 +33,10 @@ export function PageHeader({ title, description, meta, actions }: { title: strin
|
||||
|
||||
export function ListToolbar({ children, trailing, active, onReset }: { children: ReactNode; trailing?: ReactNode; active?: boolean; onReset?: () => void }) {
|
||||
return (
|
||||
<div className="mt-4 flex flex-col gap-3 border-b border-border pb-4 xl:flex-row xl:items-center xl:justify-between">
|
||||
<div className="flex min-w-0 flex-1 flex-wrap items-center gap-2">{children}</div>
|
||||
<div className="mt-3 flex min-h-12 flex-col gap-2 border-b border-border/75 pb-3 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div className="flex min-w-0 flex-1 flex-wrap items-center gap-2.5">{children}</div>
|
||||
<div className="flex shrink-0 flex-wrap items-center gap-2">
|
||||
{active && onReset ? <Button icon={<RotateCcw className="size-3.5" />} onClick={onReset}>重置筛选</Button> : null}
|
||||
{active && onReset ? <Button type="text" icon={<RotateCcw className="size-3.5" />} onClick={onReset}>重置</Button> : null}
|
||||
{trailing}
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +48,7 @@ export function TableSurface({ children, className }: { children: ReactNode; cla
|
||||
}
|
||||
|
||||
export function CollectionGrid({ children, className }: { children: ReactNode; className?: string }) {
|
||||
return <div className={cn("mt-4 grid grid-cols-1 gap-3 sm:grid-cols-[repeat(auto-fill,minmax(220px,1fr))]", className)}>{children}</div>;
|
||||
return <div className={cn("mt-4 grid grid-cols-1 gap-x-4 gap-y-5 sm:grid-cols-[repeat(auto-fill,minmax(248px,1fr))]", className)}>{children}</div>;
|
||||
}
|
||||
|
||||
export function PaginationBar({ current, pageSize, total, onChange, pageSizeOptions = [20, 50, 100] }: { current: number; pageSize: number; total: number; onChange: (page: number, pageSize: number) => void; pageSizeOptions?: number[] }) {
|
||||
|
||||
Reference in New Issue
Block a user