style: simplify realtime enhance ui to monochrome
This commit is contained in:
parent
ed23cd3f4a
commit
aede89654f
@ -104,38 +104,38 @@ const FALLBACK_CONFIG: EnhanceProClientConfig = {
|
||||
};
|
||||
|
||||
const PANEL_SHELL_CLASS =
|
||||
"pointer-events-auto rounded-[30px] border border-[#eadfcb] bg-[linear-gradient(180deg,#fffdf9_0%,#fff7ed_100%)] shadow-[0_0_0_1px_rgba(234,223,203,0.88),0_24px_48px_rgba(15,23,42,0.06)]";
|
||||
"pointer-events-auto rounded-[28px] border border-[#e5e5e5] bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_20px_40px_rgba(0,0,0,0.06)]";
|
||||
const SOLID_PANEL_FIELD_CLASS =
|
||||
"border-[#eadfcb] bg-[#fffdfa] text-[#1c1c1e] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_1px_2px_rgba(28,28,30,0.04)]";
|
||||
"border-[#e5e5e5] bg-white text-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_1px_2px_rgba(0,0,0,0.04)]";
|
||||
const SOLID_PANEL_CARD_CLASS =
|
||||
"rounded-[22px] border border-white/90 bg-white/78 shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_10px_22px_rgba(15,23,42,0.05)]";
|
||||
"rounded-[22px] border border-[#ececec] bg-white shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_10px_22px_rgba(0,0,0,0.04)]";
|
||||
const PANEL_SECTION_TITLE_CLASS =
|
||||
"font-semibold text-[15px] tracking-[-0.04em] text-[#1c1c1e]";
|
||||
"font-semibold text-[15px] tracking-[-0.04em] text-[#111111]";
|
||||
const PANEL_SECTION_NOTE_CLASS =
|
||||
"text-[12px] leading-5 text-[#555a6a]";
|
||||
"text-[12px] leading-5 text-[#666666]";
|
||||
const SOLID_PANEL_SELECT_CONTENT_CLASS =
|
||||
"border-[#eadfcb] bg-[#fffdfa] shadow-[0_0_0_1px_rgba(234,223,203,0.88),0_18px_38px_rgba(15,23,42,0.08)]";
|
||||
"border-[#e5e5e5] bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_18px_38px_rgba(0,0,0,0.08)]";
|
||||
const PRIMARY_ACTION_BUTTON_CLASS =
|
||||
"border border-[#5b76fe] bg-[linear-gradient(180deg,#6d87ff_0%,#516bf5_100%)] text-white shadow-[0_16px_30px_rgba(91,118,254,0.26)] transition hover:border-[#2a41b6] hover:bg-[linear-gradient(180deg,#5d78ff_0%,#2a41b6_100%)] disabled:border-[#e0e2e8] disabled:bg-[#eef1f6] disabled:text-[#a5a8b5] disabled:shadow-none";
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_16px_30px_rgba(0,0,0,0.18)] transition hover:bg-black hover:border-black disabled:border-[#e5e5e5] disabled:bg-[#f1f1f1] disabled:text-[#9a9a9a] disabled:shadow-none";
|
||||
const SECONDARY_ACTION_BUTTON_CLASS =
|
||||
"border border-[#d9e2fb] bg-[#f7f9ff] text-[#3150d3] shadow-[0_0_0_1px_rgba(217,226,251,0.75),0_10px_22px_rgba(91,118,254,0.08)] transition hover:border-[#5b76fe] hover:bg-[#edf2ff] hover:text-[#2a41b6] disabled:border-[#e0e2e8] disabled:bg-[#f7f8fb] disabled:text-[#a5a8b5] disabled:shadow-none";
|
||||
"border border-[#d9d9d9] bg-white text-[#111111] shadow-[0_0_0_1px_rgba(0,0,0,0.02),0_10px_22px_rgba(0,0,0,0.03)] transition hover:border-[#111111] hover:bg-[#fafafa] hover:text-black disabled:border-[#e5e5e5] disabled:bg-[#f7f7f7] disabled:text-[#a5a5a5] disabled:shadow-none";
|
||||
const COMPACT_FIELD_CLASS = `${SOLID_PANEL_FIELD_CLASS} h-11 rounded-[16px] text-sm`;
|
||||
const COMPACT_LABEL_CLASS =
|
||||
"font-medium text-[#555a6a] text-[11px] leading-4 tracking-[0.01em]";
|
||||
"font-medium text-[#666666] text-[11px] leading-4 tracking-[0.01em]";
|
||||
const COMPACT_TOGGLE_CARD_CLASS =
|
||||
"flex items-center justify-between gap-2.5 px-3.5 py-3";
|
||||
const SLIDER_TRACK_CLASS = "h-2.5 bg-[#e9edf5] shadow-inner";
|
||||
const SLIDER_RANGE_CLASS = "bg-[#5b76fe]";
|
||||
const SLIDER_TRACK_CLASS = "h-2.5 bg-[#ededed] shadow-inner";
|
||||
const SLIDER_RANGE_CLASS = "bg-[#111111]";
|
||||
const SLIDER_THUMB_CLASS =
|
||||
"h-4 w-4 border border-[#d6d1c4] bg-white shadow-[0_0_0_4px_rgba(91,118,254,0.16)]";
|
||||
"h-4 w-4 border border-[#d4d4d4] bg-white shadow-[0_0_0_4px_rgba(0,0,0,0.08)]";
|
||||
const SIDEBAR_SCROLL_CLASS =
|
||||
"pr-1.5 [scrollbar-width:thin] [scrollbar-color:#d7cfbf_transparent] [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-[#d7cfbf] hover:[&::-webkit-scrollbar-thumb]:bg-[#c8bda9]";
|
||||
"pr-1.5 [scrollbar-width:thin] [scrollbar-color:#c8c8c8_transparent] [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-[#c8c8c8] hover:[&::-webkit-scrollbar-thumb]:bg-[#a8a8a8]";
|
||||
const SIDEBAR_SECTION_CARD_CLASS =
|
||||
"rounded-[30px] border p-3.5 shadow-[0_18px_36px_rgba(15,23,42,0.06)]";
|
||||
"rounded-[28px] border border-[#e5e5e5] bg-white p-3.5 shadow-[0_18px_36px_rgba(0,0,0,0.05)]";
|
||||
const SECTION_EYEBROW_CLASS =
|
||||
"inline-flex items-center gap-1.5 rounded-full border border-white/90 bg-white/72 px-2.5 py-1 font-semibold text-[10px] tracking-[0.14em] text-[#6b7280] uppercase";
|
||||
"inline-flex items-center gap-1.5 rounded-full border border-[#ebebeb] bg-[#fafafa] px-2.5 py-1 font-semibold text-[10px] tracking-[0.14em] text-[#666666] uppercase";
|
||||
const INNER_PANEL_CLASS =
|
||||
"rounded-[22px] border border-white/90 bg-white/76 p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]";
|
||||
"rounded-[22px] border border-[#efefef] bg-[#fbfbfb] p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]";
|
||||
|
||||
function clampNumber(value: number, min: number, max: number) {
|
||||
return Math.min(max, Math.max(min, value));
|
||||
@ -286,15 +286,15 @@ function ParameterSliderRow({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"space-y-3 rounded-[20px] border border-white/80 bg-white/74 px-3.5 py-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.94)]",
|
||||
"space-y-3 rounded-[20px] border border-[#efefef] bg-white px-3.5 py-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.94)]",
|
||||
disabled && "opacity-50"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="font-medium text-[12px] text-slate-700 tracking-[-0.01em]">
|
||||
<div className="font-medium text-[12px] text-[#222222] tracking-[-0.01em]">
|
||||
{label}
|
||||
</div>
|
||||
<div className="inline-flex min-w-[54px] justify-center rounded-full border border-[#e7e1d4] bg-[#fffdfa] px-2.5 py-1 font-medium text-[11px] text-slate-600 shadow-[0_4px_12px_rgba(15,23,42,0.04)]">
|
||||
<div className="inline-flex min-w-[54px] justify-center rounded-full border border-[#e7e7e7] bg-white px-2.5 py-1 font-medium text-[11px] text-[#666666] shadow-[0_4px_12px_rgba(0,0,0,0.04)]">
|
||||
{displayValue}
|
||||
</div>
|
||||
</div>
|
||||
@ -657,10 +657,10 @@ export function EnhanceProWorkspace({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative flex h-full w-full bg-[linear-gradient(180deg,#fdfbf6_0%,#f7f4ec_100%)] text-[#1c1c1e]">
|
||||
<div className="relative flex h-full w-full bg-[#ffffff] text-[#111111]">
|
||||
<div className="relative flex min-w-0 flex-1 items-center justify-center overflow-hidden px-6 pb-28 pt-24">
|
||||
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_18%_14%,rgba(255,240,190,0.68),transparent_24%),radial-gradient(circle_at_86%_18%,rgba(195,250,245,0.72),transparent_18%),radial-gradient(circle_at_70%_84%,rgba(238,242,255,0.95),transparent_25%),linear-gradient(180deg,#fffdf8_0%,#faf6ef_100%)]" />
|
||||
<div className="pattern-grid-lg pointer-events-none absolute inset-0 opacity-[0.035] [mask-image:radial-gradient(circle_at_center,black_38%,transparent_82%)]" />
|
||||
<div className="pointer-events-none absolute inset-0 bg-[#ffffff]" />
|
||||
<div className="pattern-grid-lg pointer-events-none absolute inset-0 opacity-[0.025] [mask-image:radial-gradient(circle_at_center,black_38%,transparent_82%)]" />
|
||||
{activePreviewUrl ? (
|
||||
<div
|
||||
className={cn(
|
||||
@ -673,10 +673,8 @@ export function EnhanceProWorkspace({
|
||||
onPointerMove={handlePreviewPointerMove}
|
||||
onPointerUp={finishPreviewDrag}
|
||||
>
|
||||
<div className="pointer-events-none absolute top-[12%] left-[10%] h-40 w-40 rounded-full bg-[#fff0be] blur-3xl" />
|
||||
<div className="pointer-events-none absolute right-[10%] bottom-[12%] h-44 w-44 rounded-full bg-[#c3faf5] blur-3xl" />
|
||||
<div className="relative flex max-h-full max-w-full items-center justify-center rounded-[38px] border border-[#eadfcb] bg-[linear-gradient(180deg,rgba(255,255,255,0.95),rgba(255,248,238,0.95))] p-4 shadow-[0_0_0_1px_rgba(234,223,203,0.72),0_28px_56px_rgba(15,23,42,0.10)] backdrop-blur-xl">
|
||||
<div className="overflow-hidden rounded-[30px] border border-white/90 bg-white shadow-[0_20px_36px_rgba(15,23,42,0.10)]">
|
||||
<div className="relative flex max-h-full max-w-full items-center justify-center rounded-[38px] border border-[#e8e8e8] bg-[#fafafa] p-4 shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_24px_56px_rgba(0,0,0,0.08)] backdrop-blur-xl">
|
||||
<div className="overflow-hidden rounded-[30px] border border-[#efefef] bg-white shadow-[0_18px_30px_rgba(0,0,0,0.08)]">
|
||||
<img
|
||||
alt={activePreviewLabel}
|
||||
className="pointer-events-none max-h-[calc(100vh-17rem)] max-w-[min(1000px,calc(100vw-35rem))] object-contain transition-transform duration-75"
|
||||
@ -687,54 +685,52 @@ export function EnhanceProWorkspace({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute top-6 left-6 flex items-center gap-2 rounded-full border border-[#eadfcb] bg-white/94 px-3.5 py-1.5 text-[#555a6a] text-xs shadow-[0_0_0_1px_rgba(234,223,203,0.75),0_10px_24px_rgba(28,28,30,0.04)] backdrop-blur-sm">
|
||||
<div className="pointer-events-none absolute top-6 left-6 flex items-center gap-2 rounded-full border border-[#e5e5e5] bg-white/96 px-3.5 py-1.5 text-[#666666] text-xs shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_10px_24px_rgba(0,0,0,0.04)] backdrop-blur-sm">
|
||||
<ImageIcon className="h-3.5 w-3.5" />
|
||||
<span>{activePreviewLabel}</span>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute top-6 right-8 hidden items-center gap-2 rounded-full border border-[#eadfcb] bg-white/90 px-3 py-1.5 text-[#555a6a] text-xs shadow-[0_0_0_1px_rgba(234,223,203,0.72),0_10px_24px_rgba(28,28,30,0.04)] lg:inline-flex">
|
||||
<div className="pointer-events-none absolute top-6 right-8 hidden items-center gap-2 rounded-full border border-[#e5e5e5] bg-white/96 px-3 py-1.5 text-[#666666] text-xs shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_10px_24px_rgba(0,0,0,0.04)] lg:inline-flex">
|
||||
双击回正
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="relative w-full max-w-[42rem] px-6">
|
||||
<div className="pointer-events-none absolute -top-6 left-8 h-24 w-24 rounded-[32px] bg-[#fff0be] blur-3xl" />
|
||||
<div className="pointer-events-none absolute right-12 -bottom-4 h-28 w-28 rounded-[32px] bg-[#c3faf5] blur-3xl" />
|
||||
<div className="relative rounded-[38px] border border-[#eadfcb] bg-[linear-gradient(180deg,rgba(255,255,255,0.97),rgba(255,247,236,0.97))] px-8 py-8 shadow-[0_0_0_1px_rgba(234,223,203,0.8),0_30px_60px_rgba(15,23,42,0.08)] backdrop-blur-sm">
|
||||
<div className="relative rounded-[38px] border border-[#e6e6e6] bg-white px-8 py-8 shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_30px_60px_rgba(0,0,0,0.06)] backdrop-blur-sm">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex h-16 w-16 shrink-0 items-center justify-center rounded-[24px] border border-white/90 bg-[#fff0be] text-[#7a5b00] shadow-[0_14px_28px_rgba(255,221,117,0.25)]">
|
||||
<div className="flex h-16 w-16 shrink-0 items-center justify-center rounded-[24px] border border-[#ececec] bg-[#fafafa] text-[#111111] shadow-[0_14px_28px_rgba(0,0,0,0.06)]">
|
||||
<Sparkles className="h-8 w-8" />
|
||||
</div>
|
||||
<div className="min-w-0 text-left">
|
||||
<div className={SECTION_EYEBROW_CLASS}>Enhance Pro Studio</div>
|
||||
<div className="mt-3 font-semibold text-[34px] tracking-[-0.05em] text-[#1c1c1e] leading-[1.02]">
|
||||
<div className="mt-3 font-semibold text-[34px] tracking-[-0.05em] text-[#111111] leading-[1.02]">
|
||||
还没有可增强的图片
|
||||
</div>
|
||||
<div className="mt-3 max-w-[30rem] text-[#555a6a] text-[15px] leading-7">
|
||||
<div className="mt-3 max-w-[30rem] text-[#666666] text-[15px] leading-7">
|
||||
先在主画布里选中一张图片,或者先在实时画布模式里生成结果,
|
||||
再切回这里进行精修、增强和细节重建。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-7 grid gap-3 md:grid-cols-2">
|
||||
<div className="rounded-[24px] border border-white/90 bg-white/78 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]">
|
||||
<div className="text-[11px] font-semibold tracking-[0.16em] text-[#8c6c1f] uppercase">
|
||||
<div className="rounded-[24px] border border-[#efefef] bg-[#fafafa] p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]">
|
||||
<div className="text-[11px] font-semibold tracking-[0.16em] text-[#666666] uppercase">
|
||||
Step 01
|
||||
</div>
|
||||
<div className="mt-2 font-semibold text-[18px] tracking-[-0.03em] text-[#1c1c1e]">
|
||||
<div className="mt-2 font-semibold text-[18px] tracking-[-0.03em] text-[#111111]">
|
||||
选中一张图
|
||||
</div>
|
||||
<div className="mt-1 text-[13px] leading-6 text-[#555a6a]">
|
||||
<div className="mt-1 text-[13px] leading-6 text-[#666666]">
|
||||
从主画布中选择要增强的图片,系统会自动把它带入当前工作台。
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-[24px] border border-white/90 bg-white/78 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]">
|
||||
<div className="text-[11px] font-semibold tracking-[0.16em] text-[#0c7270] uppercase">
|
||||
<div className="rounded-[24px] border border-[#efefef] bg-[#fafafa] p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.92)]">
|
||||
<div className="text-[11px] font-semibold tracking-[0.16em] text-[#666666] uppercase">
|
||||
Step 02
|
||||
</div>
|
||||
<div className="mt-2 font-semibold text-[18px] tracking-[-0.03em] text-[#1c1c1e]">
|
||||
<div className="mt-2 font-semibold text-[18px] tracking-[-0.03em] text-[#111111]">
|
||||
调参后开始增强
|
||||
</div>
|
||||
<div className="mt-1 text-[13px] leading-6 text-[#555a6a]">
|
||||
<div className="mt-1 text-[13px] leading-6 text-[#666666]">
|
||||
使用右侧工具卡片快速选择模式、强度和增强范围,生成后可直接发回画布。
|
||||
</div>
|
||||
</div>
|
||||
@ -745,7 +741,7 @@ export function EnhanceProWorkspace({
|
||||
|
||||
{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-[#e0e2e8] bg-white/94 px-3 py-3 shadow-[0_0_0_1px_rgb(224,226,232),0_20px_40px_rgba(28,28,30,0.05)] backdrop-blur-sm">
|
||||
<div className="flex max-w-[min(720px,calc(100vw-5rem))] items-center gap-2 rounded-[24px] border border-[#e5e5e5] bg-white/96 px-3 py-3 shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_20px_40px_rgba(0,0,0,0.05)] backdrop-blur-sm">
|
||||
{sidePreviewItems.map((item, index) => {
|
||||
const isActive = item.isSource
|
||||
? selectedResultIndex < 0
|
||||
@ -755,8 +751,8 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
"group flex h-16 w-16 shrink-0 overflow-hidden rounded-2xl border transition",
|
||||
isActive
|
||||
? "border-[#5b76fe] shadow-[0_0_0_1px_rgba(91,118,254,0.18),0_10px_20px_rgba(91,118,254,0.12)]"
|
||||
: "border-[#e0e2e8] hover:shadow-sm"
|
||||
? "border-[#111111] shadow-[0_0_0_1px_rgba(0,0,0,0.08),0_10px_20px_rgba(0,0,0,0.08)]"
|
||||
: "border-[#e5e5e5] hover:shadow-sm"
|
||||
)}
|
||||
key={item.key}
|
||||
onClick={() =>
|
||||
@ -778,15 +774,15 @@ export function EnhanceProWorkspace({
|
||||
) : null}
|
||||
|
||||
<div className="pointer-events-none absolute bottom-6 left-1/2 z-30 flex w-fit max-w-[calc(100%-2rem)] -translate-x-1/2 flex-col items-center gap-2">
|
||||
<div className="pointer-events-auto rounded-full border border-[#eadfcb] bg-white/92 px-4 py-1.5 text-[#555a6a] text-[11px] shadow-[0_0_0_1px_rgba(234,223,203,0.75),0_12px_24px_rgba(28,28,30,0.04)] backdrop-blur-xl">
|
||||
<div className="pointer-events-auto rounded-full border border-[#e5e5e5] bg-white/96 px-4 py-1.5 text-[#666666] text-[11px] shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_12px_24px_rgba(0,0,0,0.04)] backdrop-blur-xl">
|
||||
<span className="inline-flex items-center gap-1.5">
|
||||
{selectedGeneratedImage ? (
|
||||
<CheckCircle2 className="h-3.5 w-3.5 text-emerald-600" />
|
||||
<CheckCircle2 className="h-3.5 w-3.5 text-[#111111]" />
|
||||
) : null}
|
||||
{actionHint}
|
||||
</span>
|
||||
</div>
|
||||
<div className="pointer-events-auto inline-flex items-center justify-center gap-2 rounded-[32px] border border-[#eadfcb] bg-[linear-gradient(180deg,rgba(255,255,255,0.96),rgba(255,247,236,0.96))] p-2 shadow-[0_0_0_1px_rgba(234,223,203,0.78),0_18px_38px_rgba(28,28,30,0.08)] backdrop-blur-xl">
|
||||
<div className="pointer-events-auto inline-flex items-center justify-center gap-2 rounded-[32px] border border-[#e5e5e5] bg-white p-2 shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_18px_38px_rgba(0,0,0,0.08)] backdrop-blur-xl">
|
||||
<Button
|
||||
className={cn(
|
||||
"h-11 min-w-[214px] rounded-[24px] px-5 text-sm font-medium tracking-[-0.01em]",
|
||||
@ -826,7 +822,7 @@ export function EnhanceProWorkspace({
|
||||
<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-4 py-3 text-[#666666] text-sm"
|
||||
)}
|
||||
>
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
@ -835,14 +831,14 @@ export function EnhanceProWorkspace({
|
||||
) : null}
|
||||
|
||||
{!config.enabled && !isLoading ? (
|
||||
<div className="rounded-[24px] border border-amber-200 bg-[#fff7df] px-4 py-3 text-amber-800 text-sm leading-6 shadow-[0_10px_24px_rgba(255,209,102,0.12)]">
|
||||
<div className="rounded-[24px] border border-[#e5e5e5] bg-white px-4 py-3 text-[#333333] text-sm leading-6 shadow-[0_10px_24px_rgba(0,0,0,0.04)]">
|
||||
当前未启用图像增强 Pro。请先在系统设置的“本地AI设置”里完成 Krea
|
||||
配置。
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{lastErrorMessage ? (
|
||||
<div className="rounded-[24px] border border-rose-200 bg-[#fff3f1] px-4 py-3 text-rose-700 text-sm leading-6 shadow-[0_10px_24px_rgba(244,114,182,0.08)]">
|
||||
<div className="rounded-[24px] border border-[#e5e5e5] bg-[#fafafa] px-4 py-3 text-[#333333] text-sm leading-6 shadow-[0_10px_24px_rgba(0,0,0,0.04)]">
|
||||
{lastErrorMessage}
|
||||
</div>
|
||||
) : null}
|
||||
@ -851,18 +847,18 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
PANEL_SHELL_CLASS,
|
||||
SIDEBAR_SECTION_CARD_CLASS,
|
||||
"border-[#eadfcb] bg-[linear-gradient(180deg,#fffdf7_0%,#fff6ea_100%)] px-3.5 py-3.5"
|
||||
"px-3.5 py-3.5"
|
||||
)}
|
||||
onOpenChange={setSettingsOpen}
|
||||
open={settingsOpen}
|
||||
>
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
className="flex w-full items-center justify-between gap-3 rounded-[24px] border border-white/90 bg-white/70 px-3.5 py-3 text-left transition hover:bg-white/82"
|
||||
className="flex w-full items-center justify-between gap-3 rounded-[24px] border border-[#efefef] bg-[#fafafa] px-3.5 py-3 text-left transition hover:bg-white"
|
||||
type="button"
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-white/90 bg-[#fff0be] text-[#7c5a00] shadow-[0_10px_22px_rgba(255,221,117,0.20)]">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-[#ececec] bg-white text-[#111111] shadow-[0_10px_22px_rgba(0,0,0,0.05)]">
|
||||
<Settings2 className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0 space-y-1">
|
||||
@ -871,12 +867,12 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="hidden rounded-full border border-white/90 bg-white/80 px-2.5 py-1 text-[11px] text-[#555a6a] sm:inline-flex">
|
||||
<div className="hidden rounded-full border border-[#ebebeb] bg-white px-2.5 py-1 text-[11px] text-[#666666] sm:inline-flex">
|
||||
{formState.model}
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
"h-4 w-4 text-slate-500 transition-transform",
|
||||
"h-4 w-4 text-[#666666] transition-transform",
|
||||
settingsOpen && "rotate-180"
|
||||
)}
|
||||
/>
|
||||
@ -899,7 +895,7 @@ export function EnhanceProWorkspace({
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{selectedPreset ? (
|
||||
<div className="rounded-[18px] border border-white/90 bg-[#fffdfa] px-3 py-2.5">
|
||||
<div className="rounded-[18px] border border-[#ececec] bg-white px-3 py-2.5">
|
||||
<div className={cn(PANEL_SECTION_NOTE_CLASS, "line-clamp-2")}>
|
||||
{selectedPreset.description ||
|
||||
`${selectedPreset.model} · ${getSubjectDetectionLabel(selectedPreset.subjectDetection)}`}
|
||||
@ -916,7 +912,7 @@ export function EnhanceProWorkspace({
|
||||
增强提示词
|
||||
</Label>
|
||||
<Textarea
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} min-h-[84px] resize-none rounded-[20px] bg-[#fffdfa] text-sm placeholder:text-[#a5a8b5]`}
|
||||
className={`${SOLID_PANEL_FIELD_CLASS} min-h-[84px] resize-none rounded-[20px] bg-white text-sm placeholder:text-[#a5a8b5]`}
|
||||
id="enhance-workspace-prompt"
|
||||
onChange={(event) =>
|
||||
setFormState((prev) => ({
|
||||
@ -1134,10 +1130,10 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
SOLID_PANEL_CARD_CLASS,
|
||||
COMPACT_TOGGLE_CARD_CLASS,
|
||||
"bg-white/78"
|
||||
"bg-white"
|
||||
)}
|
||||
>
|
||||
<span className="text-foreground text-xs">启用放大</span>
|
||||
<span className="text-[#111111] text-xs">启用放大</span>
|
||||
<Switch
|
||||
checked={formState.upscaling_activated}
|
||||
onCheckedChange={(checked) =>
|
||||
@ -1152,10 +1148,10 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
SOLID_PANEL_CARD_CLASS,
|
||||
COMPACT_TOGGLE_CARD_CLASS,
|
||||
"bg-white/78"
|
||||
"bg-white"
|
||||
)}
|
||||
>
|
||||
<span className="text-foreground text-xs">裁剪铺满</span>
|
||||
<span className="text-[#111111] text-xs">裁剪铺满</span>
|
||||
<Switch
|
||||
checked={formState.crop_to_fill}
|
||||
onCheckedChange={(checked) =>
|
||||
@ -1175,18 +1171,18 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
PANEL_SHELL_CLASS,
|
||||
SIDEBAR_SECTION_CARD_CLASS,
|
||||
"border-[#dfe6f5] bg-[linear-gradient(180deg,#fbfdff_0%,#f3f7ff_100%)] px-3.5 py-3.5"
|
||||
"px-3.5 py-3.5"
|
||||
)}
|
||||
onOpenChange={setAdjustmentsOpen}
|
||||
open={adjustmentsOpen}
|
||||
>
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
className="flex w-full items-center justify-between gap-3 rounded-[24px] border border-white/90 bg-white/72 px-3.5 py-3 text-left transition hover:bg-white/84"
|
||||
className="flex w-full items-center justify-between gap-3 rounded-[24px] border border-[#efefef] bg-[#fafafa] px-3.5 py-3 text-left transition hover:bg-white"
|
||||
type="button"
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-white/90 bg-[#eef2ff] text-[#5b76fe] shadow-[0_10px_22px_rgba(91,118,254,0.16)]">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-[#ececec] bg-white text-[#111111] shadow-[0_10px_22px_rgba(0,0,0,0.05)]">
|
||||
<SlidersHorizontal className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0 space-y-1">
|
||||
@ -1196,7 +1192,7 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
"h-4 w-4 text-slate-500 transition-transform",
|
||||
"h-4 w-4 text-[#666666] transition-transform",
|
||||
adjustmentsOpen && "rotate-180"
|
||||
)}
|
||||
/>
|
||||
@ -1272,7 +1268,7 @@ export function EnhanceProWorkspace({
|
||||
className={cn(
|
||||
PANEL_SHELL_CLASS,
|
||||
SIDEBAR_SECTION_CARD_CLASS,
|
||||
"border-[#f1ddd7] bg-[linear-gradient(180deg,#fffaf7_0%,#fff1eb_100%)] px-3.5 py-3.5"
|
||||
"px-3.5 py-3.5"
|
||||
)}
|
||||
onOpenChange={setFaceOpen}
|
||||
open={faceOpen}
|
||||
@ -1280,11 +1276,11 @@ export function EnhanceProWorkspace({
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
className="flex min-w-0 flex-1 items-center justify-between gap-3 rounded-[24px] border border-white/90 bg-white/72 px-3.5 py-3 text-left transition hover:bg-white/84"
|
||||
className="flex min-w-0 flex-1 items-center justify-between gap-3 rounded-[24px] border border-[#efefef] bg-[#fafafa] px-3.5 py-3 text-left transition hover:bg-white"
|
||||
type="button"
|
||||
>
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-white/90 bg-[#ffe8df] text-[#b95a36] shadow-[0_10px_22px_rgba(240,150,120,0.18)]">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-[#ececec] bg-white text-[#111111] shadow-[0_10px_22px_rgba(0,0,0,0.05)]">
|
||||
<ScanFace className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0 space-y-1">
|
||||
@ -1294,7 +1290,7 @@ export function EnhanceProWorkspace({
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
"h-4 w-4 shrink-0 text-slate-500 transition-transform",
|
||||
"h-4 w-4 shrink-0 text-[#666666] transition-transform",
|
||||
faceOpen && "rotate-180"
|
||||
)}
|
||||
/>
|
||||
|
||||
@ -851,22 +851,22 @@ export function RealtimeCanvasDialog({
|
||||
if (status === "live")
|
||||
return {
|
||||
label: "实时中",
|
||||
className: "bg-emerald-500/15 text-emerald-600 dark:text-emerald-400",
|
||||
className: "border border-[#e5e5e5] bg-white text-[#111111]",
|
||||
};
|
||||
if (status === "connecting") {
|
||||
return {
|
||||
label: "连接中",
|
||||
className: "bg-blue-500/15 text-blue-600 dark:text-blue-400",
|
||||
className: "border border-[#e5e5e5] bg-white text-[#111111]",
|
||||
};
|
||||
}
|
||||
if (status === "error")
|
||||
return {
|
||||
label: "异常",
|
||||
className: "bg-rose-500/15 text-rose-600 dark:text-rose-400",
|
||||
className: "border border-[#e5e5e5] bg-[#fafafa] text-[#111111]",
|
||||
};
|
||||
return {
|
||||
label: "待启动",
|
||||
className: "bg-muted text-muted-foreground",
|
||||
className: "border border-[#e5e5e5] bg-white text-[#666666]",
|
||||
};
|
||||
}, [status]);
|
||||
|
||||
@ -2918,17 +2918,17 @@ export function RealtimeCanvasDialog({
|
||||
}, [clearPreviewCanvas, closeBrushSettingPopovers, resetCanvas]);
|
||||
|
||||
const floatingSurfaceClass =
|
||||
"border border-[#eadfcb] bg-[linear-gradient(180deg,rgba(255,255,255,0.96),rgba(255,247,236,0.94))] shadow-[0_0_0_1px_rgba(234,223,203,0.82),0_20px_42px_rgba(15,23,42,0.08)] backdrop-blur-xl";
|
||||
"border border-[#e5e5e5] bg-white/96 shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_20px_42px_rgba(0,0,0,0.08)] backdrop-blur-xl";
|
||||
const controlSurfaceClass =
|
||||
"border border-[#eadfcb] bg-[#fffdfa] text-[#1c1c1e] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_1px_2px_rgba(28,28,30,0.04)]";
|
||||
"border border-[#e5e5e5] bg-white text-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_1px_2px_rgba(0,0,0,0.04)]";
|
||||
const softActionButtonClass =
|
||||
"border border-[#dbe2ff] bg-[linear-gradient(180deg,#f4f7ff_0%,#e9efff_100%)] text-[#5b76fe] shadow-[0_12px_24px_rgba(91,118,254,0.10)] transition hover:bg-[#e7ecff] hover:text-[#2a41b6]";
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_12px_24px_rgba(0,0,0,0.12)] transition hover:bg-black hover:text-white";
|
||||
const primaryActionButtonClass =
|
||||
"border border-[#5b76fe] bg-[linear-gradient(180deg,#6d87ff_0%,#516bf5_100%)] text-white shadow-[0_16px_30px_rgba(91,118,254,0.22)] transition hover:border-[#2a41b6] hover:bg-[linear-gradient(180deg,#5d78ff_0%,#2a41b6_100%)]";
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_16px_30px_rgba(0,0,0,0.18)] transition hover:bg-black hover:border-black";
|
||||
const compactToolButtonClass =
|
||||
"h-9 w-9 rounded-[16px] border border-transparent text-[#555a6a] transition hover:border-[#dbe2ff] hover:bg-[#eef2ff] hover:text-[#5b76fe]";
|
||||
"h-9 w-9 rounded-[16px] border border-transparent text-[#666666] transition hover:border-[#e5e5e5] hover:bg-[#fafafa] hover:text-[#111111]";
|
||||
const compactToolButtonActiveClass =
|
||||
"border-[#dbe2ff] bg-[#eef2ff] text-[#5b76fe] shadow-[0_10px_20px_rgba(91,118,254,0.14)] hover:bg-[#e7ecff] hover:text-[#5b76fe]";
|
||||
"border-[#111111] bg-[#111111] text-white shadow-[0_10px_20px_rgba(0,0,0,0.12)] hover:bg-black hover:text-white";
|
||||
const currentModeLabel =
|
||||
brushMode === "select"
|
||||
? "鼠标"
|
||||
@ -2975,12 +2975,12 @@ export function RealtimeCanvasDialog({
|
||||
)}
|
||||
>
|
||||
<button
|
||||
className="inline-flex h-12 shrink-0 items-center gap-3 rounded-[22px] border border-white/90 bg-white/80 px-4 text-left text-foreground shadow-[inset_0_1px_0_rgba(255,255,255,0.95)] transition hover:bg-white"
|
||||
className="inline-flex h-12 shrink-0 items-center gap-3 rounded-[22px] border border-white/90 bg-white/80 px-4 text-left text-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95)] transition hover:bg-white"
|
||||
onClick={handleGoHome}
|
||||
title="返回首页"
|
||||
type="button"
|
||||
>
|
||||
<span className="flex h-8 w-8 items-center justify-center rounded-full bg-[#eef2ff] shadow-[0_8px_18px_rgba(91,118,254,0.14)]">
|
||||
<span className="flex h-8 w-8 items-center justify-center rounded-full border border-[#ececec] bg-white shadow-[0_8px_18px_rgba(0,0,0,0.06)]">
|
||||
{siteLogo ? (
|
||||
<img
|
||||
alt={siteName}
|
||||
@ -2992,7 +2992,7 @@ export function RealtimeCanvasDialog({
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Sparkles className="h-3.5 w-3.5 text-[#1d4ed8]" />
|
||||
<Sparkles className="h-3.5 w-3.5 text-[#111111]" />
|
||||
)}
|
||||
</span>
|
||||
<span className="font-semibold text-[14px] tracking-[-0.02em]">
|
||||
@ -3000,13 +3000,13 @@ export function RealtimeCanvasDialog({
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div className="inline-flex h-12 min-w-0 items-center gap-1 rounded-[22px] border border-white/90 bg-white/72 p-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.9)]">
|
||||
<div className="inline-flex h-12 min-w-0 items-center gap-1 rounded-[22px] border border-[#ebebeb] bg-[#fafafa] p-1 shadow-[inset_0_1px_0_rgba(255,255,255,0.9)]">
|
||||
<button
|
||||
className={cn(
|
||||
"inline-flex h-full items-center gap-2 rounded-[18px] px-4 text-[14px] font-medium tracking-[-0.02em] transition",
|
||||
workspaceMode === "realtime"
|
||||
? softActionButtonClass
|
||||
: "border border-transparent bg-transparent text-slate-600 hover:bg-white hover:text-foreground"
|
||||
: "border border-transparent bg-transparent text-[#666666] hover:bg-white hover:text-[#111111]"
|
||||
)}
|
||||
onClick={() => setWorkspaceMode("realtime")}
|
||||
type="button"
|
||||
@ -3019,7 +3019,7 @@ export function RealtimeCanvasDialog({
|
||||
"inline-flex h-full items-center gap-2 rounded-[18px] px-4 text-[14px] font-medium tracking-[-0.02em] transition",
|
||||
workspaceMode === "enhance-pro"
|
||||
? softActionButtonClass
|
||||
: "border border-transparent bg-transparent text-slate-600 hover:bg-white hover:text-foreground"
|
||||
: "border border-transparent bg-transparent text-[#666666] hover:bg-white hover:text-[#111111]"
|
||||
)}
|
||||
onClick={() => setWorkspaceMode("enhance-pro")}
|
||||
type="button"
|
||||
@ -3039,10 +3039,10 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-semibold text-foreground text-sm">
|
||||
<div className="font-semibold text-[#111111] text-sm">
|
||||
保存项目
|
||||
</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
请输入项目名称后保存当前画布
|
||||
</div>
|
||||
</div>
|
||||
@ -3097,10 +3097,10 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<div className="font-semibold text-foreground text-sm">
|
||||
<div className="font-semibold text-[#111111] text-sm">
|
||||
项目列表
|
||||
</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
本地保存,便于下次继续编辑
|
||||
</div>
|
||||
</div>
|
||||
@ -3116,17 +3116,17 @@ export function RealtimeCanvasDialog({
|
||||
</div>
|
||||
<div className="mt-4 max-h-[55vh] min-h-0 space-y-2 overflow-y-auto overscroll-contain pr-1">
|
||||
{savedProjects.length === 0 ? (
|
||||
<div className="rounded-2xl border border-[#e7e1d4] border-dashed px-4 py-8 text-center text-muted-foreground text-sm">
|
||||
<div className="rounded-2xl border border-[#e5e5e5] border-dashed px-4 py-8 text-center text-[#666666] text-sm">
|
||||
暂无保存的项目
|
||||
</div>
|
||||
) : (
|
||||
savedProjects.map((project) => (
|
||||
<div
|
||||
className="rounded-2xl border border-[#e7e1d4] bg-[#fffdfa] p-3 shadow-sm"
|
||||
className="rounded-2xl border border-[#e5e5e5] bg-white p-3 shadow-sm"
|
||||
key={project.id}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="h-14 w-14 shrink-0 overflow-hidden rounded-xl border border-[#e7e1d4] bg-muted">
|
||||
<div className="h-14 w-14 shrink-0 overflow-hidden rounded-xl border border-[#e5e5e5] bg-[#fafafa]">
|
||||
{project.coverImageUrl || project.previewUrl ? (
|
||||
<img
|
||||
alt={project.name}
|
||||
@ -3146,13 +3146,13 @@ export function RealtimeCanvasDialog({
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex h-full items-center justify-center text-[11px] text-muted-foreground">
|
||||
<div className="flex h-full items-center justify-center text-[11px] text-[#666666]">
|
||||
无预览
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate font-medium text-foreground text-sm leading-5">
|
||||
<div className="truncate font-medium text-[#111111] text-sm leading-5">
|
||||
{project.name}
|
||||
</div>
|
||||
<div className="mt-2 flex items-center justify-end gap-2">
|
||||
@ -3194,11 +3194,11 @@ export function RealtimeCanvasDialog({
|
||||
) : (
|
||||
<>
|
||||
{/* Main Canvas Area - Split View */}
|
||||
<div className="relative flex h-full w-full bg-muted/30">
|
||||
<div className="relative flex h-full w-full bg-[#fafafa]">
|
||||
{/* Left: Input Canvas */}
|
||||
<div className="relative flex flex-1 flex-col items-center justify-center overflow-hidden border-[#e7e1d4] border-r">
|
||||
<div className="relative flex flex-1 flex-col items-center justify-center overflow-hidden border-[#e5e5e5] border-r">
|
||||
<div
|
||||
className="relative flex h-full w-full items-center justify-center bg-background"
|
||||
className="relative flex h-full w-full items-center justify-center bg-white"
|
||||
onDragEnter={handleDragEnter}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDragOver={handleDragOver}
|
||||
@ -3207,7 +3207,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<div className="pattern-grid-lg pointer-events-none absolute inset-0 opacity-[0.03]" />
|
||||
{isDragImportActive ? (
|
||||
<div className="absolute inset-6 z-20 flex items-center justify-center rounded-[28px] border-2 border-sky-400 border-dashed bg-sky-50/90 font-medium text-sky-700 text-sm shadow-inner">
|
||||
<div className="absolute inset-6 z-20 flex items-center justify-center rounded-[28px] border-2 border-[#111111] border-dashed bg-white/92 font-medium text-[#111111] text-sm shadow-inner">
|
||||
松开鼠标,上传图片到图层
|
||||
</div>
|
||||
) : null}
|
||||
@ -3242,7 +3242,7 @@ export function RealtimeCanvasDialog({
|
||||
/>
|
||||
{selectedImageLayer && brushMode === "select" ? (
|
||||
<div
|
||||
className="pointer-events-none absolute border border-sky-500 border-dashed shadow-[0_0_0_1px_rgba(14,165,233,0.25)]"
|
||||
className="pointer-events-none absolute border border-[#111111] border-dashed shadow-[0_0_0_1px_rgba(0,0,0,0.18)]"
|
||||
style={{
|
||||
left: selectedImageLayer.x,
|
||||
top: selectedImageLayer.y,
|
||||
@ -3281,7 +3281,7 @@ export function RealtimeCanvasDialog({
|
||||
] as const
|
||||
).map((handle) => (
|
||||
<div
|
||||
className="-translate-x-1/2 -translate-y-1/2 pointer-events-none absolute z-20 h-3.5 w-3.5 rounded-full border border-[#e7e1d4] bg-background shadow-[0_2px_8px_rgba(15,23,42,0.18)]"
|
||||
className="-translate-x-1/2 -translate-y-1/2 pointer-events-none absolute z-20 h-3.5 w-3.5 rounded-full border border-[#e5e5e5] bg-white shadow-[0_2px_8px_rgba(0,0,0,0.12)]"
|
||||
key={handle.key}
|
||||
style={{
|
||||
left: handle.left,
|
||||
@ -3292,7 +3292,7 @@ export function RealtimeCanvasDialog({
|
||||
: null}
|
||||
{/* Custom Brush Cursor */}
|
||||
<div
|
||||
className="pointer-events-none absolute top-0 left-0 z-10 rounded-full border border-zinc-500/50 bg-zinc-500/10 backdrop-invert transition-opacity duration-75"
|
||||
className="pointer-events-none absolute top-0 left-0 z-10 rounded-full border border-black/30 bg-black/5 backdrop-invert transition-opacity duration-75"
|
||||
ref={cursorRef}
|
||||
style={{
|
||||
width: brushSize,
|
||||
@ -3309,23 +3309,23 @@ export function RealtimeCanvasDialog({
|
||||
floatingSurfaceClass
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center justify-center border-[#e7e1d4] border-b pb-3">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-muted text-foreground">
|
||||
<div className="flex items-center justify-center border-[#e5e5e5] border-b pb-3">
|
||||
<div className="flex h-8 w-8 items-center justify-center rounded-full border border-[#ececec] bg-white text-[#111111]">
|
||||
<Layers3 className="h-4 w-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 flex flex-1 flex-col items-center space-y-2 overflow-y-auto py-1">
|
||||
{imageLayers.length === 0 ? (
|
||||
<div className="rounded-2xl border border-[#e7e1d4] border-dashed px-1 py-4 text-center text-[10px] text-muted-foreground leading-4">
|
||||
<div className="rounded-2xl border border-[#e5e5e5] border-dashed px-1 py-4 text-center text-[10px] text-[#666666] leading-4">
|
||||
暂无图层
|
||||
</div>
|
||||
) : (
|
||||
[...imageLayers].reverse().map((layer) => (
|
||||
<button
|
||||
className={cn(
|
||||
"flex h-12 w-12 shrink-0 items-center justify-center rounded-[18px] p-1.5 transition hover:bg-muted",
|
||||
"flex h-12 w-12 shrink-0 items-center justify-center rounded-[18px] p-1.5 transition hover:bg-[#f5f5f5]",
|
||||
selectedLayerId === layer.id
|
||||
? "bg-muted shadow-[inset_0_0_0_1px_rgba(0,0,0,0.08)]"
|
||||
? "bg-[#f5f5f5] shadow-[inset_0_0_0_1px_rgba(0,0,0,0.08)]"
|
||||
: ""
|
||||
)}
|
||||
draggable
|
||||
@ -3368,7 +3368,7 @@ export function RealtimeCanvasDialog({
|
||||
<div className="mt-2 flex flex-col gap-2">
|
||||
<Button
|
||||
className={cn(
|
||||
"h-10 rounded-xl px-0 hover:bg-[#f7f3eb]",
|
||||
"h-10 rounded-xl px-0 hover:bg-[#f5f5f5]",
|
||||
controlSurfaceClass
|
||||
)}
|
||||
disabled={isLayerSplitImporting}
|
||||
@ -3385,7 +3385,7 @@ export function RealtimeCanvasDialog({
|
||||
</Button>
|
||||
<Button
|
||||
className={cn(
|
||||
"h-10 rounded-xl px-0 hover:bg-[#f7f3eb]",
|
||||
"h-10 rounded-xl px-0 hover:bg-[#f5f5f5]",
|
||||
controlSurfaceClass
|
||||
)}
|
||||
disabled={isLayerSplitImporting}
|
||||
@ -3401,7 +3401,7 @@ export function RealtimeCanvasDialog({
|
||||
</div>
|
||||
|
||||
{/* Right: Output Preview */}
|
||||
<div className="relative flex flex-1 flex-col items-center justify-center overflow-hidden bg-muted/10">
|
||||
<div className="relative flex flex-1 flex-col items-center justify-center overflow-hidden bg-[#fcfcfc]">
|
||||
<div className="relative flex h-full w-full items-center justify-center">
|
||||
{previewUrl ? (
|
||||
<img
|
||||
@ -3410,7 +3410,7 @@ export function RealtimeCanvasDialog({
|
||||
src={previewUrl}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex flex-col items-center justify-center gap-3 text-muted-foreground">
|
||||
<div className="flex flex-col items-center justify-center gap-3 text-[#666666]">
|
||||
{status === "connecting" ? (
|
||||
<>
|
||||
<Loader2 className="h-8 w-8 animate-spin opacity-50" />
|
||||
@ -3483,7 +3483,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">鼠标</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
选择图层并拖动位置
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3518,7 +3518,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<div className="font-medium text-muted-foreground text-xs">
|
||||
<div className="font-medium text-[#666666] text-xs">
|
||||
颜色
|
||||
</div>
|
||||
<button
|
||||
@ -3531,7 +3531,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<span>选择颜色</span>
|
||||
<span
|
||||
className="h-5 w-5 rounded-full border border-[#e7e1d4] shadow-inner"
|
||||
className="h-5 w-5 rounded-full border border-[#e5e5e5] shadow-inner"
|
||||
style={{ backgroundColor: brushColor }}
|
||||
/>
|
||||
</button>
|
||||
@ -3547,9 +3547,9 @@ export function RealtimeCanvasDialog({
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between font-medium text-muted-foreground text-xs">
|
||||
<div className="flex items-center justify-between font-medium text-[#666666] text-xs">
|
||||
<span>粗细</span>
|
||||
<span className="w-8 text-right text-foreground">
|
||||
<span className="w-8 text-right text-[#111111]">
|
||||
{brushSize}
|
||||
</span>
|
||||
</div>
|
||||
@ -3558,10 +3558,10 @@ export function RealtimeCanvasDialog({
|
||||
max={50}
|
||||
min={2}
|
||||
onValueChange={([val]) => setBrushSize(val)}
|
||||
rangeClassName="bg-[#7da2ff]"
|
||||
rangeClassName="bg-[#111111]"
|
||||
step={1}
|
||||
thumbClassName="h-5 w-5 border border-[#d8e4ff] bg-[#eef4ff] shadow-sm"
|
||||
trackClassName="h-2.5 bg-muted shadow-inner"
|
||||
thumbClassName="h-5 w-5 border border-[#d4d4d4] bg-white shadow-sm"
|
||||
trackClassName="h-2.5 bg-[#ededed] shadow-inner"
|
||||
value={[brushSize]}
|
||||
/>
|
||||
</div>
|
||||
@ -3570,7 +3570,7 @@ export function RealtimeCanvasDialog({
|
||||
</Popover>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">画笔</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
点击后直接调整颜色和粗细
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3604,9 +3604,9 @@ export function RealtimeCanvasDialog({
|
||||
)}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between font-medium text-muted-foreground text-xs">
|
||||
<div className="flex items-center justify-between font-medium text-[#666666] text-xs">
|
||||
<span>橡皮粗细</span>
|
||||
<span className="w-8 text-right text-foreground">
|
||||
<span className="w-8 text-right text-[#111111]">
|
||||
{brushSize}
|
||||
</span>
|
||||
</div>
|
||||
@ -3615,10 +3615,10 @@ export function RealtimeCanvasDialog({
|
||||
max={50}
|
||||
min={2}
|
||||
onValueChange={([val]) => setBrushSize(val)}
|
||||
rangeClassName="bg-[#7da2ff]"
|
||||
rangeClassName="bg-[#111111]"
|
||||
step={1}
|
||||
thumbClassName="h-5 w-5 border border-[#d8e4ff] bg-[#eef4ff] shadow-sm"
|
||||
trackClassName="h-2.5 bg-muted shadow-inner"
|
||||
thumbClassName="h-5 w-5 border border-[#d4d4d4] bg-white shadow-sm"
|
||||
trackClassName="h-2.5 bg-[#ededed] shadow-inner"
|
||||
value={[brushSize]}
|
||||
/>
|
||||
</div>
|
||||
@ -3626,7 +3626,7 @@ export function RealtimeCanvasDialog({
|
||||
</Popover>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">橡皮</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
点击后直接调整橡皮粗细
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3655,7 +3655,7 @@ export function RealtimeCanvasDialog({
|
||||
floatingSurfaceClass
|
||||
)}
|
||||
>
|
||||
<div className="mb-2 font-medium text-muted-foreground text-xs">
|
||||
<div className="mb-2 font-medium text-[#666666] text-xs">
|
||||
形状工具
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
@ -3664,7 +3664,7 @@ export function RealtimeCanvasDialog({
|
||||
"h-10 rounded-xl border",
|
||||
brushMode === "rect"
|
||||
? softActionButtonClass
|
||||
: "border-transparent text-slate-600 hover:bg-[#f7f3eb] hover:text-foreground"
|
||||
: "border-transparent text-[#666666] hover:bg-[#f5f5f5] hover:text-[#111111]"
|
||||
)}
|
||||
onClick={() => activateShapeMode("rect")}
|
||||
type="button"
|
||||
@ -3677,7 +3677,7 @@ export function RealtimeCanvasDialog({
|
||||
"h-10 rounded-xl border",
|
||||
brushMode === "circle"
|
||||
? softActionButtonClass
|
||||
: "border-transparent text-slate-600 hover:bg-[#f7f3eb] hover:text-foreground"
|
||||
: "border-transparent text-[#666666] hover:bg-[#f5f5f5] hover:text-[#111111]"
|
||||
)}
|
||||
onClick={() => activateShapeMode("circle")}
|
||||
type="button"
|
||||
@ -3690,7 +3690,7 @@ export function RealtimeCanvasDialog({
|
||||
"h-10 rounded-xl border",
|
||||
brushMode === "line"
|
||||
? softActionButtonClass
|
||||
: "border-transparent text-slate-600 hover:bg-[#f7f3eb] hover:text-foreground"
|
||||
: "border-transparent text-[#666666] hover:bg-[#f5f5f5] hover:text-[#111111]"
|
||||
)}
|
||||
onClick={() => activateShapeMode("line")}
|
||||
type="button"
|
||||
@ -3703,7 +3703,7 @@ export function RealtimeCanvasDialog({
|
||||
</Popover>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">形状</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
矩形、圆形与直线
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3723,7 +3723,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">保存项目</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
保存当前画布状态
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3745,7 +3745,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">项目列表</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
打开已保存项目
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3764,7 +3764,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">新建空白</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
清空并开始新项目
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3785,7 +3785,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">撤销</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
回退上一步编辑
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3805,7 +3805,7 @@ export function RealtimeCanvasDialog({
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<div className="font-medium text-sm">重做</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
<div className="text-[#666666] text-xs">
|
||||
恢复已撤销操作
|
||||
</div>
|
||||
</TooltipContent>
|
||||
@ -3853,7 +3853,7 @@ export function RealtimeCanvasDialog({
|
||||
/>
|
||||
{statusBadge.label}
|
||||
</div>
|
||||
<div className="flex h-6 items-center rounded-full bg-muted px-2.5 font-medium text-muted-foreground text-xs">
|
||||
<div className="flex h-6 items-center rounded-full border border-[#e5e5e5] bg-white px-2.5 font-medium text-[#666666] text-xs">
|
||||
延迟 {adaptiveThrottleMs}ms
|
||||
</div>
|
||||
</div>
|
||||
@ -3897,8 +3897,8 @@ export function RealtimeCanvasDialog({
|
||||
|
||||
if (standalone) {
|
||||
return (
|
||||
<div className="h-dvh w-full overflow-hidden bg-background">
|
||||
<div className="relative h-full w-full overflow-hidden bg-background">
|
||||
<div className="h-dvh w-full overflow-hidden bg-white">
|
||||
<div className="relative h-full w-full overflow-hidden bg-white">
|
||||
{content}
|
||||
</div>
|
||||
</div>
|
||||
@ -3907,7 +3907,7 @@ export function RealtimeCanvasDialog({
|
||||
|
||||
return (
|
||||
<Dialog onOpenChange={onOpenChange} open={open}>
|
||||
<DialogContent className="h-[97vh] w-[98vw] max-w-[1800px] overflow-hidden rounded-[20px] border-0 bg-background p-0 shadow-2xl sm:rounded-[20px] md:rounded-[24px]">
|
||||
<DialogContent className="h-[97vh] w-[98vw] max-w-[1800px] overflow-hidden rounded-[20px] border-0 bg-white p-0 shadow-2xl sm:rounded-[20px] md:rounded-[24px]">
|
||||
{content}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user