fix: restore list mode entry in text composer

This commit is contained in:
Codex
2026-09-19 20:25:53 +08:00
parent 3f5b0bd347
commit 5843d489c6
2 changed files with 54 additions and 14 deletions

View File

@@ -1,7 +1,7 @@
import { Button, Image as AntImage, InputNumber, Modal, Popover } from "antd";
import { Tooltip } from "@/components/ui/base/tooltip";
import { useEffect, useMemo, useRef, useState, type CSSProperties, type KeyboardEvent as ReactKeyboardEvent, type PointerEvent as ReactPointerEvent, type ReactNode } from "react";
import { ArrowLeftRight, ArrowUp, AtSign, Boxes, Camera, ChevronDown, FileText, GripVertical, ImageIcon, ImagePlus, Link2, LoaderCircle, Maximize2, Music2, Pencil, SlidersHorizontal, UserRound, Video, WandSparkles, X } from "lucide-react";
import { ArrowLeftRight, ArrowUp, AtSign, Boxes, Camera, ChevronDown, FileText, GripVertical, ImageIcon, ImagePlus, LayoutList, Link2, LoaderCircle, Maximize2, Music2, Pencil, SlidersHorizontal, UserRound, Video, WandSparkles, X } from "lucide-react";
import { ModelPicker } from "@/components/model-picker";
import { defaultConfig, modelOptionName, resolveModelChannel, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
@@ -51,6 +51,7 @@ type CanvasNodePromptPanelProps = {
onNodeMouseDown?: (event: ReactPointerEvent, nodeId: string) => void;
onImageSettingsOpenChange?: (open: boolean) => void;
workspaceMode?: CanvasWorkspaceMode;
onListGenerate?: (nodeId: string, prompt: string) => void;
};
type CanvasTheme = (typeof canvasThemes)[keyof typeof canvasThemes];
@@ -69,7 +70,7 @@ const PROMPT_EDITOR_MODAL_WIDTH = "min(1200px, 92vw)";
const PROMPT_EDITOR_MODAL_DEFAULT_WIDTH = 1200;
const PROMPT_EDITOR_MODAL_DEFAULT_HEIGHT = 420;
export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChange, onConfigChange, onGenerate, mentionReferences = [], onAddReference, onRemoveReference, onReorderReferences, onReplaceReference, onReplaceReferenceFiles, onClose, onNodeMouseDown, onImageSettingsOpenChange, workspaceMode = "professional" }: CanvasNodePromptPanelProps) {
export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChange, onConfigChange, onGenerate, mentionReferences = [], onAddReference, onRemoveReference, onReorderReferences, onReplaceReference, onReplaceReferenceFiles, onClose, onNodeMouseDown, onImageSettingsOpenChange, workspaceMode = "professional", onListGenerate }: CanvasNodePromptPanelProps) {
const globalConfig = useEffectiveConfig();
const themeName = useActiveTheme();
const theme = canvasThemes[themeName];
@@ -256,7 +257,8 @@ export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChan
const submit = () => {
const text = prompt.trim();
if (!text || isRunning) return false;
onGenerate(node.id, mode, text);
if (mode === "text" && node.metadata?.listMode && onListGenerate) onListGenerate(node.id, text);
else onGenerate(node.id, mode, text);
return true;
};
@@ -411,17 +413,35 @@ export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChan
compact={!expanded}
/>
{mode === "text" ? (
<Tooltip title={`文本生成份数(默认 1,可在生成配置中调整)`}>
<InputNumber
size="small"
min={1}
max={15}
value={Math.max(1, Math.min(15, Math.floor(Math.abs(Number(node.metadata?.textCount) || 1))))}
onChange={(value) => onConfigChange(node.id, { textCount: Math.max(1, Math.min(15, Math.floor(Math.abs(Number(value)) || 1))) })}
aria-label="文本生成份数"
className="!w-14 !h-7 [&_.ant-input-number-input]:!text-[var(--fs-tiny)]"
/>
</Tooltip>
<>
<div className="flex h-7 items-center overflow-hidden rounded-md border" style={{ borderColor: theme.node.stroke }}>
<button type="button" onClick={() => onConfigChange(node.id, { listMode: false })} className={`flex h-full items-center gap-1 px-2 text-[var(--fs-tiny)] transition-colors ${!node.metadata?.listMode ? "font-medium" : ""}`} style={!node.metadata?.listMode ? { background: theme.accent.primary, color: "#fff" } : { color: theme.node.muted }}>
<FileText className="size-3" />
文本
</button>
<button type="button" onClick={() => onConfigChange(node.id, { listMode: true })} className={`flex h-full items-center gap-1 px-2 text-[var(--fs-tiny)] transition-colors ${node.metadata?.listMode ? "font-medium" : ""}`} style={node.metadata?.listMode ? { background: theme.accent.primary, color: "#fff" } : { color: theme.node.muted }}>
<LayoutList className="size-3" />
列表
</button>
</div>
{!node.metadata?.listMode ? (
<Tooltip title={`文本生成份数(默认 1,可在生成配置中调整)`}>
<InputNumber
size="small"
min={1}
max={15}
value={Math.max(1, Math.min(15, Math.floor(Math.abs(Number(node.metadata?.textCount) || 1))))}
onChange={(value) =>
onConfigChange(node.id, {
textCount: Math.max(1, Math.min(15, Math.floor(Math.abs(Number(value) || 1)))),
})
}
aria-label="文本生成份数"
className="!w-14 !h-7 [&_.ant-input-number-input]:!text-[var(--fs-tiny)]"
/>
</Tooltip>
) : <span className="text-[10px]" style={{ color: theme.node.muted }}>行数和列结构由模型判断</span>}
</>
) : mode === "image" ? (
// 图片模式下,显示相机配置与镜头配置
<>

View File

@@ -60,6 +60,7 @@ import { CanvasPanoramaConfigModal } from "@/components/canvas/canvas-panorama-c
import { InfiniteCanvas } from "@/components/canvas/infinite-canvas";
import { Minimap } from "@/components/canvas/canvas-mini-map";
import { CanvasNodePromptPanel, type CanvasNodeGenerationMode } from "@/components/canvas/canvas-node-prompt-panel";
import { handleListGenerate } from "./list-mode-generator";
import { CanvasToolbar } from "@/components/canvas/canvas-toolbar";
import { useCanvasCreateCommands } from "@/components/canvas/use-canvas-create-commands";
import { AssetPickerModal } from "@/components/canvas/asset-picker-modal";
@@ -2118,11 +2119,26 @@ function InfiniteCanvasPage() {
setNodeImageSettingsOpen(open);
if (open) setToolbarNodeId(null);
}}
onListGenerate={(nodeId, listPrompt) => {
void handleListGenerate({
sourceNodeId: nodeId,
prompt: listPrompt,
nodes: nodesRef.current,
connections: connectionsRef.current,
config: effectiveConfig,
projectId,
setNodes,
setConnections,
setRunningNodeId,
setDialogNodeId,
});
}}
/>
);
},
[
configInputsById,
effectiveConfig,
handleConfigNodeChange,
handleGenerateNode,
handleNodePromptChange,
@@ -2134,6 +2150,10 @@ function InfiniteCanvasPage() {
message,
projectId,
runningNodeId,
setConnections,
setDialogNodeId,
setNodes,
setRunningNodeId,
skillMentionReferences,
workspaceMode,
],