style: tighten detail mode layout spacing
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-02-17 14:29:54 +08:00
parent 4533547d68
commit dde1b95f25

View File

@ -367,6 +367,23 @@ const DETAIL_SLOT_CONFIGS: DetailSlotConfig[] = [
{ key: "product-5", label: "产品图5", role: "product" },
{ key: "model-1", label: "模特图", role: "model" },
];
const DETAIL_FIELD_EXAMPLES: Record<keyof DetailBriefForm, string> = {
productName: "示例:Buyi-AI 无线手持吸尘器",
targetAudience: "示例:25-40岁养宠家庭、宝妈",
mainUser: "示例:家庭主理人、租房上班族",
usageScenario: "示例:下班回家10分钟快速清洁",
triggerMoment: "示例:宠物掉毛高峰、饭后碎屑清理",
coreNeed: "示例:省时省力清除毛发与灰尘",
riskConcern: "示例:担心吸力不足、续航短、噪音大",
expectedResult: "示例:3分钟清洁桌面,地面无明显毛发",
coreSellingPoint: "示例:18000Pa吸力、0.9kg轻量、一键倒尘",
positioningStatement: "示例:让日常清洁更快更轻松",
userVoice: "示例:家里有猫掉毛太多,希望安静一点不吵宝宝",
competitorReference: "示例:对标戴森入门款,突出轻便高性价比",
priceBand: "示例:199-299元",
brandTone: "示例:专业、可靠、亲和",
bannedWords: "示例:最强、第一、100%治愈",
};
const SESSION_TITLE_MAX_LEN = 18;
@ -2969,12 +2986,17 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
</div>
{/* 消息列表 */}
<ScrollArea className="flex-1 p-4 pt-16">
<ScrollArea
className={cn(
"flex-1 p-4",
isDetailGenerationMode && messages.length === 0 ? "pt-10" : "pt-16"
)}
>
<div className="space-y-6">
{messages.length === 0 && (
<div className="flex flex-col h-full pt-4">
<div className={cn("flex flex-col h-full", isDetailGenerationMode ? "pt-0" : "pt-4")}>
{/* Greeting */}
<div className="mb-8">
<div className={cn(isDetailGenerationMode ? "mb-4" : "mb-8")}>
<h1 className="text-2xl font-bold mb-2">Hi, 我是你的AI设计师</h1>
<p className="text-muted-foreground">让我们开始今天的创作吧!</p>
</div>
@ -3274,7 +3296,12 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
data-canvas-chat-input-anchor="true"
>
{isDetailGenerationMode && (
<div className="mx-3 mt-3 max-h-[54vh] overflow-y-auto rounded-2xl border border-black/10 bg-white/95 p-3 pr-2">
<div
className={cn(
"mx-3 mt-3 overflow-y-auto rounded-2xl border border-black/10 bg-white/95 p-3 pr-2",
messages.length === 0 ? "max-h-[62vh]" : "max-h-[54vh]"
)}
>
<div className="flex items-start justify-between gap-3">
<div>
<p className="text-sm font-semibold text-black">
@ -3286,7 +3313,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
</div>
<span
className={cn(
"rounded-full px-2 py-0.5 text-[10px] font-medium",
"shrink-0 whitespace-nowrap rounded-full px-2 py-0.5 text-[10px] font-medium leading-none",
detailProgress.status === "running"
? "bg-blue-50 text-blue-700"
: detailProgress.status === "done"
@ -3329,6 +3356,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
</div>
<div className="mt-3 space-y-2">
<p className="px-1 text-[11px] text-black/45">提示:鼠标悬停输入框可查看填写示例。</p>
<div className="rounded-xl border border-black/10 bg-white">
<button
type="button"
@ -3351,60 +3379,70 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
<input
value={detailBrief.targetAudience}
onChange={(event) => updateDetailBriefField("targetAudience", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.targetAudience}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="主购买人群 *"
/>
<input
value={detailBrief.usageScenario}
onChange={(event) => updateDetailBriefField("usageScenario", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.usageScenario}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="需求场景 *"
/>
<input
value={detailBrief.coreNeed}
onChange={(event) => updateDetailBriefField("coreNeed", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.coreNeed}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="核心需求 *"
/>
<input
value={detailBrief.productName}
onChange={(event) => updateDetailBriefField("productName", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.productName}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="产品名称(选填)"
/>
<input
value={detailBrief.mainUser}
onChange={(event) => updateDetailBriefField("mainUser", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.mainUser}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="主使用者(选填)"
/>
<input
value={detailBrief.triggerMoment}
onChange={(event) => updateDetailBriefField("triggerMoment", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.triggerMoment}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="触发时刻(选填)"
/>
<input
value={detailBrief.riskConcern}
onChange={(event) => updateDetailBriefField("riskConcern", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.riskConcern}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="用户顾虑(选填)"
/>
<input
value={detailBrief.expectedResult}
onChange={(event) => updateDetailBriefField("expectedResult", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.expectedResult}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="期望结果(选填)"
/>
<input
value={detailBrief.coreSellingPoint}
onChange={(event) => updateDetailBriefField("coreSellingPoint", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.coreSellingPoint}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400 xl:col-span-2"
placeholder="核心卖点关键词(选填)"
/>
<input
value={detailBrief.positioningStatement}
onChange={(event) => updateDetailBriefField("positioningStatement", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.positioningStatement}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400 xl:col-span-2"
placeholder="一句话定位(选填)"
/>
@ -3434,30 +3472,35 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
<input
value={detailBrief.priceBand}
onChange={(event) => updateDetailBriefField("priceBand", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.priceBand}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="价格带(选填)"
/>
<input
value={detailBrief.brandTone}
onChange={(event) => updateDetailBriefField("brandTone", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.brandTone}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400"
placeholder="品牌语气(选填)"
/>
<input
value={detailBrief.competitorReference}
onChange={(event) => updateDetailBriefField("competitorReference", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.competitorReference}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400 xl:col-span-2"
placeholder="竞品对标(选填)"
/>
<input
value={detailBrief.bannedWords}
onChange={(event) => updateDetailBriefField("bannedWords", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.bannedWords}
className="h-8 rounded-lg border border-black/15 bg-white px-2 text-xs outline-none focus:border-blue-400 xl:col-span-2"
placeholder="禁用表达(选填,逗号分隔)"
/>
<textarea
value={detailBrief.userVoice}
onChange={(event) => updateDetailBriefField("userVoice", event.target.value)}
title={DETAIL_FIELD_EXAMPLES.userVoice}
className="min-h-[64px] resize-y rounded-lg border border-black/15 bg-white px-2 py-1.5 text-xs outline-none focus:border-blue-400 xl:col-span-4"
placeholder="用户原话样本(选填,建议3-5条)"
/>
@ -3589,7 +3632,10 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
)}
{/* 混合输入区域:使用 contenteditable 实现真正的混合编辑 */}
<div
className="relative px-4 pt-3 pb-12 min-h-[60px]"
className={cn(
"relative px-4 pt-3 pb-12",
isDetailGenerationMode ? "min-h-[72px]" : "min-h-[60px]"
)}
>
<div
ref={textareaRef as any}