style: refine ai wash workspace
This commit is contained in:
parent
4e6f47d35f
commit
1eddc7e296
@ -51,21 +51,21 @@ import { cn } from "@/lib/utils";
|
||||
const fetcher = (url: string) => fetch(url).then((res) => res.json());
|
||||
|
||||
const PANEL_CLASS =
|
||||
"rounded-[28px] border border-[#e5e5e5] bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.03),0_20px_40px_rgba(0,0,0,0.06)]";
|
||||
"rounded-[22px] border border-[#ececec] bg-white shadow-[0_1px_2px_rgba(0,0,0,0.04),0_14px_30px_rgba(0,0,0,0.035)]";
|
||||
const PRIMARY_ACTION_BUTTON_CLASS =
|
||||
"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";
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_14px_28px_rgba(0,0,0,0.14)] transition hover:bg-black hover:border-black disabled:border-[#ededed] disabled:bg-[#f7f7f7] disabled:text-[#c8c8c8] disabled:shadow-none";
|
||||
const SECONDARY_ACTION_BUTTON_CLASS =
|
||||
"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";
|
||||
"border border-[#e3e3e3] bg-white text-[#111111] shadow-[0_1px_2px_rgba(0,0,0,0.04),0_8px_18px_rgba(0,0,0,0.025)] transition hover:border-[#111111] hover:bg-[#fafafa] hover:text-black disabled:border-[#eeeeee] disabled:bg-[#fafafa] disabled:text-[#cfcfcf] disabled:shadow-none";
|
||||
const FIELD_CLASS =
|
||||
"h-10 rounded-[14px] 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)]";
|
||||
"h-10 rounded-[16px] border-[#e9e9e9] bg-white text-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95),0_1px_2px_rgba(0,0,0,0.035)]";
|
||||
const SELECT_CONTENT_CLASS =
|
||||
"border-[#e5e5e5] bg-white text-[#111111] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_18px_38px_rgba(0,0,0,0.08)]";
|
||||
"border-[#ececec] bg-white text-[#111111] shadow-[0_1px_2px_rgba(0,0,0,0.04),0_18px_38px_rgba(0,0,0,0.06)]";
|
||||
const SIDEBAR_SCROLL_CLASS =
|
||||
"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 SLIDER_TRACK_CLASS = "h-2.5 bg-[#ededed] shadow-inner";
|
||||
const SLIDER_TRACK_CLASS = "h-1.5 bg-[#ededed] shadow-inner";
|
||||
const SLIDER_RANGE_CLASS = "bg-[#111111]";
|
||||
const SLIDER_THUMB_CLASS =
|
||||
"h-4 w-4 border border-[#d4d4d4] bg-white shadow-[0_0_0_4px_rgba(0,0,0,0.08)]";
|
||||
"h-3.5 w-3.5 border border-[#d8d8d8] bg-white shadow-[0_0_0_3px_rgba(0,0,0,0.05)]";
|
||||
const AI_WASH_HISTORY_STORAGE_KEY = "ai-chatbot:ai-wash-history:v1";
|
||||
const AI_WASH_HISTORY_TOTAL_LIMIT = 24;
|
||||
const AI_WASH_TASK_POLL_INTERVAL_MS = 2500;
|
||||
@ -537,10 +537,6 @@ export function AiWashWorkspace({
|
||||
() => presetExecutionStates.some((item) => item.usesUserSelectableModel),
|
||||
[presetExecutionStates]
|
||||
);
|
||||
const totalEstimatedCost = useMemo(
|
||||
() => presetExecutionStates.reduce((sum, item) => sum + item.unitCost, 0),
|
||||
[presetExecutionStates]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setResults(createIdleResultCards(enabledPresets));
|
||||
@ -941,13 +937,13 @@ export function AiWashWorkspace({
|
||||
return (
|
||||
<div className="relative flex h-full w-full bg-[#ffffff] text-[#111111]">
|
||||
<div className="pointer-events-none absolute inset-0 bg-[#ffffff]" />
|
||||
<div className="pattern-grid-lg pointer-events-none absolute inset-0 opacity-[0.025]" />
|
||||
<div className="pattern-grid-lg pointer-events-none absolute inset-0 opacity-[0.018]" />
|
||||
|
||||
<div className="relative z-10 flex h-full w-full pt-24">
|
||||
<aside className="relative z-20 order-2 -mt-16 h-[calc(100%+4rem)] w-[430px] max-w-[42vw] shrink-0 pb-6 pr-6">
|
||||
<div className="relative z-10 flex h-full w-full pt-[86px]">
|
||||
<aside className="relative z-20 order-2 -mt-12 h-[calc(100%+3rem)] w-[404px] max-w-[36vw] shrink-0 pb-5 pr-5">
|
||||
<div
|
||||
className={cn(
|
||||
"h-full space-y-4 overflow-y-auto rounded-[36px] border border-[#e7e7e7] bg-white/72 p-4 shadow-[0_24px_70px_rgba(0,0,0,0.08)] backdrop-blur-xl",
|
||||
"h-full space-y-3.5 overflow-y-auto rounded-[30px] border border-[#ececec] bg-white/78 p-3.5 shadow-[0_1px_2px_rgba(0,0,0,0.04),0_20px_54px_rgba(0,0,0,0.055)] backdrop-blur-xl",
|
||||
SIDEBAR_SCROLL_CLASS
|
||||
)}
|
||||
>
|
||||
@ -975,24 +971,24 @@ export function AiWashWorkspace({
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="rounded-[30px] border border-[#e8e8e8] bg-[#fbfbfb]/90 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.9)]">
|
||||
<div className="space-y-3.5">
|
||||
<div className="rounded-[26px] border border-[#ededed] bg-[#fbfbfb]/82 p-3 shadow-[inset_0_1px_0_rgba(255,255,255,0.9)]">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div className="flex h-14 w-14 shrink-0 items-center justify-center rounded-[22px] border border-[#ececec] bg-white text-[#111111] shadow-[0_12px_24px_rgba(0,0,0,0.06)]">
|
||||
<SlidersHorizontal className="h-6 w-6" />
|
||||
<div className="flex min-w-0 items-center gap-2.5">
|
||||
<div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[18px] border border-[#ececec] bg-white text-[#111111] shadow-[0_8px_18px_rgba(0,0,0,0.045)]">
|
||||
<SlidersHorizontal className="h-5 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="inline-flex rounded-full border border-[#e6e6e6] bg-white px-3 py-1 font-semibold text-[11px] text-[#777777] tracking-[0.18em]">
|
||||
<div className="inline-flex rounded-full border border-[#e7e7e7] bg-white px-2.5 py-0.5 font-semibold text-[10px] text-[#777777] tracking-[0.18em]">
|
||||
STUDIO SETUP
|
||||
</div>
|
||||
<div className="mt-2 font-semibold text-[20px] text-[#111111]">
|
||||
<div className="mt-1.5 font-semibold text-[18px] text-[#111111] tracking-[-0.03em]">
|
||||
设置
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-2">
|
||||
<span className="rounded-full border border-[#e6e6e6] bg-white px-3 py-1.5 text-xs text-[#666666]">
|
||||
<span className="rounded-full border border-[#e6e6e6] bg-white px-3 py-1 text-xs text-[#666666]">
|
||||
Redefine
|
||||
</span>
|
||||
<ChevronDown className="h-4 w-4 rotate-180 text-[#666666]" />
|
||||
@ -1000,11 +996,11 @@ export function AiWashWorkspace({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-[26px] border border-[#ececec] bg-[#fbfbfb]/92 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.95)]">
|
||||
<div className="mb-3 font-semibold text-[17px] text-[#111111]">
|
||||
<div className="rounded-[24px] border border-[#ededed] bg-[#fbfbfb]/84 p-3.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.95)]">
|
||||
<div className="mb-2.5 font-semibold text-[16px] text-[#111111] tracking-[-0.02em]">
|
||||
增强预设
|
||||
</div>
|
||||
<div className="space-y-2.5">
|
||||
<div className="space-y-2">
|
||||
{presetExecutionStates.map((item) => {
|
||||
const targetResult = results.find(
|
||||
(result) => result.presetId === item.preset.id
|
||||
@ -1017,22 +1013,22 @@ export function AiWashWorkspace({
|
||||
<button
|
||||
aria-pressed={isActive}
|
||||
className={cn(
|
||||
"w-full rounded-[18px] border px-4 py-3 text-left transition",
|
||||
"w-full rounded-[17px] border px-3.5 py-2.5 text-left transition",
|
||||
isActive
|
||||
? "border-[#111111] bg-white text-[#111111] shadow-[0_10px_22px_rgba(0,0,0,0.08)]"
|
||||
: "border-[#e8e8e8] bg-white text-[#666666] hover:border-[#111111] hover:text-[#111111]"
|
||||
? "border-[#111111] bg-white text-[#111111] shadow-[0_8px_18px_rgba(0,0,0,0.055)]"
|
||||
: "border-[#e9e9e9] bg-white/92 text-[#666666] hover:border-[#d6d6d6] hover:text-[#111111]"
|
||||
)}
|
||||
key={item.preset.id}
|
||||
onClick={() => setSelectedResultId(item.preset.id)}
|
||||
type="button"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="min-w-0 truncate font-medium text-[15px]">
|
||||
<div className="min-w-0 truncate font-medium text-[14px]">
|
||||
{item.preset.title}
|
||||
</div>
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0 rounded-full border px-2 py-1 text-[11px]",
|
||||
"shrink-0 rounded-full border px-2 py-0.5 text-[10px]",
|
||||
isActive
|
||||
? "border-[#111111] bg-[#111111] text-white"
|
||||
: "border-[#ebebeb] bg-[#fafafa] text-[#666666]"
|
||||
@ -1045,15 +1041,15 @@ export function AiWashWorkspace({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mt-3 max-h-24 overflow-hidden rounded-[18px] border border-[#e9e9e9] bg-white px-4 py-3 text-sm leading-6 text-[#666666]">
|
||||
<div className="mt-3 max-h-24 overflow-hidden rounded-[17px] border border-[#ececec] bg-white/92 px-3.5 py-2.5 text-[13px] leading-6 text-[#666666] shadow-[0_1px_2px_rgba(0,0,0,0.025)]">
|
||||
{selectedExecutionState?.resolvedPrompt ||
|
||||
"选择预设后会使用管理员配置的提示词进行 AI洗图。"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-[26px] border border-[#ececec] bg-[#fbfbfb]/92 p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.95)]">
|
||||
<div className="rounded-[24px] border border-[#ededed] bg-[#fbfbfb]/84 p-3.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.95)]">
|
||||
<div className="mb-3 flex min-w-0 items-center justify-between gap-3">
|
||||
<div className="font-semibold text-[17px] text-[#111111]">
|
||||
<div className="font-semibold text-[16px] text-[#111111] tracking-[-0.02em]">
|
||||
参数设置
|
||||
</div>
|
||||
<Settings2 className="h-4 w-4 text-[#777777]" />
|
||||
@ -1125,14 +1121,14 @@ export function AiWashWorkspace({
|
||||
null;
|
||||
return (
|
||||
<div
|
||||
className="rounded-[20px] border border-[#ececec] bg-white px-4 py-3.5 shadow-[0_8px_18px_rgba(0,0,0,0.03)]"
|
||||
className="rounded-[18px] border border-[#ececec] bg-white/94 px-3.5 py-3 shadow-[0_1px_2px_rgba(0,0,0,0.025)]"
|
||||
key={control.id}
|
||||
>
|
||||
<div className="mb-2 flex items-center justify-between gap-3">
|
||||
<div className="text-sm font-medium text-[#222222]">
|
||||
<div className="text-[13px] font-medium text-[#222222]">
|
||||
{control.label}
|
||||
</div>
|
||||
<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)]">
|
||||
<div className="inline-flex min-w-[42px] justify-center rounded-full border border-[#e7e7e7] bg-white px-2 py-0.5 font-medium text-[11px] text-[#666666] shadow-[0_1px_2px_rgba(0,0,0,0.035)]">
|
||||
{activeLevel?.label || selectedIndex + 1}
|
||||
</div>
|
||||
</div>
|
||||
@ -1161,12 +1157,12 @@ export function AiWashWorkspace({
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main className="order-1 relative min-w-0 flex-1 overflow-hidden px-8 pb-7 pt-6">
|
||||
<main className="order-1 relative min-w-0 flex-1 overflow-hidden px-7 pb-6 pt-5">
|
||||
<div className="relative h-full w-full">
|
||||
{compareSourceUrl ? (
|
||||
<button
|
||||
className={cn(
|
||||
"absolute right-4 top-2 z-20 inline-flex h-10 items-center rounded-full px-4 text-sm font-medium",
|
||||
"absolute right-4 top-2 z-20 inline-flex h-9 items-center rounded-full px-3.5 text-[13px] font-medium",
|
||||
SECONDARY_ACTION_BUTTON_CLASS
|
||||
)}
|
||||
onClick={() => onRequestAddImage?.()}
|
||||
@ -1177,12 +1173,12 @@ export function AiWashWorkspace({
|
||||
</button>
|
||||
) : null}
|
||||
|
||||
<div className="absolute inset-0 flex items-center justify-center px-8 pb-44 pt-8">
|
||||
<div className="absolute inset-0 flex items-center justify-center px-8 pb-36 pt-6">
|
||||
{selectedPreviewResult && previewHasImage ? (
|
||||
<div className="relative max-h-full max-w-full overflow-hidden rounded-[24px] shadow-[0_18px_52px_rgba(0,0,0,0.08)]">
|
||||
<div className="relative max-h-full max-w-full overflow-hidden rounded-[22px] shadow-[0_16px_44px_rgba(0,0,0,0.07)]">
|
||||
<img
|
||||
alt={selectedPreviewResult.title}
|
||||
className="block max-h-[calc(100vh-320px)] max-w-[min(64vw,1120px)] object-contain"
|
||||
className="block max-h-[calc(100vh-284px)] max-w-[min(62vw,1080px)] object-contain"
|
||||
src={getDisplayImageUrl(selectedPreviewResult.imageUrl || "", 1800)}
|
||||
/>
|
||||
{compareSourceUrl ? (
|
||||
@ -1229,15 +1225,15 @@ export function AiWashWorkspace({
|
||||
style={{ left: `${previewComparePosition}%` }}
|
||||
>
|
||||
<div className="absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-white" />
|
||||
<div className="absolute left-1/2 top-1/2 flex h-12 w-12 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-white bg-black/72 text-white shadow-[0_14px_28px_rgba(0,0,0,0.24)]">
|
||||
<RefreshCcw className="h-4 w-4" />
|
||||
<div className="absolute left-1/2 top-1/2 flex h-10 w-10 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full border border-white bg-black/70 text-white shadow-[0_12px_24px_rgba(0,0,0,0.2)]">
|
||||
<RefreshCcw className="h-3.5 w-3.5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="pointer-events-none absolute left-4 top-4 rounded-full bg-black/65 px-3 py-1.5 text-[11px] text-white">
|
||||
<div className="pointer-events-none absolute left-4 top-4 rounded-full bg-black/58 px-2.5 py-1 text-[11px] text-white">
|
||||
原图
|
||||
</div>
|
||||
<div className="pointer-events-none absolute right-4 top-4 rounded-full bg-black/65 px-3 py-1.5 text-[11px] text-white">
|
||||
<div className="pointer-events-none absolute right-4 top-4 rounded-full bg-black/58 px-2.5 py-1 text-[11px] text-white">
|
||||
洗后
|
||||
</div>
|
||||
</>
|
||||
@ -1247,17 +1243,17 @@ export function AiWashWorkspace({
|
||||
<div className="relative max-h-full max-w-full">
|
||||
<img
|
||||
alt="AI洗图底图"
|
||||
className="block max-h-[calc(100vh-320px)] max-w-[min(64vw,1120px)] rounded-[24px] object-contain shadow-[0_18px_52px_rgba(0,0,0,0.08)]"
|
||||
className="block max-h-[calc(100vh-284px)] max-w-[min(62vw,1080px)] rounded-[22px] object-contain shadow-[0_16px_44px_rgba(0,0,0,0.07)]"
|
||||
src={getDisplayImageUrl(compareSourceUrl, 1800)}
|
||||
/>
|
||||
<div className="pointer-events-none absolute left-4 top-4 rounded-full bg-black/65 px-3 py-1.5 text-[11px] text-white">
|
||||
<div className="pointer-events-none absolute left-4 top-4 rounded-full bg-black/58 px-2.5 py-1 text-[11px] text-white">
|
||||
原图
|
||||
</div>
|
||||
{selectedPreviewResult?.status === "running" ||
|
||||
selectedPreviewResult?.status === "submitting" ||
|
||||
selectedPreviewResult?.status === "failed" ? (
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-[24px] bg-white/58 px-6 text-center backdrop-blur-[1px]">
|
||||
<div className="max-w-sm rounded-[24px] border border-[#ececec] bg-white/92 px-6 py-5 shadow-[0_18px_40px_rgba(0,0,0,0.08)]">
|
||||
<div className="absolute inset-0 flex items-center justify-center rounded-[22px] bg-white/58 px-6 text-center backdrop-blur-[1px]">
|
||||
<div className="max-w-sm rounded-[22px] border border-[#ececec] bg-white/92 px-5 py-4 shadow-[0_14px_34px_rgba(0,0,0,0.07)]">
|
||||
{selectedPreviewResult.status === "running" ||
|
||||
selectedPreviewResult.status === "submitting" ? (
|
||||
<>
|
||||
@ -1288,33 +1284,28 @@ export function AiWashWorkspace({
|
||||
) : (
|
||||
<div className="text-center">
|
||||
<button
|
||||
className="inline-flex h-[92px] items-center rounded-[28px] bg-[#111111] px-12 text-[22px] font-semibold text-white shadow-[0_22px_56px_rgba(0,0,0,0.16)] transition hover:bg-black"
|
||||
className="inline-flex h-16 items-center rounded-[22px] bg-[#111111] px-9 text-[18px] font-semibold text-white shadow-[0_18px_42px_rgba(0,0,0,0.14)] transition hover:-translate-y-0.5 hover:bg-black"
|
||||
onClick={() => onRequestAddImage?.()}
|
||||
type="button"
|
||||
>
|
||||
<ImageIcon className="mr-4 h-6 w-6" />
|
||||
<ImageIcon className="mr-3 h-5 w-5" />
|
||||
添加图片
|
||||
</button>
|
||||
<div className="mt-5 text-[15px] text-[#777777]">
|
||||
<div className="mt-4 text-[14px] text-[#777777]">
|
||||
选择本地图后即可开始 {config.modeLabel || "AI洗图"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-0 left-1/2 z-30 flex -translate-x-1/2 flex-col items-center gap-2">
|
||||
<div className="rounded-full border border-[#e5e5e5] bg-white/92 px-5 py-2 text-xs text-[#666666] shadow-[0_10px_24px_rgba(0,0,0,0.06)] backdrop-blur">
|
||||
<div className="absolute bottom-2 left-1/2 z-30 flex -translate-x-1/2 flex-col items-center gap-2">
|
||||
<div className="rounded-full border border-[#e7e7e7] bg-white/90 px-4 py-1.5 text-[12px] text-[#666666] shadow-[0_8px_18px_rgba(0,0,0,0.04)] backdrop-blur">
|
||||
生成后可直接发送回画布
|
||||
</div>
|
||||
<div className="rounded-full border border-[#e5e5e5] bg-white/92 px-5 py-2 text-xs text-[#333333] shadow-[0_10px_24px_rgba(0,0,0,0.06)] backdrop-blur">
|
||||
{totalEstimatedCost > 0
|
||||
? `预计消耗 ${totalEstimatedCost} 积分`
|
||||
: "预计消耗按模型配置计算"}
|
||||
</div>
|
||||
<div className="flex items-center gap-3 rounded-[34px] border border-[#e6e6e6] bg-white/88 p-3 shadow-[0_18px_46px_rgba(0,0,0,0.08)] backdrop-blur-xl">
|
||||
<div className="flex items-center gap-2 rounded-[30px] border border-[#e7e7e7] bg-white/86 p-2 shadow-[0_14px_36px_rgba(0,0,0,0.06)] backdrop-blur-xl">
|
||||
<Button
|
||||
className={cn(
|
||||
"h-14 min-w-[220px] rounded-[26px] px-8 text-[15px] font-semibold",
|
||||
"h-12 min-w-[190px] rounded-[24px] px-6 text-[14px] font-semibold",
|
||||
PRIMARY_ACTION_BUTTON_CLASS
|
||||
)}
|
||||
disabled={
|
||||
@ -1335,7 +1326,7 @@ export function AiWashWorkspace({
|
||||
</Button>
|
||||
<Button
|
||||
className={cn(
|
||||
"h-14 min-w-[220px] rounded-[26px] px-8 text-[15px] font-medium",
|
||||
"h-12 min-w-[190px] rounded-[24px] px-6 text-[14px] font-medium",
|
||||
SECONDARY_ACTION_BUTTON_CLASS
|
||||
)}
|
||||
disabled={!selectedResult?.imageUrl}
|
||||
|
||||
@ -3428,11 +3428,11 @@ export function RealtimeCanvasDialog({
|
||||
}, [clearPreviewCanvas, closeBrushSettingPopovers, resetCanvas]);
|
||||
|
||||
const floatingSurfaceClass =
|
||||
"border border-[#e5e5e5] bg-white/96 text-[#111111] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_20px_42px_rgba(0,0,0,0.08)] backdrop-blur-xl dark:border-white/12 dark:bg-[#111317]/92 dark:text-white dark:shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_24px_56px_rgba(0,0,0,0.45)]";
|
||||
"border border-[#e9e9e9] bg-white/92 text-[#111111] shadow-[0_1px_2px_rgba(0,0,0,0.045),0_14px_34px_rgba(0,0,0,0.055)] backdrop-blur-xl dark:border-white/12 dark:bg-[#111317]/92 dark:text-white dark:shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_24px_56px_rgba(0,0,0,0.45)]";
|
||||
const controlSurfaceClass =
|
||||
"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)] dark:border-white/12 dark:bg-white/[0.07] dark:text-white dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.08),0_1px_2px_rgba(0,0,0,0.35)]";
|
||||
const softActionButtonClass =
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_12px_24px_rgba(0,0,0,0.12)] transition hover:bg-black hover:text-white dark:border-white dark:bg-white dark:text-[#111111] dark:shadow-[0_14px_30px_rgba(0,0,0,0.42)] dark:hover:bg-white/90 dark:hover:text-[#111111]";
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_9px_20px_rgba(0,0,0,0.11)] transition hover:bg-black hover:text-white dark:border-white dark:bg-white dark:text-[#111111] dark:shadow-[0_14px_30px_rgba(0,0,0,0.42)] dark:hover:bg-white/90 dark:hover:text-[#111111]";
|
||||
const primaryActionButtonClass =
|
||||
"border border-[#111111] bg-[#111111] text-white shadow-[0_16px_30px_rgba(0,0,0,0.18)] transition hover:bg-black hover:border-black dark:border-white dark:bg-white dark:text-[#111111] dark:hover:border-white/90 dark:hover:bg-white/90";
|
||||
const compactToolButtonClass =
|
||||
@ -3477,35 +3477,35 @@ export function RealtimeCanvasDialog({
|
||||
<DialogDescription>左侧绘制草图,右侧实时预览。</DialogDescription>
|
||||
</DialogHeader>
|
||||
)}
|
||||
<div className="pointer-events-none absolute top-6 left-6 right-6 z-50 flex flex-wrap items-start gap-3">
|
||||
<div className="pointer-events-none absolute top-5 left-5 right-5 z-50 flex flex-wrap items-start gap-2.5">
|
||||
<div
|
||||
className={cn(
|
||||
"pointer-events-auto inline-flex max-w-full items-center gap-2 rounded-[30px] p-2",
|
||||
"pointer-events-auto inline-flex max-w-full items-center gap-1.5 rounded-[28px] p-1.5",
|
||||
floatingSurfaceClass
|
||||
)}
|
||||
>
|
||||
<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-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95)] transition hover:bg-white dark:border-white/12 dark:bg-white/8 dark:text-white dark:shadow-none dark:hover:bg-white/12"
|
||||
className="inline-flex h-10 shrink-0 items-center gap-2 rounded-[20px] border border-white/90 bg-white/78 px-3 text-left text-[#111111] shadow-[inset_0_1px_0_rgba(255,255,255,0.95)] transition hover:bg-white dark:border-white/12 dark:bg-white/8 dark:text-white dark:shadow-none dark:hover:bg-white/12"
|
||||
onClick={handleCloseRealtime}
|
||||
title={realtimeReturnCanvasItem.label}
|
||||
type="button"
|
||||
>
|
||||
<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)] dark:border-white/12 dark:bg-white/10 dark:shadow-none">
|
||||
<span className="flex h-7 w-7 items-center justify-center rounded-full border border-[#ececec] bg-white shadow-[0_5px_12px_rgba(0,0,0,0.045)] dark:border-white/12 dark:bg-white/10 dark:shadow-none">
|
||||
<CanvasToolbarIcon
|
||||
className="h-4 w-4 text-[#111111] dark:text-white"
|
||||
className="h-3.5 w-3.5 text-[#111111] dark:text-white"
|
||||
fallback={ArrowLeft}
|
||||
item={realtimeReturnCanvasItem}
|
||||
/>
|
||||
</span>
|
||||
<span className="font-semibold text-[14px] tracking-[-0.02em]">
|
||||
<span className="font-semibold text-[13px] tracking-[-0.02em]">
|
||||
{realtimeReturnCanvasItem.label}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<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)] dark:border-white/12 dark:bg-white/8 dark:shadow-none">
|
||||
<div className="inline-flex h-10 min-w-0 items-center gap-0.5 rounded-[20px] border border-[#ebebeb] bg-[#fafafa]/90 p-0.5 shadow-[inset_0_1px_0_rgba(255,255,255,0.9)] dark:border-white/12 dark:bg-white/8 dark:shadow-none">
|
||||
<button
|
||||
className={cn(
|
||||
"group inline-flex h-full min-w-0 items-center gap-2 rounded-[18px] px-4 text-[14px] font-medium tracking-[-0.02em] transition",
|
||||
"group inline-flex h-full min-w-0 items-center gap-1.5 rounded-[17px] px-3 text-[13px] font-medium tracking-[-0.02em] transition",
|
||||
workspaceMode === "realtime"
|
||||
? softActionButtonClass
|
||||
: "border border-transparent bg-transparent text-[#666666] hover:bg-white hover:text-[#111111] dark:text-white/58 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
@ -3515,7 +3515,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<CanvasToolbarIcon
|
||||
active={workspaceMode === "realtime"}
|
||||
className="h-4 w-4 transition group-hover:opacity-100"
|
||||
className="h-3.5 w-3.5 transition group-hover:opacity-100"
|
||||
fallback={Paintbrush}
|
||||
item={realtimeModeRealtimeItem}
|
||||
/>
|
||||
@ -3526,7 +3526,7 @@ export function RealtimeCanvasDialog({
|
||||
{isEnhanceProEnabled ? (
|
||||
<button
|
||||
className={cn(
|
||||
"group inline-flex h-full min-w-0 items-center gap-2 rounded-[18px] px-4 text-[14px] font-medium tracking-[-0.02em] transition",
|
||||
"group inline-flex h-full min-w-0 items-center gap-1.5 rounded-[17px] px-3 text-[13px] font-medium tracking-[-0.02em] transition",
|
||||
workspaceMode === "enhance-pro"
|
||||
? softActionButtonClass
|
||||
: "border border-transparent bg-transparent text-[#666666] hover:bg-white hover:text-[#111111] dark:text-white/58 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
@ -3536,7 +3536,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<CanvasToolbarIcon
|
||||
active={workspaceMode === "enhance-pro"}
|
||||
className="h-4 w-4 transition group-hover:opacity-100"
|
||||
className="h-3.5 w-3.5 transition group-hover:opacity-100"
|
||||
fallback={Wand2}
|
||||
item={realtimeModeEnhanceItem}
|
||||
/>
|
||||
@ -3548,7 +3548,7 @@ export function RealtimeCanvasDialog({
|
||||
{isAiWashEnabled ? (
|
||||
<button
|
||||
className={cn(
|
||||
"group inline-flex h-full min-w-0 items-center gap-2 rounded-[18px] px-4 text-[14px] font-medium tracking-[-0.02em] transition",
|
||||
"group inline-flex h-full min-w-0 items-center gap-1.5 rounded-[17px] px-3 text-[13px] font-medium tracking-[-0.02em] transition",
|
||||
workspaceMode === "ai-wash"
|
||||
? softActionButtonClass
|
||||
: "border border-transparent bg-transparent text-[#666666] hover:bg-white hover:text-[#111111] dark:text-white/58 dark:hover:bg-white/10 dark:hover:text-white"
|
||||
@ -3558,7 +3558,7 @@ export function RealtimeCanvasDialog({
|
||||
>
|
||||
<CanvasToolbarIcon
|
||||
active={workspaceMode === "ai-wash"}
|
||||
className="h-4 w-4 transition group-hover:opacity-100"
|
||||
className="h-3.5 w-3.5 transition group-hover:opacity-100"
|
||||
fallback={Sparkles}
|
||||
iconUrl={aiWashModeIconUrl}
|
||||
/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user