fix(canvas): 画布创作交互 - 优化提示词面板并修复工具弹窗与节点缩放卡顿

This commit is contained in:
ddCat committed 2026-07-31 22:27:58 +08:00
1 parent 8006149370
commit ea02df69cd
13 files changed
+478 -130

No files matched your search

+22 -11
View File
@@ -40,7 +40,7 @@ type ImageSettingsPanelProps = {
quickCount?: number;
};
export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle = true, showCount = true, className = "w-[304px] space-y-3 rounded-2xl px-1 py-0.5", maxCount = 15, quickCount = 10 }: ImageSettingsPanelProps) {
export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle = true, showCount = true, className = "w-[304px] space-y-3 rounded-2xl px-1 py-0.5", maxCount = 15, quickCount = 3 }: ImageSettingsPanelProps) {
const [snapDimensionToStep, setSnapDimensionToStep] = useState(true);
const quality = config.quality || "auto";
const transparentBackground = config.transparentBackground === "true";
@@ -116,18 +116,18 @@ export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle =
</div>
<div className="space-y-2">
<SettingTitle color={theme.node.muted}>宽高比</SettingTitle>
<div className="grid grid-cols-4 gap-1.5">
<div className="grid grid-cols-4 gap-1.5 min-[380px]:grid-cols-5">
{aspectOptions.map((item) => (
<button
key={item.value}
type="button"
className="flex h-[58px] cursor-pointer flex-col items-center justify-center gap-0.5 rounded-lg bg-transparent text-xs transition-colors hover:brightness-110 focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-1"
className="flex h-[52px] cursor-pointer flex-col items-center justify-center gap-0.5 rounded-lg bg-transparent text-[11px] transition-colors hover:brightness-110 focus-visible:outline focus-visible:outline-1 focus-visible:outline-offset-1"
style={{ background: selectedAspect?.value === item.value ? theme.toolbar.activeBg : "transparent", color: theme.node.text, outlineColor: theme.node.muted }}
onMouseDown={(event) => event.stopPropagation()}
onClick={() => selectAspect(item.value)}
>
<AspectIcon type={item.icon} width={item.width} height={item.height} color={theme.node.text} />
<span>{item.label}</span>
<span className="whitespace-nowrap">{item.label}</span>
</button>
))}
</div>
@@ -138,10 +138,10 @@ export function ImageSettingsPanel({ config, onConfigChange, theme, showTitle =
<div className="grid grid-cols-4 gap-1.5">
{Array.from({ length: quickCount }, (_, index) => index + 1).map((value) => (
<OptionPill key={value} selected={count === value} theme={theme} onClick={() => onConfigChange("count", String(value))}>
{value} 张
{value}
</OptionPill>
))}
<CountInput value={count} max={maxCount} theme={theme} onChange={(value) => onConfigChange("count", String(value || 1))} />
<CountInput value={count} quickCount={quickCount} max={maxCount} theme={theme} onChange={(value) => onConfigChange("count", String(value || 1))} />
</div>
</div>
) : null}
@@ -214,17 +214,28 @@ function DimensionInput({ prefix, value, disabled, theme, alignToStep, onChange
);
}
function CountInput({ value, max, theme, onChange }: { value: number; max: number; theme: CanvasTheme; onChange: (value: number | null) => void }) {
function CountInput({ value, quickCount, max, theme, onChange }: { value: number; quickCount: number; max: number; theme: CanvasTheme; onChange: (value: number | null) => void }) {
const commit = (input: HTMLInputElement) => {
const next = Math.max(1, Math.min(max, Math.floor(Number(input.value) || 1)));
input.value = String(next);
onChange(next);
};
return (
<label className="col-span-2 flex h-8 overflow-hidden rounded-full text-xs" style={{ background: theme.toolbar.itemHover, color: theme.node.text }}>
<label className="flex h-8 overflow-hidden rounded-full text-xs" style={{ background: theme.toolbar.itemHover, color: theme.node.text }}>
<input
key={value > quickCount ? `custom-${value}` : "quick"}
type="number"
min={1}
max={max}
className="min-w-0 flex-1 bg-transparent px-3 text-center outline-none [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
aria-label="自定义生成张数"
placeholder="输入"
className="min-w-0 flex-1 bg-transparent px-2 text-center outline-none placeholder:text-current placeholder:opacity-55 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
style={{ color: theme.node.text, WebkitTextFillColor: theme.node.text }}
value={value || ""}
onChange={(event) => onChange(Number(event.target.value) || null)}
defaultValue={value > quickCount ? value : ""}
onBlur={(event) => commit(event.currentTarget)}
onKeyDown={(event) => {
if (event.key === "Enter") event.currentTarget.blur();
}}
onMouseDown={(event) => event.stopPropagation()}
/>
</label>