fix: compact enhance pro workspace 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-04-05 21:59:05 +08:00
parent 5c2ece9fb6
commit 9c8228b697
2 changed files with 305 additions and 291 deletions

View File

@ -89,6 +89,10 @@ const FALLBACK_CONFIG: EnhanceProClientConfig = {
presets: defaultEnhanceProPresets(), presets: defaultEnhanceProPresets(),
}; };
const SOLID_PANEL_FIELD_CLASS = "border-white/10 bg-[#1a1b22] text-white";
const SOLID_PANEL_CARD_CLASS = "rounded-2xl border border-white/10 bg-[#17181f]";
const SOLID_PANEL_CHIP_CLASS = "rounded-full border border-white/10 bg-[#1b1c24]";
function clampNumber(value: number, min: number, max: number) { function clampNumber(value: number, min: number, max: number) {
return Math.min(max, Math.max(min, value)); return Math.min(max, Math.max(min, value));
} }
@ -486,7 +490,7 @@ export function EnhanceProWorkspace({
className="max-h-full max-w-full object-contain" className="max-h-full max-w-full object-contain"
src={getDisplayImageUrl(activePreviewUrl, 1800)} src={getDisplayImageUrl(activePreviewUrl, 1800)}
/> />
<div className="pointer-events-none absolute top-6 left-6 flex items-center gap-2 rounded-full border border-white/10 bg-black/45 px-3 py-1.5 text-white/80 text-xs backdrop-blur-md"> <div className="pointer-events-none absolute top-6 left-6 flex items-center gap-2 rounded-full border border-white/10 bg-[#101114] px-3 py-1.5 text-white/80 text-xs">
<ImageIcon className="h-3.5 w-3.5" /> <ImageIcon className="h-3.5 w-3.5" />
<span>{activePreviewLabel}</span> <span>{activePreviewLabel}</span>
</div> </div>
@ -506,7 +510,7 @@ export function EnhanceProWorkspace({
{sidePreviewItems.length > 0 ? ( {sidePreviewItems.length > 0 ? (
<div className="absolute right-6 bottom-6 left-6 flex items-center justify-center"> <div className="absolute right-6 bottom-6 left-6 flex items-center justify-center">
<div className="flex max-w-[min(720px,calc(100vw-5rem))] items-center gap-2 rounded-[24px] border border-white/10 bg-black/45 px-3 py-3 shadow-2xl backdrop-blur-xl"> <div className="flex max-w-[min(720px,calc(100vw-5rem))] items-center gap-2 rounded-[24px] border border-white/10 bg-[#101114] px-3 py-3 shadow-2xl">
{sidePreviewItems.map((item, index) => { {sidePreviewItems.map((item, index) => {
const isActive = item.isSource const isActive = item.isSource
? selectedResultIndex < 0 ? selectedResultIndex < 0
@ -539,50 +543,29 @@ export function EnhanceProWorkspace({
) : null} ) : null}
</div> </div>
<div className="flex h-full w-[360px] shrink-0 flex-col border-white/10 border-l bg-[#111217]/95"> <div className="flex h-full w-[420px] max-w-[42vw] shrink-0 flex-col border-white/10 border-l bg-[#111217]">
<div className="border-white/10 border-b px-5 py-5"> <div className="border-white/10 border-b px-4 py-4 pr-24">
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div> <div>
<div className="flex items-center gap-2 font-semibold text-base text-white"> <div className="flex items-center gap-2 font-semibold text-base text-white">
<Wand2 className="h-4.5 w-4.5 text-sky-300" /> <Wand2 className="h-4.5 w-4.5 text-sky-300" />
图像增强模式 图像增强模式
</div> </div>
<div className="mt-1 text-white/55 text-xs leading-5">
使用 {config.providerName}{" "}
对单张图片进行更可控的增强、修复和细节重建。
</div>
</div> </div>
<div className="rounded-full border border-white/10 bg-white/5 px-2.5 py-1 text-[11px] text-white/65"> <div
className={cn(
SOLID_PANEL_CHIP_CLASS,
"px-2.5 py-1 text-[11px] text-white/70"
)}
>
{selectedPreset?.model || config.defaultModel} {selectedPreset?.model || config.defaultModel}
</div> </div>
</div> </div>
<div className="mt-4 overflow-hidden rounded-2xl border border-white/10 bg-black/30">
{sourceImageUrl ? (
<img
alt="增强源图"
className="h-[128px] w-full object-cover"
src={getDisplayImageUrl(sourceImageUrl, 420)}
/>
) : (
<div className="flex h-[128px] items-center justify-center text-sm text-white/40">
暂无源图
</div>
)}
</div>
<div className="mt-3 flex flex-wrap gap-2 text-[11px] text-white/50">
<span className="rounded-full border border-white/10 bg-white/5 px-2 py-1">
原图 {naturalSize.width} x {naturalSize.height}
</span>
<span className="rounded-full border border-white/10 bg-white/5 px-2 py-1">
最大输出长边 {config.maxOutputEdge}px
</span>
</div>
</div> </div>
<div className="min-h-0 flex-1 space-y-5 overflow-y-auto px-5 py-5"> <div className="min-h-0 flex-1 space-y-4 overflow-y-auto px-4 py-4">
{isLoading ? ( {isLoading ? (
<div className="flex items-center gap-2 rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-sm text-white/60"> <div className={cn(SOLID_PANEL_CARD_CLASS, "flex items-center gap-2 px-4 py-3 text-sm text-white/60")}>
<Loader2 className="h-4 w-4 animate-spin" /> <Loader2 className="h-4 w-4 animate-spin" />
正在加载增强配置... 正在加载增强配置...
</div> </div>
@ -602,9 +585,11 @@ export function EnhanceProWorkspace({
) : null} ) : null}
<div className="space-y-2"> <div className="space-y-2">
<Label className="text-white/80">增强预设</Label> <Label className="text-[11px] uppercase tracking-[0.08em] text-white/65">
增强预设
</Label>
<Select onValueChange={handleSelectPreset} value={selectedPresetId}> <Select onValueChange={handleSelectPreset} value={selectedPresetId}>
<SelectTrigger className="border-white/10 bg-white/5 text-white"> <SelectTrigger className={`${SOLID_PANEL_FIELD_CLASS} h-10`}>
<SelectValue placeholder="选择一个增强预设" /> <SelectValue placeholder="选择一个增强预设" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
@ -616,7 +601,7 @@ export function EnhanceProWorkspace({
</SelectContent> </SelectContent>
</Select> </Select>
{selectedPreset ? ( {selectedPreset ? (
<div className="text-white/45 text-xs leading-5"> <div className="line-clamp-2 text-[11px] leading-5 text-white/45">
{selectedPreset.description || {selectedPreset.description ||
`${selectedPreset.model} · ${getSubjectDetectionLabel(selectedPreset.subjectDetection)}`} `${selectedPreset.model} · ${getSubjectDetectionLabel(selectedPreset.subjectDetection)}`}
</div> </div>
@ -624,11 +609,14 @@ export function EnhanceProWorkspace({
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label className="text-white/80" htmlFor="enhance-workspace-prompt"> <Label
className="text-[11px] uppercase tracking-[0.08em] text-white/65"
htmlFor="enhance-workspace-prompt"
>
增强提示词 增强提示词
</Label> </Label>
<Textarea <Textarea
className="border-white/10 bg-white/5 text-white placeholder:text-white/30" className={`${SOLID_PANEL_FIELD_CLASS} min-h-[82px] resize-none placeholder:text-white/30`}
id="enhance-workspace-prompt" id="enhance-workspace-prompt"
onChange={(event) => onChange={(event) =>
setFormState((prev) => ({ setFormState((prev) => ({
@ -637,221 +625,251 @@ export function EnhanceProWorkspace({
})) }))
} }
placeholder="例如:保持主体不变,提升画质层次、纹理和局部细节,让结果更高级。" placeholder="例如:保持主体不变,提升画质层次、纹理和局部细节,让结果更高级。"
rows={4} rows={3}
value={formState.prompt} value={formState.prompt}
/> />
</div> </div>
<div className="grid grid-cols-2 gap-3"> <div className="space-y-2">
<div className="space-y-2"> <div className="text-[11px] uppercase tracking-[0.08em] text-white/65">
<Label 基础参数
className="text-white/80"
htmlFor="enhance-workspace-width"
>
输出宽度
</Label>
<Input
className="border-white/10 bg-white/5 text-white"
id="enhance-workspace-width"
max={config.maxOutputEdge}
min="1"
onChange={(event) =>
handleNumericField(
"width",
clampNumber(
Number.parseInt(event.target.value, 10) || 1,
1,
config.maxOutputEdge
)
)
}
type="number"
value={formState.width}
/>
</div> </div>
<div className="space-y-2"> <div className="grid grid-cols-3 gap-3">
<Label <div className="space-y-1.5">
className="text-white/80" <Label
htmlFor="enhance-workspace-height" className="text-xs text-white/70"
> htmlFor="enhance-workspace-width"
输出高度 >
</Label> 宽度
<Input </Label>
className="border-white/10 bg-white/5 text-white" <Input
id="enhance-workspace-height" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max={config.maxOutputEdge} id="enhance-workspace-width"
min="1" max={config.maxOutputEdge}
onChange={(event) => min="1"
handleNumericField( onChange={(event) =>
"height",
clampNumber(
Number.parseInt(event.target.value, 10) || 1,
1,
config.maxOutputEdge
)
)
}
type="number"
value={formState.height}
/>
</div>
</div>
<div className="grid grid-cols-3 gap-3">
<div className="space-y-2">
<Label className="text-white/80">增强模式</Label>
<Select
onValueChange={(value) =>
setFormState((prev) => ({
...prev,
model: value as FormState["model"],
}))
}
value={formState.model}
>
<SelectTrigger className="border-white/10 bg-white/5 text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="Redefine">Redefine</SelectItem>
<SelectItem value="Recovery">Recovery</SelectItem>
<SelectItem value="Recovery V2">Recovery V2</SelectItem>
<SelectItem value="Reimagine">Reimagine</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label className="text-white/80">输出格式</Label>
<Select
onValueChange={(value) =>
setFormState((prev) => ({
...prev,
output_format: value as FormState["output_format"],
}))
}
value={formState.output_format}
>
<SelectTrigger className="border-white/10 bg-white/5 text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="jpg">JPG</SelectItem>
<SelectItem value="png">PNG</SelectItem>
<SelectItem value="webp">WEBP</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label className="text-white/80">作用区域</Label>
<Select
onValueChange={(value) =>
setFormState((prev) => ({
...prev,
subject_detection: value as FormState["subject_detection"],
}))
}
value={formState.subject_detection}
>
<SelectTrigger className="border-white/10 bg-white/5 text-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="All">全部</SelectItem>
<SelectItem value="Foreground">前景</SelectItem>
<SelectItem value="Background">背景</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="grid grid-cols-3 gap-3">
{config.allowBatchSize ? (
<div className="space-y-2">
<Label className="text-white/80">候选结果</Label>
<Select
onValueChange={(value) =>
handleNumericField( handleNumericField(
"batchSize", "width",
clampNumber( clampNumber(
Number.parseInt(value, 10) || 1, Number.parseInt(event.target.value, 10) || 1,
1, 1,
config.maxBatchSize config.maxOutputEdge
) )
) )
} }
value={String(formState.batchSize)} type="number"
value={formState.width}
/>
</div>
<div className="space-y-1.5">
<Label
className="text-xs text-white/70"
htmlFor="enhance-workspace-height"
> >
<SelectTrigger className="border-white/10 bg-white/5 text-white"> 高度
</Label>
<Input
className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
id="enhance-workspace-height"
max={config.maxOutputEdge}
min="1"
onChange={(event) =>
handleNumericField(
"height",
clampNumber(
Number.parseInt(event.target.value, 10) || 1,
1,
config.maxOutputEdge
)
)
}
type="number"
value={formState.height}
/>
</div>
{config.allowBatchSize ? (
<div className="space-y-1.5">
<Label className="text-xs text-white/70">候选</Label>
<Select
onValueChange={(value) =>
handleNumericField(
"batchSize",
clampNumber(
Number.parseInt(value, 10) || 1,
1,
config.maxBatchSize
)
)
}
value={String(formState.batchSize)}
>
<SelectTrigger
className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
>
<SelectValue />
</SelectTrigger>
<SelectContent>
{Array.from(
{ length: config.maxBatchSize },
(_, index) => index + 1
).map((item) => (
<SelectItem key={item} value={String(item)}>
{item} 张
</SelectItem>
))}
</SelectContent>
</Select>
</div>
) : (
<div className="space-y-1.5">
<Label
className="text-xs text-white/70"
htmlFor="enhance-workspace-seed"
>
Seed
</Label>
<Input
className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
id="enhance-workspace-seed"
onChange={(event) =>
handleNumericField(
"seed",
Number.parseInt(event.target.value, 10) || 1337
)
}
type="number"
value={formState.seed}
/>
</div>
)}
<div className="space-y-1.5">
<Label className="text-xs text-white/70">模式</Label>
<Select
onValueChange={(value) =>
setFormState((prev) => ({
...prev,
model: value as FormState["model"],
}))
}
value={formState.model}
>
<SelectTrigger className={`${SOLID_PANEL_FIELD_CLASS} h-10`}>
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{Array.from( <SelectItem value="Redefine">Redefine</SelectItem>
{ length: config.maxBatchSize }, <SelectItem value="Recovery">Recovery</SelectItem>
(_, index) => index + 1 <SelectItem value="Recovery V2">Recovery V2</SelectItem>
).map((item) => ( <SelectItem value="Reimagine">Reimagine</SelectItem>
<SelectItem key={item} value={String(item)}>
{item} 张
</SelectItem>
))}
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
) : null} <div className="space-y-1.5">
<div className="space-y-2"> <Label className="text-xs text-white/70">格式</Label>
<Label className="text-white/80" htmlFor="enhance-workspace-seed"> <Select
Seed onValueChange={(value) =>
</Label> setFormState((prev) => ({
<Input ...prev,
className="border-white/10 bg-white/5 text-white" output_format: value as FormState["output_format"],
id="enhance-workspace-seed" }))
onChange={(event) => }
handleNumericField( value={formState.output_format}
"seed", >
Number.parseInt(event.target.value, 10) || 1337 <SelectTrigger className={`${SOLID_PANEL_FIELD_CLASS} h-10`}>
) <SelectValue />
} </SelectTrigger>
type="number" <SelectContent>
value={formState.seed} <SelectItem value="jpg">JPG</SelectItem>
/> <SelectItem value="png">PNG</SelectItem>
</div> <SelectItem value="webp">WEBP</SelectItem>
<div className="space-y-2"> </SelectContent>
<Label </Select>
className="text-white/80" </div>
htmlFor="enhance-workspace-scale" <div className="space-y-1.5">
> <Label className="text-xs text-white/70">区域</Label>
放大倍数 <Select
</Label> onValueChange={(value) =>
<Input setFormState((prev) => ({
className="border-white/10 bg-white/5 text-white" ...prev,
id="enhance-workspace-scale" subject_detection: value as FormState["subject_detection"],
max="32" }))
min="1" }
onChange={(event) => value={formState.subject_detection}
handleNumericField( >
"image_scaling_factor", <SelectTrigger className={`${SOLID_PANEL_FIELD_CLASS} h-10`}>
clampNumber( <SelectValue />
Number.parseFloat(event.target.value) || 1, </SelectTrigger>
1, <SelectContent>
32 <SelectItem value="All">全部</SelectItem>
<SelectItem value="Foreground">前景</SelectItem>
<SelectItem value="Background">背景</SelectItem>
</SelectContent>
</Select>
</div>
{config.allowBatchSize ? (
<div className="space-y-1.5">
<Label
className="text-xs text-white/70"
htmlFor="enhance-workspace-seed"
>
Seed
</Label>
<Input
className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
id="enhance-workspace-seed"
onChange={(event) =>
handleNumericField(
"seed",
Number.parseInt(event.target.value, 10) || 1337
)
}
type="number"
value={formState.seed}
/>
</div>
) : null}
<div className="space-y-1.5">
<Label
className="text-xs text-white/70"
htmlFor="enhance-workspace-scale"
>
放大
</Label>
<Input
className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
id="enhance-workspace-scale"
max="32"
min="1"
onChange={(event) =>
handleNumericField(
"image_scaling_factor",
clampNumber(
Number.parseFloat(event.target.value) || 1,
1,
32
)
) )
) }
} step="0.5"
step="0.5" type="number"
type="number" value={formState.image_scaling_factor}
value={formState.image_scaling_factor} />
/> </div>
</div> </div>
</div> </div>
<div className="grid grid-cols-3 gap-3"> <div className="space-y-2">
<div className="rounded-2xl border border-white/10 bg-white/5 p-3"> <div className="text-[11px] uppercase tracking-[0.08em] text-white/65">
<div className="flex items-center justify-between gap-3"> 增强开关
<div> </div>
<div className="font-medium text-sm text-white">人脸增强</div> <div className="grid grid-cols-3 gap-3">
<div className="mt-1 text-[11px] text-white/45 leading-4"> <div
适合人像和模特图修复 className={cn(
</div> SOLID_PANEL_CARD_CLASS,
</div> "flex items-center justify-between gap-3 px-3 py-3"
)}
>
<span className="text-sm text-white">人脸增强</span>
<Switch <Switch
checked={formState.face_enhancement} checked={formState.face_enhancement}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
@ -862,15 +880,13 @@ export function EnhanceProWorkspace({
} }
/> />
</div> </div>
</div> <div
<div className="rounded-2xl border border-white/10 bg-white/5 p-3"> className={cn(
<div className="flex items-center justify-between gap-3"> SOLID_PANEL_CARD_CLASS,
<div> "flex items-center justify-between gap-3 px-3 py-3"
<div className="font-medium text-sm text-white">启用放大</div> )}
<div className="mt-1 text-[11px] text-white/45 leading-4"> >
强化增强时的上采样 <span className="text-sm text-white">启用放大</span>
</div>
</div>
<Switch <Switch
checked={formState.upscaling_activated} checked={formState.upscaling_activated}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
@ -881,15 +897,13 @@ export function EnhanceProWorkspace({
} }
/> />
</div> </div>
</div> <div
<div className="rounded-2xl border border-white/10 bg-white/5 p-3"> className={cn(
<div className="flex items-center justify-between gap-3"> SOLID_PANEL_CARD_CLASS,
<div> "flex items-center justify-between gap-3 px-3 py-3"
<div className="font-medium text-sm text-white">裁剪铺满</div> )}
<div className="mt-1 text-[11px] text-white/45 leading-4"> >
尺寸比例不同时裁切填充 <span className="text-sm text-white">裁剪铺满</span>
</div>
</div>
<Switch <Switch
checked={formState.crop_to_fill} checked={formState.crop_to_fill}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
@ -903,13 +917,15 @@ export function EnhanceProWorkspace({
{config.enableAdvancedControls ? ( {config.enableAdvancedControls ? (
<> <>
<Separator className="bg-white/10" /> <Separator className="bg-white/10" />
<div className="space-y-3"> <div className="space-y-2">
<div className="font-medium text-sm text-white">高级调节</div> <div className="text-[11px] uppercase tracking-[0.08em] text-white/65">
<div className="grid grid-cols-2 gap-3"> 高级调节
<div className="space-y-2"> </div>
<Label className="text-white/80">Creativity (1-6)</Label> <div className="grid grid-cols-3 gap-3">
<div className="space-y-1.5">
<Label className="text-xs text-white/70">创造力</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="6" max="6"
min="1" min="1"
onChange={(event) => onChange={(event) =>
@ -926,10 +942,10 @@ export function EnhanceProWorkspace({
value={formState.creativity} value={formState.creativity}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80">Texture (1-5)</Label> <Label className="text-xs text-white/70">纹理</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="5" max="5"
min="1" min="1"
onChange={(event) => onChange={(event) =>
@ -946,10 +962,10 @@ export function EnhanceProWorkspace({
value={formState.texture} value={formState.texture}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80">Detail (0-1)</Label> <Label className="text-xs text-white/70">细节</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="1" max="1"
min="0" min="0"
onChange={(event) => onChange={(event) =>
@ -967,10 +983,10 @@ export function EnhanceProWorkspace({
value={formState.detail} value={formState.detail}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80">Sharpen (0-1)</Label> <Label className="text-xs text-white/70">锐化</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="1" max="1"
min="0" min="0"
onChange={(event) => onChange={(event) =>
@ -988,10 +1004,10 @@ export function EnhanceProWorkspace({
value={formState.sharpen} value={formState.sharpen}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80">Denoise (0-1)</Label> <Label className="text-xs text-white/70">降噪</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="1" max="1"
min="0" min="0"
onChange={(event) => onChange={(event) =>
@ -1009,10 +1025,10 @@ export function EnhanceProWorkspace({
value={formState.denoise} value={formState.denoise}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80">Face Strength (0-1)</Label> <Label className="text-xs text-white/70">脸部力度</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="1" max="1"
min="0" min="0"
onChange={(event) => onChange={(event) =>
@ -1030,12 +1046,10 @@ export function EnhanceProWorkspace({
value={formState.face_enhancement_strength} value={formState.face_enhancement_strength}
/> />
</div> </div>
<div className="space-y-2"> <div className="space-y-1.5">
<Label className="text-white/80"> <Label className="text-xs text-white/70">脸部创意</Label>
Face Creativity (0-1)
</Label>
<Input <Input
className="border-white/10 bg-white/5 text-white" className={`${SOLID_PANEL_FIELD_CLASS} h-10`}
max="1" max="1"
min="0" min="0"
onChange={(event) => onChange={(event) =>
@ -1059,12 +1073,12 @@ export function EnhanceProWorkspace({
) : null} ) : null}
</div> </div>
<div className="border-white/10 border-t px-5 py-4"> <div className="border-white/10 border-t px-4 py-3">
<div className="mb-3 flex items-center justify-between text-white/45 text-xs"> <div className="mb-3 flex items-center justify-between text-white/45 text-xs">
<span> <span>
{generatedImages.length > 0 {generatedImages.length > 0
? `已生成 ${generatedImages.length} 张候选结果` ? `已生成 ${generatedImages.length} 张候选结果`
: "结果会在生成后显示并可发送回画布"} : "生成后可直接发送回画布"}
</span> </span>
{selectedGeneratedImage ? ( {selectedGeneratedImage ? (
<span className="inline-flex items-center gap-1 text-emerald-300"> <span className="inline-flex items-center gap-1 text-emerald-300">
@ -1075,7 +1089,7 @@ export function EnhanceProWorkspace({
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button <Button
className="h-11 flex-1 rounded-2xl bg-[#0f62fe] text-white hover:bg-[#0a58e0]" className="h-10 flex-1 rounded-2xl bg-[#0f62fe] text-white hover:bg-[#0a58e0]"
disabled={isSubmitting || !sourceImageUrl} disabled={isSubmitting || !sourceImageUrl}
onClick={handleSubmit} onClick={handleSubmit}
type="button" type="button"
@ -1088,7 +1102,7 @@ export function EnhanceProWorkspace({
开始增强 Pro 开始增强 Pro
</Button> </Button>
<Button <Button
className="h-11 rounded-2xl border-white/10 bg-white/5 px-4 text-white hover:bg-white/10 hover:text-white" className="h-10 rounded-2xl border-white/10 bg-[#1a1b22] px-4 text-white hover:bg-[#23242c] hover:text-white"
disabled={!selectedGeneratedImage} disabled={!selectedGeneratedImage}
onClick={handleApply} onClick={handleApply}
type="button" type="button"

View File

@ -2961,7 +2961,7 @@ export function RealtimeCanvasDialog({
)} )}
<div className="pointer-events-none absolute top-6 left-6 z-50 flex flex-col gap-3"> <div className="pointer-events-none absolute top-6 left-6 z-50 flex flex-col gap-3">
<button <button
className="pointer-events-auto flex items-center gap-3 rounded-full border border-border/40 bg-background/80 px-4 py-2 shadow-sm backdrop-blur-md transition hover:bg-background" className="pointer-events-auto flex items-center gap-3 rounded-full border border-white/10 bg-[#111216] px-4 py-2 text-white shadow-sm transition hover:bg-[#1a1b22]"
onClick={handleGoHome} onClick={handleGoHome}
title="返回首页" title="返回首页"
type="button" type="button"
@ -2981,18 +2981,18 @@ export function RealtimeCanvasDialog({
<Sparkles className="h-3.5 w-3.5" /> <Sparkles className="h-3.5 w-3.5" />
</div> </div>
)} )}
<span className="font-semibold text-foreground text-sm"> <span className="font-semibold text-sm text-white">
{siteName} {siteName}
</span> </span>
</button> </button>
<div className="pointer-events-auto inline-flex w-fit items-center gap-1 rounded-full border border-border/40 bg-background/85 p-1.5 shadow-sm backdrop-blur-md"> <div className="pointer-events-auto inline-flex w-fit items-center gap-1 rounded-full border border-white/10 bg-[#111216] p-1.5 shadow-sm">
<button <button
className={cn( className={cn(
"inline-flex items-center gap-2 rounded-full px-3 py-2 text-sm transition", "inline-flex items-center gap-2 rounded-full px-3 py-2 text-sm transition",
workspaceMode === "realtime" workspaceMode === "realtime"
? "bg-foreground text-background shadow-sm" ? "bg-white text-black shadow-sm"
: "text-foreground/70 hover:bg-background hover:text-foreground" : "bg-[#1a1b22] text-white/78 hover:bg-[#23242c] hover:text-white"
)} )}
onClick={() => setWorkspaceMode("realtime")} onClick={() => setWorkspaceMode("realtime")}
type="button" type="button"
@ -3004,8 +3004,8 @@ export function RealtimeCanvasDialog({
className={cn( className={cn(
"inline-flex items-center gap-2 rounded-full px-3 py-2 text-sm transition", "inline-flex items-center gap-2 rounded-full px-3 py-2 text-sm transition",
workspaceMode === "enhance-pro" workspaceMode === "enhance-pro"
? "bg-foreground text-background shadow-sm" ? "bg-white text-black shadow-sm"
: "text-foreground/70 hover:bg-background hover:text-foreground" : "bg-[#1a1b22] text-white/78 hover:bg-[#23242c] hover:text-white"
)} )}
onClick={() => setWorkspaceMode("enhance-pro")} onClick={() => setWorkspaceMode("enhance-pro")}
type="button" type="button"
@ -3017,9 +3017,9 @@ export function RealtimeCanvasDialog({
</div> </div>
<div className="pointer-events-none absolute top-6 right-6 z-50"> <div className="pointer-events-none absolute top-6 right-6 z-50">
<div className="pointer-events-auto rounded-full border border-black bg-black p-1 shadow-sm"> <div className="pointer-events-auto rounded-full border border-white/10 bg-[#111216] p-1 shadow-sm">
<Button <Button
className="h-7 w-7 rounded-full text-white transition hover:bg-white/10 hover:text-white" className="h-7 w-7 rounded-full bg-[#1a1b22] text-white transition hover:bg-[#23242c] hover:text-white"
onClick={handleCloseRealtime} onClick={handleCloseRealtime}
size="icon" size="icon"
title="关闭" title="关闭"
@ -3290,7 +3290,7 @@ export function RealtimeCanvasDialog({
/> />
</div> </div>
</div> </div>
<div className="absolute top-28 bottom-4 left-4 z-10 flex w-16 max-w-[18vw] flex-col rounded-[24px] border border-border/40 bg-background/80 p-2 shadow-xl backdrop-blur-md"> <div className="absolute top-28 bottom-4 left-4 z-10 flex w-16 max-w-[18vw] flex-col rounded-[24px] border border-border/40 bg-[#111216] p-2 shadow-xl">
<div className="flex items-center justify-center border-border/10 border-b pb-3"> <div className="flex items-center justify-center border-border/10 border-b pb-3">
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-muted text-foreground"> <div className="flex h-8 w-8 items-center justify-center rounded-full bg-muted text-foreground">
<Layers3 className="h-4 w-4" /> <Layers3 className="h-4 w-4" />
@ -3433,7 +3433,7 @@ export function RealtimeCanvasDialog({
/> />
<div className="-translate-x-1/2 pointer-events-none absolute bottom-4 left-1/2 z-30 flex w-[min(600px,calc(100vw-2rem))] flex-col items-center gap-2.5"> <div className="-translate-x-1/2 pointer-events-none absolute bottom-4 left-1/2 z-30 flex w-[min(600px,calc(100vw-2rem))] flex-col items-center gap-2.5">
<TooltipProvider delayDuration={120}> <TooltipProvider delayDuration={120}>
<div className="pointer-events-auto flex flex-wrap items-center justify-center gap-1 rounded-[24px] border border-border/40 bg-background/80 p-1.5 shadow-xl backdrop-blur-md"> <div className="pointer-events-auto flex flex-wrap items-center justify-center gap-1 rounded-[24px] border border-border/40 bg-[#111216] p-1.5 shadow-xl">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
@ -3760,7 +3760,7 @@ export function RealtimeCanvasDialog({
</div> </div>
</TooltipProvider> </TooltipProvider>
<div className="pointer-events-auto w-full rounded-[24px] border border-border/40 bg-background/80 p-4 shadow-2xl backdrop-blur-md"> <div className="pointer-events-auto w-full rounded-[24px] border border-border/40 bg-[#111216] p-4 shadow-2xl">
<Textarea <Textarea
className="min-h-[56px] resize-none border-0 bg-transparent px-1 py-0.5 text-[15px] leading-7 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0" className="min-h-[56px] resize-none border-0 bg-transparent px-1 py-0.5 text-[15px] leading-7 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0"
onBlur={() => scheduleFlush(true, false)} onBlur={() => scheduleFlush(true, false)}