fix(platform): 用户工作台 - 统一资源卡片并修正项目列表与预览交互

This commit is contained in:
ddCat
2026-08-06 23:01:08 +08:00
parent 61f0dfb9c6
commit 7d4384fa1f
12 changed files with 529 additions and 202 deletions

View File

@@ -0,0 +1,12 @@
import type { ReactNode } from "react";
import { cn } from "@/lib/utils";
/** 资产库卡片的共同外壳;页面只负责业务动作和卡片内的信息层级。 */
export function AssetLibraryCard({ children, className, selected = false }: { children: ReactNode; className?: string; selected?: boolean }) {
return <article className={cn("library-card library-card-surface asset-library-card group", selected && "is-selected", className)}>{children}</article>;
}
export function AssetLibraryCardMedia({ children, className }: { children: ReactNode; className?: string }) {
return <div className={cn("library-card-media", className)}>{children}</div>;
}

View File

@@ -1,4 +1,5 @@
import { Check, Clapperboard, Download, FileText, Frame, Image as ImageIcon, MoreHorizontal, Music2, Pencil, Plus, Settings2, Sparkles, Trash2, Video, X } from "lucide-react";
import type { ReactNode } from "react";
import { useNavigate, useSearchParams } from "react-router";
import { Dropdown, Input } from "antd";
@@ -18,7 +19,7 @@ export function CanvasCreateCard({ disabled, onClick }: { disabled?: boolean; on
</button>;
}
export function CanvasProjectCard({ project, projectName, variant = "library" }: { project: CanvasProject; projectName?: string; variant?: "library" | "recent" }) {
export function CanvasProjectCard({ project, projectName, variant = "library", readOnly = false, footer }: { project: CanvasProject; projectName?: string; variant?: "library" | "recent"; readOnly?: boolean; footer?: ReactNode }) {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const renameProject = useCanvasStore((state) => state.renameProject);
@@ -40,7 +41,7 @@ export function CanvasProjectCard({ project, projectName, variant = "library" }:
const compact = variant === "recent";
return (
<article className={cn("app-canvas-project-card group h-full cursor-pointer", compact ? "is-recent" : "is-library", selected && "is-selected")} onClick={() => !editing && open()}>
<article className={cn("app-canvas-project-card group h-full cursor-pointer", compact ? "is-recent" : "is-library", selected && "is-selected")} onClick={() => (!editing || readOnly) && open()}>
<div className="app-canvas-project-preview relative">
<button
type="button"
@@ -52,13 +53,13 @@ export function CanvasProjectCard({ project, projectName, variant = "library" }:
>
<ProjectPreview project={project} />
</button>
{!compact ? <span className={`canvas-project-select ${selected ? "is-visible" : ""}`} onClick={(event) => event.stopPropagation()}><input type="checkbox" checked={selected} onChange={(event) => toggleSelected(project.id, event.target.checked)} className="app-canvas-project-checkbox" aria-label={`选择 ${project.title}`} /></span> : null}
{!compact && !readOnly ? <span className={`canvas-project-select ${selected ? "is-visible" : ""}`} onClick={(event) => event.stopPropagation()}><input type="checkbox" checked={selected} onChange={(event) => toggleSelected(project.id, event.target.checked)} className="app-canvas-project-checkbox" aria-label={`选择 ${project.title}`} /></span> : null}
<div className="canvas-project-cover-meta" aria-hidden="true"><span className="canvas-project-node-count">{project.nodes.length} 节点</span></div>
</div>
<div className={cn("app-canvas-project-body", compact ? "is-compact" : "")}>
<div className="canvas-project-heading-row">
{editing ? (
{editing && !readOnly ? (
<Input className="canvas-project-title-input" value={editingTitle} onClick={(event) => event.stopPropagation()} onChange={(event) => setEditingTitle(event.target.value)} onKeyDown={(event) => event.key === "Enter" && saveTitle()} autoFocus />
) : (
<button
@@ -72,12 +73,12 @@ export function CanvasProjectCard({ project, projectName, variant = "library" }:
<h2>{project.title}</h2>
</button>
)}
{editing ? (
{editing && !readOnly ? (
<div className="canvas-project-actions" onClick={(event) => event.stopPropagation()}>
<button type="button" onClick={saveTitle} aria-label="保存名称"><Check className="size-3.5" /></button>
<button type="button" onClick={stopEditing} aria-label="取消重命名"><X className="size-3.5" /></button>
</div>
) : (
) : !readOnly ? (
<div className="canvas-project-actions" onClick={(event) => event.stopPropagation()}>
<button type="button" onClick={() => startEditing(project.id, project.title)} aria-label={`重命名 ${project.title}`} title="重命名"><Pencil className="size-3.5" /></button>
<Dropdown
@@ -94,9 +95,10 @@ export function CanvasProjectCard({ project, projectName, variant = "library" }:
<button type="button" aria-label={`${project.title} 画布操作`} title="更多操作"><MoreHorizontal className="size-4" /></button>
</Dropdown>
</div>
)}
) : null}
</div>
<div className="canvas-project-stats"><span>{projectName || "自由画布"}</span><span aria-hidden="true">·</span><time dateTime={project.updatedAt}>{formatProjectTime(project.updatedAt)}</time></div>
{footer ? <div className="canvas-project-card-footer" onClick={(event) => event.stopPropagation()}>{footer}</div> : null}
</div>
</article>
);