fix: improve psd editor dialog layout
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-03-29 09:40:32 +08:00
parent 80db6cd48d
commit 6d281e950a

View File

@ -39,6 +39,8 @@ import {
} from "@/lib/agents/psd-template-config";
const fetcher = (url: string) => fetch(url, { cache: "no-store" }).then((res) => res.json());
const PREVIEW_VIEWPORT_PADDING = 56;
const PREVIEW_STAGE_MAX_SCALE = 0.82;
function createInitialState(template: AgentPsdTemplate | null, sourceImageUrl: string) {
const imageAssignments: Record<string, string> = {};
@ -309,12 +311,12 @@ export function AgentPsdTemplateEditorDialog({
const updateScale = () => {
const rect = element.getBoundingClientRect();
const availableWidth = Math.max(240, rect.width - 32);
const availableHeight = Math.max(240, rect.height - 32);
const availableWidth = Math.max(240, rect.width - PREVIEW_VIEWPORT_PADDING);
const availableHeight = Math.max(240, rect.height - PREVIEW_VIEWPORT_PADDING);
const nextScale = Math.min(
availableWidth / Math.max(1, selectedTemplate.width),
availableHeight / Math.max(1, selectedTemplate.height),
1
PREVIEW_STAGE_MAX_SCALE
);
setStageScale(Number.isFinite(nextScale) && nextScale > 0 ? nextScale : 1);
};
@ -469,11 +471,6 @@ export function AgentPsdTemplateEditorDialog({
) : null}
</div>
<div className="rounded-xl border border-dashed border-white/15 bg-white/[0.02] p-3 text-xs leading-6 text-muted-foreground">
操作方式更接近 PS:
直接点击模板里的图片区域去替换图片,点击模板里的文字区域直接改现有文字。
</div>
<Button
onClick={handleRender}
disabled={isRendering}
@ -500,7 +497,7 @@ export function AgentPsdTemplateEditorDialog({
</ScrollArea>
</div>
<div className="min-h-0 border-b border-white/10 bg-[#09090b] p-5 xl:border-b-0 xl:border-r">
<div className="flex min-h-0 flex-col border-b border-white/10 bg-[#09090b] p-5 xl:border-b-0 xl:border-r">
<div className="mb-4 flex flex-wrap items-center gap-2">
<div className="text-sm font-medium">模板画布编辑区</div>
{selectedTemplate ? (
@ -516,11 +513,11 @@ export function AgentPsdTemplateEditorDialog({
<div
ref={previewViewportRef}
className="relative flex h-full min-h-[520px] items-start justify-center overflow-auto rounded-2xl border border-white/10 bg-[#111114]"
className="relative flex min-h-0 flex-1 items-center justify-center overflow-auto rounded-2xl border border-white/10 bg-[#111114] p-4"
>
{selectedTemplate ? (
<div
className="relative my-4"
className="relative shrink-0"
style={{
width: selectedTemplate.width * stageScale,
height: selectedTemplate.height * stageScale,
@ -731,8 +728,9 @@ export function AgentPsdTemplateEditorDialog({
}}
/>
<div className="flex h-full min-h-0 flex-col gap-5">
<div className="rounded-2xl border border-white/10 bg-white/[0.02] p-4">
<ScrollArea className="h-full pr-3">
<div className="flex min-h-full flex-col gap-5">
<div className="rounded-2xl border border-white/10 bg-white/[0.02] p-4">
{selectedImageLayer ? (
<div className="space-y-4">
<div className="flex flex-wrap items-center gap-2">
@ -744,7 +742,7 @@ export function AgentPsdTemplateEditorDialog({
</div>
<div className="text-xs text-muted-foreground">{selectedImageLayer.layerPath}</div>
<div className="overflow-hidden rounded-xl border border-white/10 bg-white/5">
<div className="aspect-[4/3]">
<div className="h-[220px]">
{effectiveImageAssignments[selectedImageLayer.id] ? (
<img
src={effectiveImageAssignments[selectedImageLayer.id]}
@ -843,50 +841,51 @@ export function AgentPsdTemplateEditorDialog({
</div>
</div>
)}
</div>
</div>
<div className="min-h-0 flex-1 rounded-2xl border border-white/10 bg-white/[0.02] p-4">
<div className="mb-3 text-sm font-medium">导出结果</div>
{renderedResultUrl ? (
<div className="flex h-full min-h-0 flex-col justify-between gap-4">
<div className="mx-auto w-full max-w-[280px] overflow-hidden rounded-2xl border border-white/10 bg-white/5">
<div
style={{
aspectRatio: selectedTemplate
? `${Math.max(1, selectedTemplate.width)} / ${Math.max(1, selectedTemplate.height)}`
: "1 / 1",
}}
>
<img
src={renderedResultUrl}
alt="PSD 模板导出结果"
className="h-full w-full object-contain"
/>
<div className="min-h-0 flex-1 rounded-2xl border border-white/10 bg-white/[0.02] p-4">
<div className="mb-3 text-sm font-medium">导出结果</div>
{renderedResultUrl ? (
<div className="flex h-full min-h-0 flex-col justify-between gap-4">
<div className="mx-auto w-full max-w-[240px] overflow-hidden rounded-2xl border border-white/10 bg-white/5">
<div
style={{
aspectRatio: selectedTemplate
? `${Math.max(1, selectedTemplate.width)} / ${Math.max(1, selectedTemplate.height)}`
: "1 / 1",
}}
>
<img
src={renderedResultUrl}
alt="PSD 模板导出结果"
className="h-full w-full object-contain"
/>
</div>
</div>
<Button onClick={handleDownload} className="w-full">
<Download className="mr-2 h-4 w-4" />
下载结果图
</Button>
</div>
) : (
<div className="flex h-full min-h-[220px] flex-col items-center justify-center rounded-2xl border border-dashed border-white/15 bg-white/[0.02] px-6 text-center">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-white/5">
{selectedTextLayer ? (
<Type className="h-8 w-8 text-muted-foreground" />
) : (
<ImageIcon className="h-8 w-8 text-muted-foreground" />
)}
</div>
<div className="mt-4 text-sm font-medium">还未导出成品图</div>
<div className="mt-2 text-xs leading-6 text-muted-foreground">
在模板画布里完成替换后,点击“应用模板并导出”,这里会显示最终图片。
</div>
</div>
<Button onClick={handleDownload} className="w-full">
<Download className="mr-2 h-4 w-4" />
下载结果图
</Button>
</div>
) : (
<div className="flex h-full min-h-[240px] flex-col items-center justify-center rounded-2xl border border-dashed border-white/15 bg-white/[0.02] px-6 text-center">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-white/5">
{selectedTextLayer ? (
<Type className="h-8 w-8 text-muted-foreground" />
) : (
<ImageIcon className="h-8 w-8 text-muted-foreground" />
)}
</div>
<div className="mt-4 text-sm font-medium">还未导出成品图</div>
<div className="mt-2 text-xs leading-6 text-muted-foreground">
在模板画布里完成替换后,点击“应用模板并导出”,这里会显示最终图片。
</div>
</div>
)}
)}
</div>
</div>
</div>
</ScrollArea>
</div>
</div>
</DialogContent>