fix(canvas): 解决画布节点拖拽操作被控件拦截问题

- 在 CanvasConfigNodePanel 组件中为 Segmented 控件添加事件阻止传播
- 为输入框和按钮组件添加 onMouseDown 事件阻止传播
- 为 ModelPicker 和 CanvasSizePicker 的下拉菜单添加事件阻止传播
- 更新 API 基础 URL 默认端口从 8080 改为 3000
- 更新开发服务器端口配置为 3001
- 在 CHANGELOG 中更新修复说明
This commit is contained in:
HouYunFei
2026-05-19 20:56:25 +08:00
parent 291df000e3
commit 7ce3044781
6 changed files with 25 additions and 18 deletions
+2 -1
View File
@@ -5,7 +5,8 @@
1. [新增] 增加生图工作台功能,支持文生图、图生图、查看历史记录,并增加移动端适配。
2. [修复] Docker 镜像启动时 Next.js 监听地址改为 `0.0.0.0`,便于容器环境访问。
3. [修复] 画布生成尺寸控件支持选择更多常用比例,并可直接输入自定义比例。
4. [文档] 增加 Render 部署说明
4. [修复] 生成配置节点恢复拖拽操作,避免面板控件拦截整块节点拖动
5. [文档] 增加 Render 部署说明。
## v0.0.1 - 2026-05-19
+1 -1
View File
@@ -4,7 +4,7 @@ import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
const apiBaseUrl = process.env.API_BASE_URL || "http://127.0.0.1:8080";
const apiBaseUrl = process.env.API_BASE_URL || "http://127.0.0.1:3000";
const webDir = dirname(fileURLToPath(import.meta.url));
const version = readFileSync(resolve(webDir, "../VERSION"), "utf8").trim() || "dev";
+1 -1
View File
@@ -4,7 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --webpack -H 0.0.0.0",
"dev": "next dev --webpack -H 0.0.0.0 -p 3001",
"build": "next build",
"start": "next start"
},
@@ -65,27 +65,29 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, inputs, o
};
return (
<div className="flex h-full w-full flex-col px-3 pb-3 pt-7 text-sm" style={{ color: theme.node.text }} onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()} onWheel={(event) => event.stopPropagation()}>
<div className="flex h-full w-full cursor-move flex-col px-3 pb-3 pt-7 text-sm" style={{ color: theme.node.text }} onWheel={(event) => event.stopPropagation()}>
<div className="mb-2 flex items-center justify-between gap-3">
<div className="shrink-0 text-sm font-semibold"></div>
<Segmented
size="small"
className="canvas-config-mode !rounded-md !p-0.5"
value={mode}
onChange={(value) => onConfigChange(node.id, { generationMode: value as CanvasGenerationMode })}
options={[
{ value: "image", label: <span className="inline-flex items-center gap-1"><ImageIcon className="size-3.5" /></span> },
{ value: "text", label: <span className="inline-flex items-center gap-1"><MessageSquare className="size-3.5" /></span> },
]}
/>
<div className="cursor-default" onMouseDown={(event) => event.stopPropagation()}>
<Segmented
size="small"
className="canvas-config-mode !rounded-md !p-0.5"
value={mode}
onChange={(value) => onConfigChange(node.id, { generationMode: value as CanvasGenerationMode })}
options={[
{ value: "image", label: <span className="inline-flex items-center gap-1"><ImageIcon className="size-3.5" /></span> },
{ value: "text", label: <span className="inline-flex items-center gap-1"><MessageSquare className="size-3.5" /></span> },
]}
/>
</div>
</div>
<div className="mb-2 flex flex-wrap gap-1.5">
<div className="mb-2 flex flex-wrap gap-1.5" onMouseDown={(event) => event.stopPropagation()}>
<InputChip label="提示词" value={`${inputSummary.textCount}`} style={chipStyle} />
<InputChip label="参考图" value={`${inputSummary.imageCount}`} style={chipStyle} />
<button
type="button"
className="inline-flex h-7 items-center gap-1 rounded-md border px-2 text-[11px]"
className="inline-flex h-7 cursor-pointer items-center gap-1 rounded-md border px-2 text-[11px]"
style={chipStyle}
onClick={() => setPreviewOpen(true)}
>
@@ -94,7 +96,7 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, inputs, o
</button>
</div>
<div className="mb-2 grid min-w-0 grid-cols-[minmax(0,1fr)_92px_64px] items-center gap-2">
<div className="mb-2 grid min-w-0 cursor-default grid-cols-[minmax(0,1fr)_92px_64px] items-center gap-2" onMouseDown={(event) => event.stopPropagation()}>
<ModelPicker className="canvas-compact-control h-10" config={config} value={config.model} onChange={(model) => onConfigChange(node.id, { model })} onMissingConfig={() => openConfigDialog(true)} fullWidth />
{mode === "image" ? <CanvasSizePicker className="h-10 min-w-0" value={node.metadata?.size || globalConfig.size || defaultConfig.size} onChange={(value) => onConfigChange(node.id, { size: value })} /> : null}
<InputNumber min={1} max={15} className="canvas-compact-control canvas-control-number h-10 !w-full" value={count} onChange={(value) => onConfigChange(node.id, { count: Number(value) || 1 })} />
@@ -102,8 +104,9 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, inputs, o
<Button
type="primary"
className="mt-auto !h-9 !w-full !rounded-lg"
className="mt-auto !h-9 !w-full !cursor-pointer !rounded-lg"
disabled={isRunning || (!inputSummary.textCount && !inputSummary.imageCount)}
onMouseDown={(event) => event.stopPropagation()}
onClick={() => onGenerate(node.id)}
icon={isRunning ? <LoaderCircle className="size-4 animate-spin" /> : <Play className="size-4" />}
>
@@ -47,6 +47,7 @@ export function CanvasSizePicker({ value, className, onChange }: CanvasSizePicke
placeholder="比例"
options={options}
popupMatchSelectWidth={false}
popupRender={(menu) => <div onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()}>{menu}</div>}
onOpenChange={setOpen}
onSearch={setSearch}
onChange={selectSize}
+2
View File
@@ -23,6 +23,7 @@ export function ModelPicker({ config, value, onChange, className, fullWidth = fa
showSearch
className={`canvas-control-select ${className || ""}`}
popupMatchSelectWidth={false}
popupRender={(menu) => <div onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()}>{menu}</div>}
style={{ width, maxWidth: "100%", minWidth: 0, flexShrink: 1 }}
value={value || undefined}
placeholder={placeholder}
@@ -30,6 +31,7 @@ export function ModelPicker({ config, value, onChange, className, fullWidth = fa
notFoundContent="请先到配置里拉取模型列表"
onChange={onChange}
onMouseDown={(event) => event.stopPropagation()}
onPointerDown={(event) => event.stopPropagation()}
onClick={() => {
if (!options.length) onMissingConfig?.();
}}