feat(plugin): AI 审美批改 - 增加结构化视觉分析与精准标注 (#387)

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

* fix(web): 插件中心 - 修复应用插件筛选与自动定位

* feat(plugin): AI审美批改 - 完成分析报告与问题标注闭环
This commit is contained in:
QAyong authored and GitHub committed 2026-09-02 20:32:58 +08:00
1 parent 29f7a5c0e5
commit a6504c0e00
29 files changed
+4909 -15

No files matched your search

@@ -1,4 +1,9 @@
import { ScanSearch, Sparkles } from "lucide-react";
import { createElement } from "react";
import type { FloatingDockEntry } from "@/components/ui/aceternity/floating-dock";
import { ART_CRITIQUE_NODE_TYPE } from "@/lib/art-critique/contracts";
import { listCreatableNodeDefinitions } from "@/lib/canvas/node-registry";
import type { AddNodeMenuCommand, AddNodeMenuContext, ToolCategory, ToolContext, ToolDefinition, ToolbarId, ToolbarPrefs } from "./tool-definition";
@@ -31,6 +36,28 @@ export function getAddNodeMenuCommands(): AddNodeMenuCommand[] {
return [...addNodeMenuRegistry].sort((a, b) => a.defaultOrder - b.defaultOrder);
}
/**
* 将已注册的插件画布节点转换为添加菜单命令。
* 这部分按需生成,避免远程/延迟加载的插件必须在工具定义模块初始化前完成注册。
*/
function getPluginNodeMenuCommands(): AddNodeMenuCommand[] {
return listCreatableNodeDefinitions()
.filter((definition) => Boolean(definition.plugin))
.map((definition, index) => {
const pluginId = definition.plugin!.pluginId;
const FallbackIcon = definition.type === ART_CRITIQUE_NODE_TYPE ? ScanSearch : Sparkles;
return {
id: definition.type,
label: definition.label,
icon: definition.icon || createElement(FallbackIcon, { "aria-hidden": true }),
section: "node",
defaultOrder: 1000 + index,
applicable: (ctx: AddNodeMenuContext) => !ctx.enabledPluginIds || ctx.enabledPluginIds.has(pluginId),
run: (ctx: AddNodeMenuContext) => ctx.handlers.onAddExtensionNode(definition.type),
};
});
}
/** 默认偏好:全部工具按 defaultOrder 排列,全部可见 */
export function defaultToolbarPrefs(toolbar: ToolbarId): ToolbarPrefs {
const tools = getToolbarTools(toolbar);
@@ -66,9 +93,9 @@ export function resolveToolbarTools(toolbar: ToolbarId, ctx: ToolContext, prefs:
});
}
/** 解析添加节点菜单命令——仅 applicable 过滤,不参与排序/显隐 */
/** 解析添加节点菜单命令——合并插件节点后按 applicable 过滤并排序。 */
export function resolveAddNodeMenuCommands(ctx: AddNodeMenuContext): AddNodeMenuCommand[] {
return getAddNodeMenuCommands().filter((command) => !command.applicable || command.applicable(ctx));
return [...getAddNodeMenuCommands(), ...getPluginNodeMenuCommands()].filter((command) => !command.applicable || command.applicable(ctx)).sort((a, b) => a.defaultOrder - b.defaultOrder);
}
/**