diff --git a/docs/pending-test.md b/docs/pending-test.md
index 00b34dd..65a702d 100644
--- a/docs/pending-test.md
+++ b/docs/pending-test.md
@@ -15,6 +15,7 @@
- 管理后台公开配置里的系统可用模型候选项改为由已启用渠道中选择的模型合并去重生成,最终开放哪些模型仍由公开配置里手动勾选。
- 视频生成请求参数对齐 `grok-imagine-video` 接口:使用 `resolution_name`、`preset=normal`、`input_reference[]`,支持清晰度、尺寸、秒数快捷选择和手动输入,并支持最多 7 张参考图。
- 画布视频设置浮层改为挂载到页面根层级,避免被节点悬浮工具栏遮挡。
+- 画布生成配置节点的生图参数改为复用图像设置浮层,支持在同一个入口里调整质量、尺寸和生成张数。
- 视频清晰度输入框改为只输入数字,提交请求时再拼接 `p` 单位。
- 视频生成前端会识别后端 `{ code, msg }` 错误响应,创建失败不再继续轮询 `undefined`。
- 新增 `/video` 视频创作台页面,参考生图工作台布局,支持提示词、参考图、视频参数、生成结果、保存素材、下载和本地生成记录;清晰度和秒数均支持常用值选择与手动输入,生成记录只保存媒体 `storageKey` 并可回填本次提示词、参考图和参数。
diff --git a/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx b/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx
index 41f2eb4..0e5b515 100644
--- a/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx
+++ b/web/src/app/(user)/canvas/components/canvas-config-node-panel.tsx
@@ -3,14 +3,14 @@
import type { CSSProperties } from "react";
import { useState } from "react";
import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Edit3, Eye, Image as ImageIcon, LoaderCircle, MessageSquare, Play, Video } from "lucide-react";
-import { App, Button, Empty, Input, InputNumber, Modal, Segmented } from "antd";
+import { App, Button, Empty, Input, Modal, Segmented } from "antd";
import { ModelPicker } from "@/components/model-picker";
import { defaultConfig, useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
import { CreditSymbol, requestCreditCost } from "@/constant/credits";
import { canvasThemes } from "@/lib/canvas-theme";
import { useThemeStore } from "@/stores/use-theme-store";
-import { CanvasSizePicker } from "./canvas-size-picker";
+import { CanvasImageSettingsPopover } from "./canvas-image-settings-popover";
import { CanvasVideoSettingsPopover } from "./canvas-video-settings-popover";
import type { NodeGenerationInput } from "./canvas-node-generation";
import type { CanvasGenerationMode, CanvasNodeData, CanvasNodeMetadata } from "../types";
@@ -118,10 +118,13 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, inputs, o
-
event.stopPropagation()}>
+
event.stopPropagation()}>
onConfigChange(node.id, { model })} onMissingConfig={() => openConfigDialog(true)} fullWidth />
- {mode === "video" ? onConfigChange(node.id, key === "videoSeconds" ? { seconds: value } : { [key]: value })} /> : mode === "image" ? onConfigChange(node.id, { size: value })} /> : null}
- {mode === "video" ? null : onConfigChange(node.id, { count: Number(value) || 1 })} />}
+ {mode === "video" ? (
+ onConfigChange(node.id, key === "videoSeconds" ? { seconds: value } : { [key]: value })} />
+ ) : mode === "image" ? (
+ onConfigChange(node.id, key === "count" ? { count: Number(value) || 1 } : { [key]: value })} />
+ ) : null}
+
+ }>
+
+ {imageQualityLabel(quality)} · {imageSizeLabel(activeSize)} · {count} 张
+
+
+
);
}
diff --git a/web/src/app/globals.css b/web/src/app/globals.css
index c72a9b5..df56d2a 100644
--- a/web/src/app/globals.css
+++ b/web/src/app/globals.css
@@ -405,6 +405,11 @@
padding: 18px;
}
+ .canvas-image-settings-popover .ant-popover-inner-content {
+ max-height: calc(100vh - 96px);
+ overflow-y: auto;
+ }
+
.canvas-image-settings-popover .ant-segmented {
border-radius: 999px;
padding: 3px;