关于 nocobase-ui-builder
用于通过 `nb` 命令行和 Flow Surfaces 编写 NocoBase 界面的 Agent 技能。它要求先经 Portal Manager 路由,并涵盖页面创建、局部编辑、校验与错误恢复。
主要功能
- 01Portal 优先的请求路由
- 02通过 Flow Surfaces 编写页面
- 03局部界面编辑
- 04聚合校验错误修复指引
- 05导航与区块类型规则
适用场景
- 01创建无代码 Portal 页面
- 02编辑现有页面界面
- 03修复未通过校验的编写载荷
MCP 相关
该技能将 `nb` 作为公开传输方式,通过 Flow Surfaces 写入界面,并规定 NocoBase 界面的编写与校验方式。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ nocobase/ skills --skill nocobase-ui-builder安装后在 Claude Code 中输入/nocobase-ui-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/ai-employee-actions.mdaliases.mdboundary-quick.mdcapabilities.mdchart-core.mdchart-validation.mdchart.mdcli-command-surface.mdcli-transport.mddashboard-routing.mdexecution-checklist.mdhelper-contracts.mdindex.mdreferences/blocks/calendar.mdchart.mdcomments.mdcreate-form.mddetails.mdedit-form.mdfilter-form.mdgrid-card.mdindex.mdkanban.mdrecord-history.mdtable.mdtree.mdreferences/js-models/index.mdjs-action.mdjs-block.md详细介绍
目标
- 面向 Agent 的写入路径是
nb api flow-surfaces <action>,并附带原始业务负载。 - 后端
flow-surfaces是创作编译器:它会规范化兼容的负载,并在硬性校验失败时返回聚合的errors[]。 - 聚合的创作
errors[]是一批完整的修复项。使用后端提供的errorCount、每条错误的path/ruleId/details和agentInstruction,在一次负载修订中修复所有列出的问题,然后重试同一写入操作。必需的 Portal 预检 中的 Portal 导航错误属于目标或实现路径故障,不是负载修复批次。 - 仅将
nb用作公共传输方式。如果缺少nb或其版本过旧,请报告受阻的命令/环境状态,而不是切换传输方式。 - 路由应以意图为先:先打开一份匹配的快速路由文档,而不是整个目录。
- 如果已有匹配的快速路由,请继续使用该路由。不要仅为重新发现文档而枚举技能目录。
- 如果任务只是部分匹配或仅需交接,请直接依据本技能的范围边界作答。不要仅为说明交接理由而检查运行时、脚本或辅助文档。
- 将跨越多个页面的单个用户请求拆分为按顺序执行的单页任务。当多个页面共享相同的
navigation.group.title时,按顺序处理:第一个页面解析标题并获取routeId;后续页面使用该routeId,绝不能仅凭标题创建;禁止并发创建仅指定标题的共享分组。 - 整页导航目标规则见 navigation-targets.md:已解析的无代码 Portal 必须使用准确的
kind: "portal",并发现routeName和navigation.portalUid;仅当capabilities.multiPortal === false时,直接指定 Admin/Mobile 布局目标才属于旧版方式;同名的重复非移动端分组必须显式指定routeId;仅指定标题的共享分组创建必须按顺序执行。
必须先进入 Portal Manager
在执行本技能中的任何其他指令之前,先为同一用户请求加载并执行 nocobase-portal-manage,并遵循其普通 UI 构建工作流。不要先启动快速路由、检查 UI Builder 导航目标或调用 flow-surfaces。
- 如果当前请求已包含 Portal Manager 的路由结果,请使用该结果,不要再次调用 Portal Manager。这可避免无代码调度回 UI Builder 后陷入循环。
- 有效结果必须且只能是以下其中一项:一个已选定且启用的 Portal,以及其准确的
name和portalType;明确证明capabilities.multiPortal === false的旧版证据;或者 Portal Manager 已验证的旧版 Flow Surfaces 特征(缺少 Portal 目标发现能力,但具备核心apply-blueprint和结构化读取能力)。随附的isDefault标记仅供展示/回读参考,不能代替选择。 portalType === "no-code":继续使用本技能,并采用已选定的 Portal 上下文。portalType === "ai":退出本技能,在 Portal Manager 的 AI Portal 源代码路径上继续处理同一请求,无需再次询问用户。如果已选记录/信息没有本地开发路径,Portal Manager 必须先拉取该 Portal。- 零个已启用 Portal、多个未选定的 Portal,或缺失/不受支持的类型,均属于 Portal Manager 的处理范围;不要在 UI Builder 中绕过这些情况。
路由
- Portal 优先边界:必须通过 Portal Manager 入口进入,这是此路由器的唯一入口。可以自动选择恰好一个已启用的 Portal,但仅凭数量或默认状态并不足以允许进入:只有当 Portal Manager 报告所选记录的
portalType恰好为no-code,或有明确证据表明capabilities.multiPortal === false时,才继续执行此处的操作。若唯一的 Portal 是 AI Portal,则退出此技能,不写入flow-surfaces,随后立即在同一请求中继续使用 Portal Manager 的源代码实现路径;如果不存在开发路径,则由 Portal Manager 先拉取 Portal。不要询问是否使用 AI Portal 或创建 no-code Portal。如果portalType缺失或不受支持,则返回 Portal Manager 解决,不要回退到 Admin。 - 整页编写通过后端
applyBlueprint、nb api flow-surfaces apply-blueprint和 整页快速指南 完成 - AI 员工 / AI 助手操作的编写应在整页或局部
flow-surfaces写入范围内完成;如果请求提及 AI 员工放置、AI 分析按钮、AI 助手或 AI 任务重新配置,请阅读 ai-employee-actions.md。仅当请求需要发现员工、匹配员工、创建员工、配置提示词 / 模型 / 技能 / 工具,或需要做出超出绑定现有可见用户名范围的生命周期决策时,才优先使用nocobase-ai-employee。 - 仪表板 / KPI / 概览路由:dashboard-routing.md
- 评论和记录历史通过公开的 Flow Surfaces 区块类型处理;如果请求提及评论、讨论串、历史记录、审计历史或变更历史,请阅读 comments.md 或 record-history.md
- 日历 / 日程 / 事件视图编写使用
CalendarBlockModel;如果请求提及 日历、calendar、排期、日程、事件视图或排班,请阅读 calendar.md - 菜单、页面入口、
routeId、pageSchemaUid、布局 / 工作区范围和重复页面身份决策请使用 导航目标。发现可见的桌面菜单时,请使用nb api resource list --resource 'desktopRoutes:listAccessible' --no-paginate -j;不要仅为查找菜单项而尝试不可用的 desktop-routes CLI 系列、menus、catalog或describe-surface。 - 对现有界面的局部编辑通过
compose、configure、update-settings、add-*、move-*和remove-*等后端操作,以及局部编辑快速指南完成 - 对现有界面进行局部反应处理时,先调用
get-reaction-meta,再通过set*Rules写入,并参考反应快速指南;首次整页反应处理应放在reaction.items[]中,不调用实时get-reaction-meta;仅生成产物的局部反应草稿应记录计划执行的get-reaction-meta探测 - 对部分匹配或仅涉及边界的请求,先使用边界快速指南
- 明确路由后,如果模板 / 参考 /
copy路由确实属于任务范围,先阅读模板快速指南,再阅读 templates.md 查看完整决策矩阵。 - 只有在准备实际的 nb 请求体时,才打开 tool-shapes.md。
- 如果任务涉及 JS
code、renderer: "js"、jsBlock、jsColumn、jsItem、JS 操作、图表或ctx.*API 问题,请先阅读 js.md,再阅读 js-surfaces/index.md,然后阅读 js-snippets/index.md,最后才阅读 js-reference-index.md。如果该意图还包括打开弹出窗口 / 抽屉 / 对话框 / 下钻视图,也请阅读 popup-openview.md:编写 JS 前,先解析出一个以模板优先且支持弹出窗口的 FlowModel。 - 每当请求载荷或 RunJS 请求体将显式编写
defaultFilter、dataScope.filter、resource.setFilter()、请求params.filter或任何{ path, operator, value }条件时,先加载nocobase-utils技能并指定主题filter,然后阅读 Filter Condition Format,并检查终端字段的实时元数据。保留宿主所需的 UI Builder 结构,但只能从终端字段的前端允许列表中选择运算符。日期比较使用$dateBefore、$dateAfter、$dateNotBefore或$dateNotAfter,绝不使用$lt、$lte、$gt或$gte。 - 在当前任务中首次使用某个
flow-surfaces操作前,如果可用,请先运行nb api flow-surfaces <action> --help。 - 此技能保留的唯一本地辅助 CLI 是
nb-template-decision。请从此仓库根目录通过node skills/nocobase-ui-builder/runtime/bin/nb-template-decision.mjs调用它,或通过指向此技能的等效绝对路径调用。不要先探测不带路径的辅助工具名称。
所需的 Portal 预检
在进行任何 flow-surfaces 修改前(包括整页写入和局部写入),都必须完成此检查:
- 获取 Mandatory Portal Manager Entry 生成的当前请求结果。如果结果缺失,返回该入口并先执行 Portal Manager,然后再在 UI Builder 中进行任何操作。
- 如果当前请求没有 Portal 解析结果,或有多个 Portal 尚未选定,则停止写入,并让请求留在
nocobase-portal-manage。 - 如果选定的 Portal 恰好有一个且已启用,则要求 Portal Manager 报告所选记录的
portalType;仅凭 Portal 只有一个,或某个 Portal 标记为isDefault,绝不足以作出判断。 - 仅当
portalType === "no-code"时,才继续使用 UI Builder。若恰好选定了一个portalType === "ai"的 Portal,则退出 UI Builder,并立即在同一构建请求中继续执行 Portal Manager 的源代码路径:定位所选 Portal 项目;如果所选记录/信息中没有开发路径,先运行nb portal pull <portal>,然后在该项目中实现并测试。原始构建请求已授权此交接;不要询问用户是选择 AI Portal 还是创建 no-code Portal,也不要仅因退出 UI Builder 就停止整个任务。若类型缺失或为其他不受支持的类型,则退出且不写入,并返回 Portal Manager 选择兼容的技能或实现路径;绝不要回退到 Admin。 - 对于已确认的 no-code Portal,要求所选 Portal 的
name非空,然后严格按照 navigation-targets.md 中的说明解析出非空的navigation.portalUid。如果映射缺失或不明确,则停止写入。 - 旧版 Admin/Mobile 布局路径要求具备
capabilities.multiPortal === false的明确证据,或 Portal Manager 验证过的旧版 Flow Surfaces 特征。仅仅能力结果缺失、为 true、失败、未授权、服务器错误或不明确,都不能作为旧版证据。 - 多 Portal 的整页创建必须包含已解析的
navigation.portalUid,省略navigation.layoutUid,并且绝不重试admin-layout-model。基于 mobile 的 no-code Portal 仍须通过navigation.portalUid进入,然后遵循后端的 mobile-root 规则。
后端的 Portal 导航错误是停止/交接信号,而不是修补整体创作载荷的理由:
navigation-portal-type-unsupported:停止对同一写入的重试,不要切换到 Admin,并交接至所选 AI Portal 的源代码路径。navigation-portal-selection-required:停止所有写入,并要求用户通过 Portal Manage 选择 Portal。navigation-portal-not-found:停止操作,并要求用户通过 Portal Manage 创建或检查所请求的 Portal。navigation-admin-layout-not-portal-target:重新运行 Portal 解析;不要修改载荷以继续写入 Admin。
必需块类型错误恢复
- 当用户要求或语义路由已选择
jsBlock时,即使出现编写错误,也要保留该部分的jsBlock类型。修复负载结构(settings.code或assets.scripts.<key>.code,以及block.script),然后重试相同的块类型。不要仅为绕过错误而将其替换为table、list、chart、actionPanel、gridCard、markdown或延后处理的说明。 - 当用户要求或语义路由已选择
chart时,即使出现编写错误,也要保留该部分的chart类型。修复负载结构(整页蓝图使用assets.charts.<key>.query、assets.charts.<key>.visual和block.chart;局部内容使用settings.query/settings.visual),然后重试相同的块类型。不要仅为绕过错误而将其替换为table、list、jsBlock、actionPanel、gridCard、markdown或延后处理的说明。 - 对于必需的
jsBlock或chart,聚合的errors[]响应意味着当前负载无效;这并不表示可以更改必需的块类型。只有当用户更改要求,或后端明确表示当前容器不支持该块类型时,才更改块类型。 - 如果经过文档所述的修复尝试后,仍无法编写必需的
jsBlock或chart,则应报告该特定部分尚未完成,并提供最新的错误证据,而不是通过回退块类型声称已完成。
硬性规则
- Required Portal Preflight 成功后,直接使用
nb api flow-surfaces <action>执行 nb 写入。仅发送一次原始业务负载;不要创建包装信封、cliBody,也不要把本地辅助程序输出作为前置条件。 - 对于常规单页请求,默认恰好使用一个真实标签页。除非用户要求,否则不要添加空标签页或占位的
markdown/ 备注 / 横幅区块。 - 默认将蓝图中的
fields[]条目设为简单字符串。仅当需要popup、target、renderer、字段专属的type,或根据实时字段description推断出明确的表单行为时,才将字段条目升级为对象。 - 页面编写时,字段事实以实时集合元数据为准。优先使用
nb api data-modeling collections get --filter-by-tk <collection> --appends fields -j;如果该命令族不可用,则使用nb api resource list --resource collections --filter '{"name":"<collection>"}' --appends fields -j。不要使用data-modeling fields list/nb api data-modeling collections fields list作为编写依据。蓝图fields[]中使用的任何字段都必须具有非空的interface。将集合字段description视为表单编写的有效输入:对任意语言使用 Agent/大模型进行语义提取,然后仅输出结构化的公开行为,可在 prepare 前将其规范化为字段元数据descriptionBehavior.{settings,linkage};明确的静态必填提示转换为字段settings.required,低风险的长度 / 范围 / 正则 / 数量约束转换为settings.rules或settings.maxCount,明确且发生于同一表单内的条件必填 / 禁用 / 隐藏提示,则转换为稳定本地表单目标上的reaction.items[],仅在需要时生成并实体化本地键;对于后端生成的新增 / 编辑弹窗,将相同行为放在目标作用域的defaults.collections.<collection>.formBehavior.addNew/edit下。当条件描述使用本地化 UI 标签 / 标题而不是字段name指代字段时(例如用状态指代status,或用重点变化指代highlights),通过实时元数据解析这些标签,并输出明确的关联规则;不要依赖后端回退解析。条件值可用时,根据实时选项的value/ 本地化label元数据进行映射。辅助文本(如settings.extra)不足以覆盖条件必填 / 禁用 / 隐藏行为;除非有真实关联规则以该字段为目标,否则不得将此类字段标记为implemented。对含糊描述,将其保留为辅助文本,不要猜测;不要依赖 NocoBase 后端解析原始描述,也不要依赖确定性关键词列表来覆盖任意语言。对于整页applyBlueprint,每次草稿都要根据实时元数据重新计算所有涉及的集合,并从头重建defaults.collections,而不是复用过期片段。对于每个涉及的直接集合,输出或允许后端生成稳定的{ name, description }形式的popups.view/popups.addNew/popups.edit描述符;即使蓝图没有明确写出addNew开启项,也要让任何table区块将该集合纳入addNew阈值评估。fieldGroups和formBehavior只能作用于目标集合;仅当场景筛选后某个固定生成的弹窗场景仍有超过 10 个有效字段时,才添加defaults.collections.<collection>.fieldGroups;否则让后端生成兼容默认值。在最终确定生成的默认fieldGroups前,执行一次简短自审并给出结论(approve或regenerate),最多使用最低可行推理 / no-think 模式重新生成一次。如果后端返回聚合字段组错误,则根据实时元数据重新生成语义分组,并重试一次。对于关联字段,在defaults.collections.<sourceCollection>.popups.associations.<associationField>.<action>下,将所有涉及的关联范围限定在同一组固定的view/addNew/edit三项中,并使用相同的{ name, description }约定;键只能取第一个关联段。不要创建按关联或关联范围划分的fieldGroups/formBehavior。绝不生成defaults.blocks,也绝不在defaults.collections.*.popups下放置blocks、fields、fieldGroups或布局。 当后端生成的新增 / 编辑候选字段具有非空description时,要为每个描述过的生成字段提供覆盖方式:使用结构化的defaults.collections.<collection>.formBehavior.addNew/edit输出,或使用同级的defaults.collections.<collection>.formBehaviorDescriptionReview.fields.<field> = { decision, reasonCode? }。仅当结构化formBehavior或适用的reaction.items[]提供了真实覆盖时,才使用decision: "implemented";否则使用decision: "noUiBehavior"或带有效reasonCode的"unsupported"。不要发送旧格式的fields: string[]、hasTried、formBehavior: {}或null作为无操作的规避手段;仅当生成候选字段的description为空时,审查条目才可为null。 layout只能放在tabs[]或内联popup上,绝不能放在区块对象上。对于createForm、editForm和details,默认省略fieldsLayout,让后端编写生成内部网格:普通字段每行两个;divider、richText和vditor字段根据实时集合元数据占用整行。对于filterForm,prepare 仍可生成紧凑的每行三个字段的fieldsLayout。只有当蓝图必须直接控制内部字段网格时,才显式使用fieldsLayout。仅当该标签页 / 弹窗最多有一个非筛选区块时,才省略页面 / 弹窗的layout;否则必须显式指定布局。当同一标签页 / 弹窗中有多个非筛选区块时,每个非模板区块都必须有标题;模板区块除外。单个非筛选区块可以省略标题,除非用户明确要求提供标题;如果提供了多余的单作用域数据区块标题,后端编写会移除保存后的区块外框标题。对于底层set-layout,不要复用公开的{ rows: [[{ key, span }]] }语法:运行时rows为Record<string, string[][]>,每个单元格数组堆叠实时子uid;[[uidA], [uidB]]表示两列,[[uidA, uidB]]表示一列堆叠。- 对于
createForm、editForm和details,当区块包含超过 10 个真实字段时,使用显式的fieldGroups,不要使用单个扁平fields[]列表。不要把手动divider项视为替代方案,也不要将fieldGroups与fieldsLayout组合使用。 - 如果点击显示的记录或关联记录应打开详情,优先使用字段弹窗。只有请求明确要求时,才使用按钮或操作列。
- 整页
navigation决策必须遵循 navigation-targets.md:同标题的重复非移动端分组必须显式指定navigation.group.routeId;移动端目标使用根导航,不带分组。非移动端页面身份由目标、菜单分组routeId和页面标题共同决定:相同分组和相同标题可以替换;不同分组、布局或 Portal 中的同标题页面不会与其他页面合并、复用或自动替换。所选无代码 Portal 必须使用其精确映射的navigation.portalUid,并省略navigation.layoutUid;忽略导航目标默认值、布局目标和后端的layoutUid值。只有在已证实的旧版路径中,才允许直接导航到 Admin/Mobile 布局。 - 在非移动端
applyBlueprint create中,任何新建的navigation.group以及任何顶层或第二层navigation.item都必须带一个有效的 Ant Design 图标名。对于移动端创建,navigation.item.icon必须带页面入口图标,且无需分组图标。 - 共享的仅标题分组创建必须串行执行:第一个非移动端页面可以通过
navigation.group.title查找 / 创建;同一目标布局中的后续页面必须使用已捕获的navigation.group.routeId。 navigation.group.routeId和桌面路由id仅是导航定位符。创建 / 初始化或成功执行整页applyBlueprint后,如需继续执行本地化操作或显式检查,应规范化为pageSchemaUid,用于页面级flow-surfaces get;对于catalog、context、get-reaction-meta、compose、configure、add*或remove*,只能使用get/describe-surface/ 创建响应返回的实时uid值。绝不要将桌面路由id作为target.uid传入。对于仅传递产物定位符的交接,保留直接的机器可读字段navigation.routeId、page.pageSchemaUid和liveTargets[].uid;尚无实时uid时,使用非空占位字符串而不是null。- 首次执行真实整页
applyBlueprint前,必须完成 Required Portal Preflight,确保用于规划的实时集合 / 页面 / 菜单元数据是最新的,然后调用nb api flow-surfaces apply-blueprint --body-file <payload>.json -j。后端会解析兼容默认值,例如排序别名、高度模式、弹窗默认值、字段组、标题字段、导航分组标题匹配、模板决策,以及省略的直接数据表面defaultFilter分组;显式无效的默认筛选器仍会返回聚合errors[]。如果后端返回聚合编写errors[],应一次性修复列出的所有问题,并重试原始负载;不要只修复第一条错误后立即再次调用applyBlueprint。上述四种 Portal 导航错误会终止此循环。 - 更新操作的字段赋值仅使用公开的
settings.assignValues。bulkUpdate是区块actions下的集合操作;updateRecord是recordActions下的记录操作。assignValues必须是一个普通对象,键为宿主集合元数据中的字段;{}有效,可清除赋值。若请求将操作描述为图标按钮 / 仅图标 / icon button,应通过设置公开的settings.icon和settings.iconOnly: true保留该视觉意图。提交 / 更新记录的工作流绑定仅使用公开的settings.triggerWorkflows或configure.changes.triggerWorkflows;每一行形如{ workflowKey, context? },[]表示清除绑定,null无效。对于这些操作设置,不要使用add-fields、原始flowModels、AssignFormGridModel、AssignFormItemModel或直接使用内部stepParams。 AI 员工操作仅使用公开的type: "aiEmployee"`` 及settings.username、settings.auto、settings.workContext、settings.tasks和settings.style;现有 AI 员工操作通过configure.changes或update-settings使用相同键重新配置。applyBlueprint/compose中的工作上下文引用可以使用target: "self"或同一运行中的区块键;本地化编辑使用self或实时 Flow Modeluid;type可省略,因为后端默认设为flow-model。任务提示词放在tasks[].message.user或别名tasks[].prompt中,不要同时使用两者。对于快捷方式,绝不要写入原始 AIprops、stepParams、flowModels` 或数据库行。 - 将后端响应视为规范化保存写入形态的权威。整页操作包括整页创建 / 替换、单个路由支持的标签页完整构建、复杂多区块页面、嵌套弹窗页面,以及包含多个反应族的页面。允许预写入读取和元数据获取,但该路由中的首次变更写入必须是后端
applyBlueprint。成功的applyBlueprint响应通常应作为停止点。仅当后续本地化操作或显式检查需要实时结构时,才执行后续get。没有额外读取结果时,应根据成功响应和用户请求意图报告写入情况,而不要声称掌握了规范化保存后的子树。 - 优先将默认值、计算值、字段 / 区块 / 操作状态以及显示 / 隐藏视为反应操作。不要猜测原始 configure 键。
- 任何 JS / RunJS 写入负载都必须保留可读的多行源码。对于
value.source: "runjs"、jsBlock/jsItem/ JS 操作、图表原始代码或任何其他code字段,编写非简单代码时,写入前必须包含实际换行符和 2 空格缩进。不要因为外围负载是 JSON,就把多条语句、本地变量初始化、条件分支或字符串拼接压缩到同一物理行;在 JSON 字符串中用\n表示换行。只有单个简短 return / 表达式,且不含初始化或分支时,才可以保持单行。 对于jsBlock,公开负载格式严格如下:新内联区块使用type: "jsBlock"和必需的settings.code/ 可选的settings.version;现有 JSBlock 的configure使用changes.code/changes.version;整页资源复用使用assets.scripts.<key>.code,区块使用script: "<key>"。绝不要创建仅含标题、依赖默认模板代码的 JSBlock。对于jsBlock,绝不要编写区块顶层code、区块顶层version、手写的stepParams或内部props/decoratorProps/flowRegistry;也绝不要将script与内联代码 / 版本组合使用。 对于打开弹窗的 JS / RunJS / 图表代码,写入代码前先使用弹窗 /openView模板优先路径。代码可以调用ctx.openView(triggerUid, ...),但triggerUid必须是现有且支持弹窗的 FlowModeluid,通常是其openView.uid的targetUid指向带有popupTemplateUid/popupTemplateMode="reference"的模板目标的弹窗宿主。默认目标绝不要使用ChildPageModel、页面、标签页、弹窗子树或临时uid。 弹窗区块 / 设置要使用的运行时值(例如表格dataScope的图表下钻筛选器)必须通过defineProperties传递,并包含meta,然后作为顶层变量读取,例如{{ctx.drilldownValue}}。不要为弹窗区块设置生成{{ctx.view.inputArgs.params.*}}。如果保存的操作只是用于这些变量的图表ctx.openView()宿主,则使用actionLinkage隐藏该宿主;不要留下依赖仅供图表使用的defineProperties的可见行操作。 - 如果实时读取结果显示存在模板引用,且请求的更改涉及模板拥有的内容,默认修改模板源。宿主 /
openView配置编辑保留在本地。页面范围措辞不表示仅限本地,因此当范围未确定时,不要自动分离为copy;写入前应先确认。对于决策产物,分别以templateOwnedContentRoute和hostOpenViewConfigRoute记录模板拥有内容的路径及宿主 /openView配置路径。 - 成功的
applyBlueprint响应若将内联弹窗开启项绑定到popup.template,这表示模板复用成功,而非结构缺失。已提交蓝图中的内联popup.blocks是模板未命中时的回退内容;如果后端选择了兼容的弹窗模板,这些内容无需保存。不要仅因规范化响应显示的是模板引用而非展开的本地弹窗区块,就移除模板复用探测、切换为replace、转换为copy或重跑整页。只有用户明确要求仅限本地的行为(例如“不要模板”、“只改当前”、copy、detach或“本地独立”)时,才强制使用内联 / 本地弹窗内容;弹窗模板的精确标志位见 template-quick.md 和 templates.md。 - 在测试或多 Agent 运行中,除非用户明确要求删除,否则不要执行破坏性清理。
- 当你确实有已保存数据的读取结果,且需要为用户或本地辅助产物撰写摘要时,优先使用一份稳定的公开摘要,其中包含规范化类型标签,如
table、details、editForm、filterForm和createForm;不要只依赖原始模型名称。对于页面级创建 / 替换,在该摘要中明确保留page.pageSchemaUid、page.pageTitle和page.menuGroupTitle。当场景跨越多个页面时,在pages.*下使用相同的规范页面身份键;对tables.*、lists.*和forms.*等具体摘要节点使用type;blockTypes仅用于root.blockTypes或popups.*.blockTypes等聚合数组。根级操作应放在root.actionTitles下,不要只用recordActionTitles作为唯一证据。 - 对于反应操作,只有在
get-reaction-meta证实目标场景中存在所需源路径后,才能选择最终区块 / 操作目标。若目标公开多种能力,应先按kind选择写入槽位,再复用与之完全匹配的能力指纹;不要复制其他kind的相近指纹。如果当前目标无法公开所需路径,应先更换目标或重构页面 / 弹窗,然后再操作;不要向不支持的宿主写入猜测的规则。 - 选择结构前先厘清筛选措辞。对于表格 / 列表 / gridCard / 日历 / 类看板数据表面,含糊的“筛选 / filter”请求默认对应同一宿主的区块级
filter操作 / 按钮,而不是单独的筛选区块。只有当请求明确要求在表格 / 列表 / gridCard / 日历 / 看板 / 卡片类宿主上添加搜索时,才将“搜索 / search”按同样方式处理,包括“支持搜索 / 带搜索 / 可搜索 / searchable”等措辞;“搜索页 / 搜索结果页 / 搜索门户 / 搜索列表页”等页面名词应保持为页面意图,而非筛选意图。“树筛选 / 树状筛选 / tree filter / tree filter block / 树形筛选区块”应直接路由到TreeBlockModel,而不是FilterFormBlockModel;写入前先阅读 references/blocks/tree.md。“分析看板 / dashboard / trend / 概览”默认路由到图表 / JSBlock 分析路径:趋势、分布、排名、百分比 / 占比和可视化分析使用图表;KPI / 指标卡 / 数字统计 / 待阅数类计数指标使用JSBlockModel;记录卡片类措辞使用GridCardBlockModel。仅在出现看板区块 / kanban / pipeline / status columns / 拖拽 / 泳道 / backlog 等看板线索时,才路由到KanbanBlockModel。单独的“看板”一词不改变分析意图。默认不要创建新的filterForm。先阅读 references/aliases.md。只有当用户明确要求筛选 / 搜索区块、表单或查询区域,且措辞并非树筛选请求时,才打开 references/blocks/filter-form.md,并在首轮蓝图中保留真实的filterForm;然后包含稳定的筛选项、submit/reset操作,以及同一蓝图中的字符串target区块键,而不是底层defaultTargetUid或原始区块设置负载。 仪表板指标硬性规则:
- 当请求表面包含 KPI / 指标卡 / 数字统计 / 统计卡 / 追踪产品数 / 待阅数 / 本周新增数 / 汇总数字时,默认使用
JSBlockModel。 - 不要使用
actionPanel+js操作实现被动指标卡。 - 不要使用
GridCardBlockModel展示聚合数值指标。 ActionPanelBlockModel仅用于用户操作、快捷方式或操作入口,除非用户明确要求将可点击操作卡片作为主要 UI。- 如果仪表板草稿将纯数字汇总内容放在
actionPanel中,写入前必须重新生成草稿。 - 如果后端返回
jsBlock编写错误,最终重试指令应修复相同的jsBlock负载(settings.code或assets.scripts + block.script),并重试该区块类型;不要将 KPI 区域切换为table、chart、actionPanel或gridCard。 - 如果后端返回图表编写错误,根据
details.repairHint修复当前图表负载,并以chart重试;不要仅为绕过错误而更改区块类型。如果错误指出内容是 KPI / 汇总数字,则将该部分重新构建为jsBlock。 - 仪表板图表门槛:当请求明确要求图表 / 图表 / Charts,或趋势 / 趋势、分布 / 分布、排名 / 排行、百分比 / 占比时,首份仪表板草稿必须为相应部分包含
type: "chart"区块。如果请求指定图表数量,则applyBlueprint前的负载必须至少包含对应数量的图表区块。 jsBlockKPI 卡片和表格 / 列表摘要均不算图表覆盖。如果草稿或读取结果中缺少必需的图表部分,应将其重新生成或修复为chart;不要将仪表板总结为已完成。- 对于要求图表的整页创建,仅
applyBlueprint成功还不够:应使用返回的pageSchemaUid运行flow-surfaces get,并确认存在图表区块证据后,才能宣称完成。 - 可使用探测页面调查元数据或负载,但它们不是最终交付物。最终交接中不要计入探测页面;如果清理安全,应移除留在用户交付菜单下的探测页面。
直接的非模板表格 / 列表 / gridCard / 日历 / 看板数据表面可以省略
defaultFilter;后端编写会根据实时集合元数据,使用最多 4 个标量 / 可筛选字段生成一个,并将其路由到同一宿主的filter操作。只有在有意覆盖这些字段时,才提供区块级defaultFilter或actions[].settings.defaultFilter。显式默认筛选器必须涵盖不超过 3 个字段,具体为 3 与集合中符合条件的直接接口字段数量两者中的较小值;显式空值、无效值、关联字段或未知路径都会通过后端聚合errors[]被拒绝。表格区块设置使用settings.pageSize、settings.sorting、settings.dataScope、settings.density、settings.showRowNumbers、settings.treeTable、settings.dragSort和settings.dragSortBy等公开键;绝不要在区块根级或settings下写入已保存 / 内部的tableSettings、defaultSorting或stepParams。对于每个直接的公开数据表面,部分actions会与该宿主的默认操作合并(filter/refresh/addNew,以及表格的bulkDelete)。普通表格recordActions会与view/edit/delete合并,但设置了settings.treeTable=true的树形集合表格不会补全view/edit/delete;除非用户明确要求,否则省略树表的recordActions,并让后端默认仅注入addChild。树表显式提供fields[]时,字段列表必须自包含:fields[0]必须是实时元数据中可直接读取的非关联字段,也可以将现有的后续可读字段移到首位;绝不要向显式字段列表中注入缺失的title/name回退字段,并拒绝不含可读直接字段的显式列表。只有省略fields[]时,才使用默认首字段元数据优先级:titleField、然后name、code、title,最后其他具有非空interface的直接字段。绝不要把id、uid、uuid、parentId、主键 / 外键、xxxId/xxxUid、_id或_uid放在首位。除非用户明确要求单独的筛选区块,否则将筛选 / 搜索意图保留在同一宿主的区块级filter操作中。 直接的非模板整页applyBlueprint看板主区块最多可显式包含 2 个卡片fields[];省略字段时会根据实时元数据生成最多 2 个合适的显示字段,显式超过数量会返回kanban-main-fields-too-many,而不是截断。相同的 applyBlueprint 路径默认设置settings.dragEnabled=true;只有存在兼容的排序字段时才发送settings.dragSortBy,否则让后端为可写的主数据源集合创建隐藏排序字段。显式设置dragEnabled=false可禁用拖动;显式提供不兼容的dragSortBy会被拒绝。
- 编写一个本地化的
compose/add-block/add-blocks/configure请求体时,直接将其发送给nb api flow-surfaces <action>。后端编写流程会在产生写入副作用之前执行兼容性规范化和严格校验。如果返回聚合errors[],应修复全部错误,而不只是第一条。 对于comments和recordHistory,仅使用公开的区块键,并在本地化添加前检查catalog。页面区块comments必须使用评论模板集合;弹窗评论必须使用resource.binding: "associatedRecords",且关联关系必须为指向评论模板集合的hasMany或belongsToMany。recordHistory区块必须使用具有真实filterTargetKey的集合;当前记录历史仅适用于单记录弹窗 / 详情场景;关联历史资源无效。绝不要编写原始CommentsBlockModel、RecordHistoryBlockModel、CommentItemModel、props、stepParams或原始 schema 来绕过这些检查。 - 如果首轮整页写入在
applyBlueprint成功后仍留下空壳filterForm,应将其视为明确的本地 / 实时缺口,并确保任何底层addBlock/addAction/addField修复范围严格受限。如果首次applyBlueprint因经核实的filterForm专属形状 / 运行时错误而失败,应根据后端聚合错误修复蓝图,并且最多进行 5 轮仅蓝图重试。成功前的这些重试中不要切换到底层写入。5 轮后仍失败时,报告最新的蓝图 / 错误证据。 - 如果创建 / 编辑表单助手或引用依赖
formValues.*,在选择宿主前检查catalog/get-reaction-meta。当该实时场景公开fields/actions/node,但不公开blocks时,应将助手建模为同一表单场景内的jsItem或其他字段类助手,而不是独立区块;对于当前的 JSItem 目标,应通过在表单值存在前渲染null来实现隐藏 / 显示,不要假设setFieldState可以针对 JSItem。成功使用这种渲染空值模式时,应在读取结果 / 证据中将其视为已配置的助手切换;不要仅因fieldLinkage无法针对 JSItem 本身,就将助手结果标记为失败。 - 包含多个工作区、筛选 / 搜索区块、嵌套弹窗或多个反应族的页面属于复杂整页请求,而不是单独的路由路径。此类请求仍应使用 whole-page-quick.md,并仍优先使用一次
applyBlueprint请求。 - 对于这些复杂整页请求,首轮蓝图生成应同时包含结构区块、内联弹窗和顶层
reaction.items[]。不要仅因页面较大,就将页面拆分为根外壳 / 弹窗 / 反应阶段。 - 仅对现有实时页面的本地化编辑,或成功执行整页
applyBlueprint后仍需严格限定范围的明确本地 / 实时缺口修复,才使用底层get-reaction-meta+set*Rules或add*修复。在整页applyBlueprint首次成功之前,不要使用createMenu、createPage、compose、configure、update-settings、add*、move*、remove*或set*Rules。如果整页applyBlueprint在首次成功前失败,应根据后端聚合错误修复蓝图,并且最多进行 5 轮仅蓝图重试。成功前的这些重试中不要切换到底层写入。5 轮后仍失败时,报告最新的蓝图 / 错误证据。 - 通用技能契约应保持环境中立。使用当前配置的 CLI 环境或显式运行时标志,而不要硬编码本地别名或固定 URL。
读取路径
- 路由不明确:references/index.md
- 根据业务意图起草、创建或替换整个页面:whole-page-quick.md
- 整个页面的导航布局、分组、路由和重复页面标识规则:navigation-targets.md
- 仪表板 / KPI / 概览路由:dashboard-routing.md
- 对本地化的现有界面进行编辑:local-edit-quick.md
- AI 员工操作的放置或任务编辑:ai-employee-actions.md
- 日历 / 日程 / 事件视图区块:calendar.md
- 评论或记录历史区块:comments.md、record-history.md
- 整个页面或局部界面的响应式变更:reaction-quick.md
- 部分匹配处理和范围有限的交接报告:boundary-quick.md
- 复用、模板选择或编辑现有模板引用:template-quick.md
- JS 或图表相关工作:js.md 或 chart.md
范围与交接
- 仅处理 Modern page(v2)的菜单 / 页面 / 标签页 / 弹窗 / 内容界面,以及其中的区块 / 字段 / 操作 / 布局 / 响应式工作;前提是已明确确认一个选定的 Portal 的
portalType === "no-code",或在已证明capabilities.multiPortal === false的旧版运行时中操作。单个 Portal 的类型未经确认或不是 no-code 时,均不在范围内。 - 在发现或修改任何导航之前,将所有尚未解决的页面 / UI 请求交给
nocobase-portal-manage。Portal Manage 只会将选定的 no-code Portal 返回给此技能。如果唯一选定的 Portal 是 AI,则退出 UI Builder,但继续通过 Portal Manage 的源项目执行原始请求,无需请求确认或提议创建 no-code Portal。缺少nb portal时,仅当能力检查明确证明multiPortal === false,才返回此处。 - 对于部分匹配或范围报告任务,将 Modern page 的处理范围控制在最小限度,并直接根据此边界列表撰写交接报告。除非请求明确涉及运行时或脚本机制,否则不要检查运行时或脚本。
- 将 ACL / 路由权限 / 角色权限交给
nocobase-acl-manage。 - 将集合 / 字段 / 关系建模交给
nocobase-data-modeling。 - 将工作流创建 / 更新 / 修订 / 执行交给
nocobase-workflow-manage。 - 将应用构建修订创建交给
nocobase-revision。
修订规则
- 在 Portal 路由、目标选择、元数据规划、预检、写入失败或验证未完成期间,不要加载
nocobase-revision。 - 只有在有意义的 UI 写入成功且完成所需验证后,才在本轮结束时加载一次
nocobase-revision。如果该技能不可用,则忽略所有修订规则要求,并且不要向用户透露任何与nocobase-revision相关的信息。 - 在
nocobase-revision确认nb revision create可用之前,不要向用户透露任何与修订相关的信息。 - 确认可用后,在本轮结束时、面向用户的最终回复之前,恰好做出一次修订决定。
- 如果创建了修订,直接说明。
- 如果已确认可用但未创建修订,说明具体原因。
评论
支持 Markdown