feat(portrait-clearance): 肖像排查 - 增加画布插件与本机检测链路

This commit is contained in:
QAyong
2026-08-26 15:23:01 +08:00
committed by ddCat
parent 86fc3fda2f
commit 9bc5512140
54 changed files with 6832 additions and 60 deletions

View File

@@ -78,5 +78,14 @@ export function isolateCopiedNodeMetadata(node: CanvasNodeData, idMap: ReadonlyM
visibleColumns: [...node.metadata.storyboard.visibleColumns],
referenceNodeIds: remapReferenceIds(node.metadata.storyboard.referenceNodeIds, idMap) || [],
} : undefined;
if (node.type === "portrait-clearance" && metadata.portraitClearance) {
metadata.portraitClearance = {
...metadata.portraitClearance,
inputBindings: metadata.portraitClearance.inputBindings.map((binding) => ({ ...binding, nodeId: idMap.get(binding.nodeId) || binding.nodeId })),
activeTaskId: undefined,
task: undefined,
lastResult: undefined,
};
}
return metadata;
}

View File

@@ -41,6 +41,8 @@ export type CanvasNodeDefinition = {
resourceKind?: (node: CanvasNodeData) => CanvasResourceKind | null;
/** 作为生成节点时的生成模式;不设表示该类型不产生生成行为 */
generationMode?: (node: CanvasNodeData) => CanvasGenerationMode | null;
/** 是否显示右侧输出连接点;缺省为 true,消费型终点节点可关闭。 */
showOutputConnection?: boolean;
/**
* 作为上游输入被参考素材容量校验计数时的类别;
* 不设表示不参与计数(生成配置、背板)。与 resourceKind 不同,计数不看内容。

View File

@@ -2,6 +2,8 @@ import { Clapperboard, Folder, FolderOpen, Image as ImageIcon, Layers3, Music2,
import { getNodeIcon, getNodeLabel } from "@/lib/canvas/node-registry";
import { registerAddNodeMenuCommands, type AddNodeMenuCommand } from "@/lib/canvas/tool-registry";
import { PortraitClearanceIcon } from "@/components/canvas/portrait-clearance/portrait-clearance-icon";
import { PORTRAIT_CLEARANCE_NODE_TYPE, PORTRAIT_CLEARANCE_PLUGIN_ID } from "@/lib/portrait-clearance/contracts";
import { CanvasNodeType, type CanvasNodeTypeId } from "@/types/canvas";
/** 真正创建节点的命令,文案与图标统一取自节点注册表。 */
@@ -41,6 +43,15 @@ export const addNodeMenuCommands: AddNodeMenuCommand[] = [
extensionCommand(CanvasNodeType.ColorGrade, 70),
// 云端和本地工作流共用独立配置节点,不进入基础模型节点的渠道选择。
{ id: "workflow", label: "工作流", icon: <Workflow />, section: "workflow", defaultOrder: 10, applicable: (ctx) => ctx.workspaceMode !== "simple", run: (ctx) => ctx.handlers.onAddWorkflow() },
{
id: PORTRAIT_CLEARANCE_NODE_TYPE,
label: getNodeLabel(PORTRAIT_CLEARANCE_NODE_TYPE),
icon: <PortraitClearanceIcon />,
section: "extension",
defaultOrder: 80,
applicable: (ctx) => Boolean(ctx.enabledPluginIds?.has(PORTRAIT_CLEARANCE_PLUGIN_ID)),
run: (ctx) => ctx.handlers.onAddExtensionNode(PORTRAIT_CLEARANCE_NODE_TYPE),
},
// 导入资源
{ id: "upload", label: "上传文件", icon: <UploadCloud />, section: "resource", defaultOrder: 10, run: (ctx) => ctx.handlers.onUpload() },
{ id: "project-character", label: "添加角色卡", icon: <UserRound />, section: "resource", defaultOrder: 20, applicable: (ctx) => ctx.isProjectLinked, run: (ctx) => ctx.handlers.onOpenProjectCharacters() },

View File

@@ -132,6 +132,8 @@ export type ToolContext = {
export type AddNodeMenuContext = {
workspaceMode: CanvasWorkspaceMode;
isProjectLinked: boolean;
/** 内置应用插件的启用状态;未声明时视为未提供 gating 信息。 */
enabledPluginIds?: ReadonlySet<string>;
handlers: Pick<ToolbarHandlers,
| "onAddText"
| "onAddImage"