feat: split psd template picker by mode
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-02 18:48:48 +08:00
parent 11ab9a8e03
commit 0f1548fdc9

View File

@ -163,6 +163,44 @@ function renderTemplateSelectContent(
);
}
function renderTemplatePickerCardContent(
template: AgentPsdTemplate,
params?: {
showSecondaryCategory?: boolean;
emphasize?: boolean;
}
) {
const showSecondaryCategory = params?.showSecondaryCategory === true;
const emphasize = params?.emphasize === true;
const metaLabel = getTemplateMetaLabel(template, showSecondaryCategory);
return (
<div className="flex min-w-0 items-center gap-3">
<div className="flex h-14 w-14 shrink-0 overflow-hidden rounded-xl border border-white/10 bg-white/5">
<img
src={template.previewUrl}
alt={template.name}
className="h-full w-full object-cover"
/>
</div>
<div className="min-w-0">
<div
className={
emphasize
? "truncate text-sm font-semibold text-white"
: "truncate text-sm font-medium text-white"
}
>
{template.name}
</div>
{metaLabel ? (
<div className="mt-1 truncate text-[11px] text-white/45">{metaLabel}</div>
) : null}
</div>
</div>
);
}
function clampImageScale(value: number) {
if (!Number.isFinite(value)) {
return 1;
@ -483,11 +521,8 @@ export function AgentPsdTemplateEditorDialog({
const searchParams = new URLSearchParams();
searchParams.set("brand", normalizedBrandName);
if (normalizedTemplateMode) {
searchParams.set("mode", normalizedTemplateMode);
}
return `/api/psd-templates?${searchParams.toString()}`;
}, [open, normalizedBrandName, normalizedTemplateMode]);
}, [open, normalizedBrandName]);
const { data, isLoading } = useSWR<AgentPsdTemplateListResponse>(
templateListRequestUrl,
fetcher
@ -554,6 +589,14 @@ export function AgentPsdTemplateEditorDialog({
templates: grouped,
}));
}, [shouldGroupTemplatesBySecondaryCategory, templates]);
const mainModeTemplates = useMemo(
() => templates.filter((template) => template.mode === "main"),
[templates]
);
const skuModeTemplates = useMemo(
() => templates.filter((template) => template.mode === "sku"),
[templates]
);
const selectedTemplateLayers = useMemo(() => {
if (!selectedTemplate || !Array.isArray(selectedTemplate.layers)) {
return [] as AgentPsdTemplateLayerSlot[];
@ -839,6 +882,15 @@ export function AgentPsdTemplateEditorDialog({
const selectedTemplateSelectValue = selectedTemplate?.id;
const hasTemplateOptions = templates.length > 0;
useEffect(() => {
if (open) {
return;
}
setSelectedTemplateId("");
setSelectedLayerId("");
}, [open]);
useEffect(() => {
if (!open) return;
@ -851,7 +903,7 @@ export function AgentPsdTemplateEditorDialog({
}
if (!templates.some((template) => template.id === selectedTemplateId)) {
setSelectedTemplateId(templates[0].id);
setSelectedTemplateId("");
}
}, [open, selectedTemplateId, templates]);
@ -1242,8 +1294,8 @@ export function AgentPsdTemplateEditorDialog({
<ScrollArea className="h-full pr-4">
<div className="space-y-4">
<div className="space-y-2">
<Label>选择模板</Label>
{hasTemplateOptions ? (
<Label>{selectedTemplate ? "选择模板" : "主图模式模板"}</Label>
{selectedTemplate && hasTemplateOptions ? (
<Select value={selectedTemplateSelectValue} onValueChange={setSelectedTemplateId}>
<SelectTrigger className="h-auto min-h-[58px] items-center px-2.5 py-2 [&>span]:contents">
{selectedTemplate ? (
@ -1290,12 +1342,43 @@ export function AgentPsdTemplateEditorDialog({
</SelectContent>
</Select>
) : (
<div className="rounded-xl border border-dashed border-white/15 bg-white/[0.02] px-3 py-2 text-sm text-muted-foreground">
{isLoading
? "正在加载可用模板..."
: normalizedBrandName
? `当前品牌“${normalizedBrandName}”下暂无可用模板`
: "请先在工作流中选择品牌后再打开 PSD 模板。"}
<div className="space-y-2">
{isLoading ? (
<>
{Array.from({ length: 2 }).map((_, index) => (
<div
key={`main-template-loading-${index}`}
className="rounded-2xl border border-dashed border-white/15 bg-white/[0.02] px-4 py-4 text-sm text-muted-foreground"
>
正在加载主图模式模板...
</div>
))}
</>
) : mainModeTemplates.length > 0 ? (
mainModeTemplates.map((template) => (
<button
key={template.id}
type="button"
onClick={() => setSelectedTemplateId(template.id)}
className={`w-full rounded-2xl border p-3 text-left transition ${
selectedTemplateId === template.id
? "border-emerald-400/45 bg-emerald-500/10"
: "border-white/10 bg-white/[0.03] hover:border-white/20 hover:bg-white/[0.05]"
}`}
>
{renderTemplatePickerCardContent(template, {
showSecondaryCategory: shouldGroupTemplatesBySecondaryCategory,
emphasize: true,
})}
</button>
))
) : (
<div className="rounded-xl border border-dashed border-white/15 bg-white/[0.02] px-3 py-3 text-sm text-muted-foreground">
{normalizedBrandName
? `当前品牌“${normalizedBrandName}”下暂无主图模式模板`
: "请先在工作流中选择品牌后再打开 PSD 模板。"}
</div>
)}
</div>
)}
</div>
@ -1704,10 +1787,59 @@ export function AgentPsdTemplateEditorDialog({
</div>
</div>
) : (
<div className="flex h-full w-full items-center justify-center px-6 text-center text-sm text-muted-foreground">
{normalizedBrandName
? "请选择一个模板后开始直接在模板中编辑。"
: "请先返回工作流区域选择品牌,再打开 PSD 模板。"}
<div className="flex h-full w-full flex-col rounded-2xl border border-white/10 bg-white/[0.02] p-5">
<div className="mb-4 flex items-center justify-between gap-3">
<div>
<div className="text-sm font-semibold text-white">SKU图模式模板</div>
<div className="mt-1 text-xs text-white/45">
{normalizedTemplateMode === "sku"
? "当前结果属于 SKU 图模式,可直接从这里选择并进入编辑。"
: "这里集中展示当前品牌下的 SKU 图模式模板。"}
</div>
</div>
<div className="rounded-full border border-white/10 bg-white/[0.04] px-3 py-1 text-xs text-white/65">
{skuModeTemplates.length} 个模板
</div>
</div>
{isLoading ? (
<div className="grid gap-3 md:grid-cols-2">
{Array.from({ length: 4 }).map((_, index) => (
<div
key={`sku-template-loading-${index}`}
className="rounded-2xl border border-dashed border-white/15 bg-white/[0.02] px-4 py-5 text-sm text-muted-foreground"
>
正在加载 SKU 图模式模板...
</div>
))}
</div>
) : skuModeTemplates.length > 0 ? (
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
{skuModeTemplates.map((template) => (
<button
key={template.id}
type="button"
onClick={() => setSelectedTemplateId(template.id)}
className={`rounded-2xl border p-3 text-left transition ${
selectedTemplateId === template.id
? "border-emerald-400/45 bg-emerald-500/10"
: "border-white/10 bg-white/[0.03] hover:border-white/20 hover:bg-white/[0.05]"
}`}
>
{renderTemplatePickerCardContent(template, {
showSecondaryCategory: shouldGroupTemplatesBySecondaryCategory,
emphasize: true,
})}
</button>
))}
</div>
) : (
<div className="flex h-full w-full items-center justify-center px-6 text-center text-sm text-muted-foreground">
{normalizedBrandName
? `当前品牌“${normalizedBrandName}”下暂无 SKU 图模式模板`
: "请先返回工作流区域选择品牌,再打开 PSD 模板。"}
</div>
)}
</div>
)}
</div>