import { useState } from "react"; import type { FormEvent } from "react"; import type { Asset } from "../types"; import { Drawer } from "../components/overlays"; type LibTab = "people" | "scenes" | "products" | "finals" | "uploads" | "unclassified"; const LIB_TABS: Array<{ key: LibTab; label: string }> = [ { key: "people", label: "人物" }, { key: "scenes", label: "场景" }, { key: "products", label: "商品图" }, { key: "finals", label: "成片" }, { key: "uploads", label: "我的上传" }, { key: "unclassified", label: "未分类" } ]; // 对齐 api-bridge:工具栏 chip 按 tab 显隐 const LIB_CHIPS: Array<{ key: string; label: string; tabs: LibTab[] }> = [ { key: "gender", label: "性别", tabs: ["people"] }, { key: "age", label: "年龄段", tabs: ["people"] }, { key: "role", label: "角色标签", tabs: ["people"] }, { key: "sceneType", label: "场景类型", tabs: ["scenes"] }, { key: "product", label: "关联商品", tabs: ["products"] }, { key: "project", label: "关联项目", tabs: ["finals"] }, { key: "duration", label: "时长", tabs: ["finals"] }, { key: "kind", label: "资产类型", tabs: ["uploads"] }, { key: "source", label: "来源", tabs: ["people", "scenes", "products", "uploads"] } ]; function assetTab(asset: Asset): LibTab { switch (asset.category) { case "person": return "people"; case "scene": return "scenes"; case "product_image": return "products"; case "final_video": return "finals"; case "upload": return "uploads"; default: return asset.asset_type === "video" ? "finals" : "unclassified"; } } export function LibraryPage({ assets, onUpload }: { assets: Asset[]; onUpload: (formData: FormData) => Promise | void }) { const [tab, setTab] = useState("people"); const [query, setQuery] = useState(""); const [drawer, setDrawer] = useState(false); const [file, setFile] = useState(null); const [name, setName] = useState(""); const counts = LIB_TABS.reduce((acc, t) => { acc[t.key] = assets.filter((a) => assetTab(a) === t.key).length; return acc; }, {} as Record); const inTab = assets.filter((a) => assetTab(a) === tab); const filtered = inTab.filter((a) => `${a.name} ${a.category}`.toLowerCase().includes(query.toLowerCase())); async function submit(event: FormEvent) { event.preventDefault(); if (!file) return; const formData = new FormData(); formData.append("file", file); formData.append("name", name || file.name); formData.append("asset_type", "image"); formData.append("category", "upload"); await onUpload(formData); setDrawer(false); } return (

资产库

// 跨项目复用 · {counts.people} 人 · {counts.scenes} 景 · {counts.products} 商 · {counts.finals}
{LIB_TABS.map((t) => (
setTab(t.key)}>{t.label} {counts[t.key]}
))}
setQuery(event.target.value)} />
{LIB_CHIPS.filter((chip) => chip.tabs.includes(tab)).map((chip) => (
))}
// 显示 {filtered.length} / {inTab.length} 个资产
{filtered.length ? (
{filtered.map((asset) => (
{asset.asset_type}
{asset.name}
{asset.category} · {asset.source}
))}
) : (
// 当前分类暂无真实资产
)} setDrawer(false)}>
setFile(event.target.files?.[0] || null)} />
setName(event.target.value)} />
); }