refactor: polish realtime enhance workspace layout
This commit is contained in:
parent
97f3bf2c20
commit
94478e469f
@ -7,7 +7,13 @@ import {
|
||||
Send,
|
||||
Sparkles,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
type PointerEvent as ReactPointerEvent,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { toast } from "sonner";
|
||||
import useSWR from "swr";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@ -93,14 +99,18 @@ const SOLID_PANEL_FIELD_CLASS =
|
||||
"border-[#e7e1d4] bg-[#fffdfa] text-foreground shadow-[0_8px_20px_rgba(15,23,42,0.05)]";
|
||||
const SOLID_PANEL_CARD_CLASS =
|
||||
"rounded-[22px] border border-[#e7e1d4] bg-[#fffdfa] shadow-[0_8px_20px_rgba(15,23,42,0.05)]";
|
||||
const PANEL_SECTION_TITLE_CLASS = "font-semibold text-[13px] text-slate-700";
|
||||
const PANEL_SECTION_NOTE_CLASS = "text-[11px] leading-5 text-slate-500";
|
||||
const PANEL_SECTION_TITLE_CLASS = "font-semibold text-[12px] text-slate-700";
|
||||
const PANEL_SECTION_NOTE_CLASS = "text-[10.5px] leading-4 text-slate-500";
|
||||
const SOLID_PANEL_SELECT_CONTENT_CLASS =
|
||||
"border-[#e7e1d4] bg-[#fffdfa] shadow-[0_16px_34px_rgba(15,23,42,0.08)]";
|
||||
const PRIMARY_ACTION_BUTTON_CLASS =
|
||||
"border border-[#2563eb] bg-[#2563eb] text-white shadow-[0_10px_22px_rgba(37,99,235,0.18)] transition hover:border-[#1d4ed8] hover:bg-[#1d4ed8] disabled:border-[#e7e1d4] disabled:bg-slate-200 disabled:text-slate-500 disabled:shadow-none";
|
||||
const SECONDARY_ACTION_BUTTON_CLASS =
|
||||
"border border-[#d8e4ff] bg-[#eef4ff] text-[#1d4ed8] shadow-[0_8px_20px_rgba(59,130,246,0.10)] transition hover:bg-[#e4eeff] hover:text-[#1e40af] disabled:border-[#e7e1d4] disabled:bg-slate-100 disabled:text-slate-400 disabled:shadow-none";
|
||||
const COMPACT_FIELD_CLASS = `${SOLID_PANEL_FIELD_CLASS} h-10 rounded-[16px] text-sm`;
|
||||
const COMPACT_LABEL_CLASS = "text-slate-600 text-[11px] leading-4";
|
||||
const COMPACT_TOGGLE_CARD_CLASS =
|
||||
"flex items-center justify-between gap-2.5 px-3 py-2.5";
|
||||
|
||||
function clampNumber(value: number, min: number, max: number) {
|
||||
return Math.min(max, Math.max(min, value));
|
||||
@ -278,6 +288,15 @@ export function EnhanceProWorkspace({
|
||||
EnhanceProImageResult[]
|
||||
>([]);
|
||||
const [lastErrorMessage, setLastErrorMessage] = useState("");
|
||||
const [previewOffset, setPreviewOffset] = useState({ x: 0, y: 0 });
|
||||
const [isPreviewDragging, setIsPreviewDragging] = useState(false);
|
||||
const previewDragStateRef = useRef<{
|
||||
pointerId: number;
|
||||
startX: number;
|
||||
startY: number;
|
||||
originX: number;
|
||||
originY: number;
|
||||
} | null>(null);
|
||||
|
||||
const { data: configPayload, isLoading } = useSWR<{
|
||||
success?: boolean;
|
||||
@ -352,6 +371,12 @@ export function EnhanceProWorkspace({
|
||||
setLastErrorMessage("");
|
||||
}, [sourceImageUrl]);
|
||||
|
||||
useEffect(() => {
|
||||
setPreviewOffset({ x: 0, y: 0 });
|
||||
setIsPreviewDragging(false);
|
||||
previewDragStateRef.current = null;
|
||||
}, [activePreviewUrl]);
|
||||
|
||||
const handleNumericField = <K extends keyof FormState>(
|
||||
key: K,
|
||||
nextValue: number
|
||||
@ -474,7 +499,7 @@ export function EnhanceProWorkspace({
|
||||
isSource?: boolean;
|
||||
}> = [];
|
||||
|
||||
if (sourceImageUrl) {
|
||||
if (generatedImages.length > 0 && sourceImageUrl) {
|
||||
items.push({
|
||||
key: "source",
|
||||
label: "原图",
|
||||
@ -494,21 +519,83 @@ export function EnhanceProWorkspace({
|
||||
return items;
|
||||
}, [generatedImages, sourceImageUrl]);
|
||||
|
||||
const handlePreviewPointerDown = (
|
||||
event: ReactPointerEvent<HTMLDivElement>
|
||||
) => {
|
||||
if (!activePreviewUrl || event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previewDragStateRef.current = {
|
||||
pointerId: event.pointerId,
|
||||
startX: event.clientX,
|
||||
startY: event.clientY,
|
||||
originX: previewOffset.x,
|
||||
originY: previewOffset.y,
|
||||
};
|
||||
setIsPreviewDragging(true);
|
||||
event.currentTarget.setPointerCapture(event.pointerId);
|
||||
};
|
||||
|
||||
const handlePreviewPointerMove = (
|
||||
event: ReactPointerEvent<HTMLDivElement>
|
||||
) => {
|
||||
const dragState = previewDragStateRef.current;
|
||||
if (!dragState || dragState.pointerId !== event.pointerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
setPreviewOffset({
|
||||
x: dragState.originX + event.clientX - dragState.startX,
|
||||
y: dragState.originY + event.clientY - dragState.startY,
|
||||
});
|
||||
};
|
||||
|
||||
const finishPreviewDrag = (event?: ReactPointerEvent<HTMLDivElement>) => {
|
||||
const dragState = previewDragStateRef.current;
|
||||
if (!dragState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
event &&
|
||||
event.currentTarget.hasPointerCapture(dragState.pointerId)
|
||||
) {
|
||||
event.currentTarget.releasePointerCapture(dragState.pointerId);
|
||||
}
|
||||
|
||||
previewDragStateRef.current = null;
|
||||
setIsPreviewDragging(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative flex h-full w-full bg-background text-foreground">
|
||||
<div className="relative flex min-w-0 flex-1 items-center justify-center overflow-hidden bg-muted/20">
|
||||
{activePreviewUrl ? (
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-full w-full items-center justify-center overflow-hidden touch-none select-none",
|
||||
isPreviewDragging ? "cursor-grabbing" : "cursor-grab"
|
||||
)}
|
||||
onDoubleClick={() => setPreviewOffset({ x: 0, y: 0 })}
|
||||
onPointerCancel={finishPreviewDrag}
|
||||
onPointerDown={handlePreviewPointerDown}
|
||||
onPointerMove={handlePreviewPointerMove}
|
||||
onPointerUp={finishPreviewDrag}
|
||||
>
|
||||
<img
|
||||
alt={activePreviewLabel}
|
||||
className="max-h-full max-w-full object-contain"
|
||||
className="pointer-events-none max-h-full max-w-full object-contain transition-transform duration-75"
|
||||
src={getDisplayImageUrl(activePreviewUrl, 1800)}
|
||||
style={{
|
||||
transform: `translate(${previewOffset.x}px, ${previewOffset.y}px)`,
|
||||
}}
|
||||
/>
|
||||
<div className="pointer-events-none absolute top-6 left-6 flex items-center gap-2 rounded-full border border-[#e7e1d4] bg-[#fffdfa]/95 px-3 py-1.5 text-muted-foreground text-xs shadow-sm backdrop-blur-sm">
|
||||
<ImageIcon className="h-3.5 w-3.5" />
|
||||
<span>{activePreviewLabel}</span>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex max-w-md flex-col items-center gap-3 px-6 text-center">
|
||||
<Sparkles className="h-10 w-10 text-muted-foreground/35" />
|
||||
@ -522,7 +609,7 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sidePreviewItems.length > 0 ? (
|
||||
{generatedImages.length > 0 && sidePreviewItems.length > 0 ? (
|
||||
<div className="absolute right-6 bottom-28 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-[#e7e1d4] bg-[#fffdfa]/95 px-3 py-3 shadow-xl backdrop-blur-sm">
|
||||
{sidePreviewItems.map((item, index) => {
|
||||
@ -557,13 +644,13 @@ export function EnhanceProWorkspace({
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute top-20 right-6 bottom-6 z-20 w-[420px] max-w-[42vw]">
|
||||
<div className="h-full space-y-4 overflow-y-auto pr-1 pb-6">
|
||||
<div className="pointer-events-none absolute top-5 right-5 bottom-5 z-20 w-[412px] max-w-[41vw]">
|
||||
<div className="h-full space-y-3 overflow-y-auto pr-1 pb-3">
|
||||
{isLoading ? (
|
||||
<div
|
||||
className={cn(
|
||||
PANEL_SHELL_CLASS,
|
||||
"flex items-center gap-2 px-4 py-3 text-muted-foreground text-sm"
|
||||
"flex items-center gap-2 px-3.5 py-2.5 text-muted-foreground text-sm"
|
||||
)}
|
||||
>
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
@ -584,13 +671,11 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-4 px-4 py-4")}>
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-3 px-3.5 py-3.5")}>
|
||||
<div className="space-y-2">
|
||||
<Label className={PANEL_SECTION_TITLE_CLASS}>增强预设</Label>
|
||||
<Select onValueChange={handleSelectPreset} value={selectedPresetId}>
|
||||
<SelectTrigger
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
>
|
||||
<SelectTrigger className={COMPACT_FIELD_CLASS}>
|
||||
<SelectValue placeholder="选择一个增强预设" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className={SOLID_PANEL_SELECT_CONTENT_CLASS}>
|
||||
@ -617,7 +702,7 @@ export function EnhanceProWorkspace({
|
||||
增强提示词
|
||||
</Label>
|
||||
<Textarea
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} min-h-[92px] resize-none rounded-[22px] placeholder:text-muted-foreground/70`}
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} min-h-[76px] resize-none rounded-[18px] text-sm placeholder:text-muted-foreground/70`}
|
||||
id="enhance-workspace-prompt"
|
||||
onChange={(event) =>
|
||||
setFormState((prev) => ({
|
||||
@ -626,24 +711,21 @@ export function EnhanceProWorkspace({
|
||||
}))
|
||||
}
|
||||
placeholder="例如:保持主体不变,提升画质层次、纹理和局部细节,让结果更高级。"
|
||||
rows={3}
|
||||
rows={2}
|
||||
value={formState.prompt}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-3 px-4 py-4")}>
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-2.5 px-3.5 py-3.5")}>
|
||||
<div className={PANEL_SECTION_TITLE_CLASS}>基础参数</div>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div className="grid grid-cols-4 gap-2.5">
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
className="text-slate-600 text-xs"
|
||||
htmlFor="enhance-workspace-width"
|
||||
>
|
||||
<Label className={COMPACT_LABEL_CLASS} htmlFor="enhance-workspace-width">
|
||||
宽度
|
||||
</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
id="enhance-workspace-width"
|
||||
max={config.maxOutputEdge}
|
||||
min="1"
|
||||
@ -662,14 +744,11 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
className="text-slate-600 text-xs"
|
||||
htmlFor="enhance-workspace-height"
|
||||
>
|
||||
<Label className={COMPACT_LABEL_CLASS} htmlFor="enhance-workspace-height">
|
||||
高度
|
||||
</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
id="enhance-workspace-height"
|
||||
max={config.maxOutputEdge}
|
||||
min="1"
|
||||
@ -689,7 +768,7 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
{config.allowBatchSize ? (
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">候选</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>候选</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
handleNumericField(
|
||||
@ -703,9 +782,7 @@ export function EnhanceProWorkspace({
|
||||
}
|
||||
value={String(formState.batchSize)}
|
||||
>
|
||||
<SelectTrigger
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
>
|
||||
<SelectTrigger className={COMPACT_FIELD_CLASS}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className={SOLID_PANEL_SELECT_CONTENT_CLASS}>
|
||||
@ -722,14 +799,11 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
className="text-slate-600 text-xs"
|
||||
htmlFor="enhance-workspace-seed"
|
||||
>
|
||||
<Label className={COMPACT_LABEL_CLASS} htmlFor="enhance-workspace-seed">
|
||||
Seed
|
||||
</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
id="enhance-workspace-seed"
|
||||
onChange={(event) =>
|
||||
handleNumericField(
|
||||
@ -743,7 +817,7 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
)}
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">模式</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>模式</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setFormState((prev) => ({
|
||||
@ -753,9 +827,7 @@ export function EnhanceProWorkspace({
|
||||
}
|
||||
value={formState.model}
|
||||
>
|
||||
<SelectTrigger
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
>
|
||||
<SelectTrigger className={COMPACT_FIELD_CLASS}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className={SOLID_PANEL_SELECT_CONTENT_CLASS}>
|
||||
@ -767,7 +839,7 @@ export function EnhanceProWorkspace({
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">格式</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>格式</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setFormState((prev) => ({
|
||||
@ -777,9 +849,7 @@ export function EnhanceProWorkspace({
|
||||
}
|
||||
value={formState.output_format}
|
||||
>
|
||||
<SelectTrigger
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
>
|
||||
<SelectTrigger className={COMPACT_FIELD_CLASS}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className={SOLID_PANEL_SELECT_CONTENT_CLASS}>
|
||||
@ -790,7 +860,7 @@ export function EnhanceProWorkspace({
|
||||
</Select>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">区域</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>区域</Label>
|
||||
<Select
|
||||
onValueChange={(value) =>
|
||||
setFormState((prev) => ({
|
||||
@ -800,9 +870,7 @@ export function EnhanceProWorkspace({
|
||||
}
|
||||
value={formState.subject_detection}
|
||||
>
|
||||
<SelectTrigger
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
>
|
||||
<SelectTrigger className={COMPACT_FIELD_CLASS}>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className={SOLID_PANEL_SELECT_CONTENT_CLASS}>
|
||||
@ -814,14 +882,11 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
{config.allowBatchSize ? (
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
className="text-slate-600 text-xs"
|
||||
htmlFor="enhance-workspace-seed"
|
||||
>
|
||||
<Label className={COMPACT_LABEL_CLASS} htmlFor="enhance-workspace-seed">
|
||||
Seed
|
||||
</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
id="enhance-workspace-seed"
|
||||
onChange={(event) =>
|
||||
handleNumericField(
|
||||
@ -835,14 +900,11 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
) : null}
|
||||
<div className="space-y-1.5">
|
||||
<Label
|
||||
className="text-slate-600 text-xs"
|
||||
htmlFor="enhance-workspace-scale"
|
||||
>
|
||||
<Label className={COMPACT_LABEL_CLASS} htmlFor="enhance-workspace-scale">
|
||||
放大
|
||||
</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
id="enhance-workspace-scale"
|
||||
max="32"
|
||||
min="1"
|
||||
@ -864,16 +926,16 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-3 px-4 py-4")}>
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-2.5 px-3.5 py-3.5")}>
|
||||
<div className={PANEL_SECTION_TITLE_CLASS}>增强开关</div>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div className="grid grid-cols-3 gap-2.5">
|
||||
<div
|
||||
className={cn(
|
||||
SOLID_PANEL_CARD_CLASS,
|
||||
"flex items-center justify-between gap-3 px-3 py-3"
|
||||
COMPACT_TOGGLE_CARD_CLASS
|
||||
)}
|
||||
>
|
||||
<span className="text-foreground text-sm">人脸增强</span>
|
||||
<span className="text-foreground text-xs">人脸增强</span>
|
||||
<Switch
|
||||
checked={formState.face_enhancement}
|
||||
onCheckedChange={(checked) =>
|
||||
@ -887,10 +949,10 @@ export function EnhanceProWorkspace({
|
||||
<div
|
||||
className={cn(
|
||||
SOLID_PANEL_CARD_CLASS,
|
||||
"flex items-center justify-between gap-3 px-3 py-3"
|
||||
COMPACT_TOGGLE_CARD_CLASS
|
||||
)}
|
||||
>
|
||||
<span className="text-foreground text-sm">启用放大</span>
|
||||
<span className="text-foreground text-xs">启用放大</span>
|
||||
<Switch
|
||||
checked={formState.upscaling_activated}
|
||||
onCheckedChange={(checked) =>
|
||||
@ -904,10 +966,10 @@ export function EnhanceProWorkspace({
|
||||
<div
|
||||
className={cn(
|
||||
SOLID_PANEL_CARD_CLASS,
|
||||
"flex items-center justify-between gap-3 px-3 py-3"
|
||||
COMPACT_TOGGLE_CARD_CLASS
|
||||
)}
|
||||
>
|
||||
<span className="text-foreground text-sm">裁剪铺满</span>
|
||||
<span className="text-foreground text-xs">裁剪铺满</span>
|
||||
<Switch
|
||||
checked={formState.crop_to_fill}
|
||||
onCheckedChange={(checked) =>
|
||||
@ -919,16 +981,16 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
|
||||
{config.enableAdvancedControls ? (
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-3 px-4 py-4")}>
|
||||
<div className={cn(PANEL_SHELL_CLASS, "space-y-2.5 px-3.5 py-3.5")}>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className={PANEL_SECTION_TITLE_CLASS}>高级调节</div>
|
||||
<div className={PANEL_SECTION_NOTE_CLASS}>细修参数</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<div className="grid grid-cols-4 gap-2.5">
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">创造力</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>创造力</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="6"
|
||||
min="1"
|
||||
onChange={(event) =>
|
||||
@ -946,9 +1008,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">纹理</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>纹理</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="5"
|
||||
min="1"
|
||||
onChange={(event) =>
|
||||
@ -966,9 +1028,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">细节</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>细节</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="1"
|
||||
min="0"
|
||||
onChange={(event) =>
|
||||
@ -987,9 +1049,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">锐化</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>锐化</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="1"
|
||||
min="0"
|
||||
onChange={(event) =>
|
||||
@ -1008,9 +1070,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">降噪</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>降噪</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="1"
|
||||
min="0"
|
||||
onChange={(event) =>
|
||||
@ -1029,9 +1091,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">脸部力度</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>脸部力度</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="1"
|
||||
min="0"
|
||||
onChange={(event) =>
|
||||
@ -1050,9 +1112,9 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-slate-600 text-xs">脸部创意</Label>
|
||||
<Label className={COMPACT_LABEL_CLASS}>脸部创意</Label>
|
||||
<Input
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[18px]`}
|
||||
className={COMPACT_FIELD_CLASS}
|
||||
max="1"
|
||||
min="0"
|
||||
onChange={(event) =>
|
||||
@ -1076,8 +1138,8 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none absolute bottom-6 left-1/2 z-30 flex w-fit max-w-[calc(100vw-2rem)] -translate-x-1/2 flex-col items-center gap-2">
|
||||
<div className="pointer-events-auto rounded-full border border-[#e7e1d4] bg-[#fffdfa]/95 px-4 py-1.5 text-muted-foreground text-xs shadow-lg backdrop-blur-xl">
|
||||
<div className="pointer-events-none absolute bottom-5 left-1/2 z-30 flex w-fit max-w-[calc(100vw-2rem)] -translate-x-1/2 flex-col items-center gap-1.5">
|
||||
<div className="pointer-events-auto rounded-full border border-[#e7e1d4] bg-[#fffdfa]/95 px-3.5 py-1 text-muted-foreground text-[11px] shadow-lg backdrop-blur-xl">
|
||||
<span className="inline-flex items-center gap-1.5">
|
||||
{selectedGeneratedImage ? (
|
||||
<CheckCircle2 className="h-3.5 w-3.5 text-emerald-600" />
|
||||
@ -1085,10 +1147,10 @@ export function EnhanceProWorkspace({
|
||||
{actionHint}
|
||||
</span>
|
||||
</div>
|
||||
<div className="pointer-events-auto inline-flex items-center justify-center gap-3 rounded-full border border-[#e7e1d4] bg-[#fffdfa]/95 p-2 shadow-2xl backdrop-blur-xl">
|
||||
<div className="pointer-events-auto inline-flex items-center justify-center gap-2 rounded-full border border-[#e7e1d4] bg-[#fffdfa]/95 p-1.5 shadow-2xl backdrop-blur-xl">
|
||||
<Button
|
||||
className={cn(
|
||||
"h-11 min-w-[220px] rounded-full px-6",
|
||||
"h-10 min-w-[208px] rounded-full px-5 text-sm",
|
||||
PRIMARY_ACTION_BUTTON_CLASS
|
||||
)}
|
||||
disabled={isSubmitting || !sourceImageUrl}
|
||||
@ -1104,7 +1166,7 @@ export function EnhanceProWorkspace({
|
||||
</Button>
|
||||
<Button
|
||||
className={cn(
|
||||
"h-11 min-w-[220px] rounded-full px-6",
|
||||
"h-10 min-w-[208px] rounded-full px-5 text-sm",
|
||||
SECONDARY_ACTION_BUTTON_CLASS
|
||||
)}
|
||||
disabled={!selectedGeneratedImage}
|
||||
|
||||
@ -2970,7 +2970,7 @@ export function RealtimeCanvasDialog({
|
||||
<div className="pointer-events-none absolute top-6 left-6 right-6 z-50 flex flex-wrap items-start gap-3">
|
||||
<button
|
||||
className={cn(
|
||||
"pointer-events-auto flex h-16 items-center gap-3 rounded-full px-5 text-foreground transition hover:bg-white",
|
||||
"pointer-events-auto flex h-16 items-center gap-2.5 rounded-full px-4 text-foreground transition hover:bg-white",
|
||||
floatingSurfaceClass
|
||||
)}
|
||||
onClick={handleGoHome}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user