ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

NocoBase 插件开发指南:基于 ActionModel 与 ActionSceneEnum 实现自定义操作按钮

NocoBase 插件开发指南:基于 ActionModel 与 ActionSceneEnum 实现自定义操作按钮 NocoBase 插件开发指南基于 ActionModel 与 ActionSceneEnum 实现自定义操作按钮【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase导读本文围绕 NocoBase 的「操作扩展」机制展开讲解如何通过继承ActionModel基类、声明static scene操作场景并在插件的load()生命周期中用registerModelLoaders注册自定义操作按钮。读完本文你将掌握数据表级collection、记录级record与通用both三种操作按钮的完整开发流程理解按钮渲染、点击事件监听与配置面板的底层实现原理能够直接在 NocoBase 插件中产出可复用的自定义操作扩展。一、操作Action扩展是什么在 NocoBase 中操作Action是区块里的按钮用于触发业务逻辑——比如「新建」「编辑」「删除」「刷新」等。界面上的这些按钮并不是写死在某个组件里的而是通过 FlowEngine 统一管理渲染、配置面板与配置持久化。对于插件开发者而言要添加一个自定义操作按钮只需继承ActionModel基类位于 packages/core/client-v2/src/flow/models/base/ActionModel.tsx基类实现见 ActionModelCore.tsx再配合ActionSceneEnum声明按钮出现的场景即可。ActionModel是 FlowEngine 提供的多个 FlowModel 基类之一其余基类包括BlockModel、DataBlockModel、CollectionBlockModel、TableBlockModel、FieldModel等做操作按钮统一用ActionModel详见 FlowEngine 概述。二、操作场景ActionSceneEnum 详解每个操作都需要声明它出现的场景通过static scene属性指定场景值说明collectionActionSceneEnum.collection作用于数据表出现在区块顶部的操作栏比如「新建」按钮recordActionSceneEnum.record作用于单条记录出现在表格每行的操作列比如「编辑」「删除」按钮bothActionSceneEnum.both两种场景都可用allActionSceneEnum.all所有场景都可用包括特殊上下文如弹窗等从源码看场景的实现原理在 ActionModelCore.tsx 中可以看到ActionSceneEnum的真实定义export type ActionSceneType collection | record | ActionSceneType[]; export const ActionSceneEnum { collection: collection as ActionSceneType, record: record as ActionSceneType, all: [collection, record] as ActionSceneType, both: [collection, record] as ActionSceneType, };几个值得注意的实现细节ActionSceneType既可以是单个字符串collection | record也可以是字符串数组因此场景是支持组合的both与all在数值上是完全等价的都等于[collection, record]数组区别在于语义约定both面向「数据表 记录」两种常规场景all还涵盖弹窗等特殊上下文就源码而言二者取值一致场景的匹配逻辑由静态方法_isScene完成ActionModelCore.tsx内部先把scene用_.castArray统一转为数组再includes判断。场景筛选在「添加操作」菜单中如何生效看两个内置基类的实现CollectionActionModel.tsx 的define({ children })会构建全部 Action 子项然后filter(item M._isScene(ActionSceneEnum.collection))只保留作用于数据表的操作RecordActionModel.tsx 同理只保留_isScene(ActionSceneEnum.record)为真的操作。也就是说你在插件里声明什么场景系统在生成「配置操作」菜单时就会自动把它归入对应的操作分组这正是static scene起作用的底层链路。三、三种场景的操作模型写法操作模型的核心结构完全一致区别只在于static scene的值和defaultProps里的按钮文案。1. 数据表级操作collection作用于整个数据表出现在区块顶部的操作栏// models/SimpleCollectionActionModel.tsx import { ActionModel, ActionSceneEnum } from nocobase/client-v2; import { ButtonProps } from antd; import { tExpr } from nocobase/flow-engine; export class SimpleCollectionActionModel extends ActionModel { static scene ActionSceneEnum.collection; defaultProps: ButtonProps { children: tExpr(Simple collection action), }; } SimpleCollectionActionModel.define({ label: tExpr(Simple collection action), });2. 记录级操作record作用于单条记录出现在表格每行的操作列// models/SimpleRecordActionModel.tsx import { ActionModel, ActionSceneEnum } from nocobase/client-v2; import { ButtonProps } from antd; import { tExpr } from nocobase/flow-engine; export class SimpleRecordActionModel extends ActionModel { static scene ActionSceneEnum.record; defaultProps: ButtonProps { children: tExpr(Simple record action), }; } SimpleRecordActionModel.define({ label: tExpr(Simple record action), });3. 两种场景都适用both如果操作不区分场景用ActionSceneEnum.both// models/SimpleBothActionModel.tsx import { ActionModel, ActionSceneEnum } from nocobase/client-v2; import { ButtonProps } from antd; import { tExpr } from nocobase/flow-engine; export class SimpleBothActionModel extends ActionModel { static scene ActionSceneEnum.both; defaultProps: ButtonProps { children: tExpr(Simple both action), }; } SimpleBothActionModel.define({ label: tExpr(Simple both action), });三种写法的结构是一样的——区别只在static scene的值和defaultProps里的按钮文案。几个关键点的源码佐证defaultProps的类型在 ActionModelCore.tsx 中声明为props: ButtonProps { tooltip?: string; iconOnly?: boolean }即直接透传 Ant DesignButton的 props所以你可以像配置 antd 按钮一样设置type、icon、danger等属性基类默认提供了type: default、title: tExpr(Action)、iconOnly: false作为兜底。define()的作用给模型设置元数据在「添加操作」菜单中的显示名等define()在模块加载时就会执行此时 i18n 尚未初始化所以 label 必须用tExpr()做延迟翻译。onClick与事件派发ActionModelCore.tsx 中onClick会调用this.dispatchEvent(click, { event, ...this.getInputArgs() }, { debounce: true })即点击事件通过 FlowEngine 事件系统派发并自动附带getInputArgs()计算出的输入参数如关联数据的sourceId、记录主键filterByTk供事件处理器使用。四、用 registerFlow 给按钮添加点击行为光有按钮还不行你通常需要让它「点了有反应」。通过registerFlow({ on: click })可以给操作模型监听点击事件在steps的handler(ctx)里编写业务逻辑// 在 SimpleCollectionActionModel.tsx 中追加 SimpleCollectionActionModel.registerFlow({ key: clickFlow, title: tExpr(Simple collection action), on: click, steps: { showMessage: { async handler(ctx) { ctx.message.success(ctx.t(Collection action clicked)); }, }, }, });记录级操作如何拿到当前行数据记录级操作比较特殊——你需要知道用户点了哪一行。在 handler 中通过ctx.model.context可以拿到当前行的数据和索引SimpleRecordActionModel.registerFlow({ key: clickFlow, title: tExpr(Simple record action), on: click, steps: { showMessage: { async handler(ctx) { const index ctx.model.context.recordIndex; const record ctx.model.context.record; const id record?.id; ctx.message.info(ctx.t(Record action clicked, record ID: {{id}}, row index: {{index}}, { id, index })); }, }, }, });ctx.model.context中的record是当前行的数据对象recordIndex是当前行在表格中的索引这两个字段由表格区块在渲染操作列时注入。点击事件的底层实现on: click之所以可用是因为ActionModel在基类中通过registerEvents预注册了click事件见 ActionModel.tsx事件携带一个可选的「触发条件」Trigger condition基于ConditionBuilder组件并绑定commonConditionHandler。也就是说所有 ActionModel 都天然具备 click 事件你只需用 registerFlow 订阅即可无需自己挂 DOM 事件。五、在插件中注册操作操作模型写好后需要在 Plugin 的load()中用registerModelLoaders按需加载注册// plugin.tsx import { Plugin } from nocobase/client-v2; export class PluginSimpleActionClient extends Plugin { async load() { this.flowEngine.registerModelLoaders({ SimpleCollectionActionModel: { loader: () import(./models/SimpleCollectionActionModel), }, SimpleRecordActionModel: { loader: () import(./models/SimpleRecordActionModel), }, SimpleBothActionModel: { loader: () import(./models/SimpleBothActionModel), }, }); } } export default PluginSimpleActionClient;这里loader使用动态import()实现按需加载——只有首次在界面上用到该模型时才真正加载对应模块避免插件启动时加载全部代码。关于 Plugin 的load()生命周期详见 Plugin 插件。注册完成后在区块的「配置操作」中就能添加你的自定义操作按钮了。启用插件使用yarn pm enable例如yarn pm enable nocobase-example/plugin-simple-action或你自己创建的my-project/plugin-simple-action。六、多语言与 tExpr 延迟翻译define()、registerFlow()都在模块加载阶段执行此时 i18n 尚未初始化所以所有面向用户的文案都必须用tExpr()包装。翻译文件放在插件src/locale/目录下// src/locale/zh-CN.json { Simple collection action: 简单数据表操作, Simple record action: 简单记录操作, Simple both action: 简单通用操作, Collection action clicked: 数据表操作被点击了, Record action clicked, record ID: {{id}}, row index: {{index}}: 记录操作被点击了记录 ID{{id}}行索引{{index}}, Both action clicked: 通用操作被点击了 }// src/locale/en-US.json { Simple collection action: Simple collection action, Simple record action: Simple record action, Simple both action: Simple both action, Collection action clicked: Collection action clicked, Record action clicked, record ID: {{id}}, row index: {{index}}: Record action clicked, record ID: {{id}}, row index: {{index}}, Both action clicked: Both action clicked }注意初次添加语言文件需要重启应用才能生效。{{id}}、{{index}}是 i18next 的插值语法对应ctx.t()传入的参数对象。翻译文件写法与tExpr()的更多用法见 i18n 国际化。七、按钮配置面板ActionModel 内置的 buttonSettings在「配置操作」中点击已添加的按钮会弹出配置面板这个面板也是 Flow 驱动的——ActionModel在模块加载时通过registerFlow注册了内置的buttonSettingsFlow见 ActionModel.tsxsort: -999保证它排在最前。它提供的配置项与每个配置项是否可编辑都由模型属性控制配置项组件是否可编辑模型属性按钮标题Button titleInputenableEditTitle默认 true提示气泡Button tooltipInputenableEditTooltip默认 true图标Button iconIconPickerenableEditIcon默认 true仅图标Icon onlySwitchenableEditIcon enableEditIconOnly ! false按钮类型Button typeRadio.GroupenableEditType默认 true危险操作Danger actionSwitchenableEditDanger默认 true颜色ColorColorPickerenableEditColor默认false按钮类型buttonTypeOptions支持五种取值default、primary、dashed、link、text与 antd Button 的type一一对应。这意味着你的自定义操作模型默认就继承了完整的按钮样式配置能力。如果你希望某个操作不允许用户改标题只需在子类中设置enableEditTitle false即可无需重写整个配置面板。另外基类还注册了buttonAclSettingsACL 权限校验与paginationChange分页切换后重新计算 ACL 与联动规则两个内置 Flow见 ActionModel.tsx。八、define() 参数说明FlowModel.define()用于设置模型的元数据控制它在菜单中的显示方式。插件开发中最常用的是label此外还支持参数类型说明labelstring \| ReactNode在「添加区块 / 字段 / 操作」菜单中的显示名支持tExpr()延迟翻译iconReactNode菜单中的图标sortnumber排序权重数字越小越靠前默认0hideboolean \| (ctx) boolean是否在菜单中隐藏支持动态判断groupstring分组标识用于归类到特定菜单分组childrenSubModelItem[] \| (ctx) SubModelItem[]子菜单项支持异步函数动态构建toggleableboolean \| (model) boolean是否支持切换行为同一父级下唯一searchableboolean子菜单是否启用搜索大多数插件只需要设置labelMyActionModel.define({ label: tExpr(My action), });如需控制排序或条件隐藏MyActionModel.define({ label: tExpr(My action), sort: 10, // 排在后面 hide: (ctx) !ctx.someCondition, // 条件隐藏 });children的典型用法正是场景筛选——上面提到的CollectionActionModel、RecordActionModel就是通过define({ children: async (ctx) ... })动态构建并过滤子菜单的这是场景机制与define()协作的完整范例。九、内置操作模型一览仓库中packages/core/client-v2/src/flow/models/actions/目录下已有大量内置操作模型可供参考它们是学习ActionModel用法的最佳范本模型文件对应操作AddNewActionModel.tsx新建EditActionModel.tsx编辑DeleteActionModel.tsx删除BulkDeleteActionModel.tsx批量删除ViewActionModel.tsx查看LinkActionModel.tsx链接跳转RefreshActionModel.tsx刷新ExpandCollapseActionModel.tsx展开 / 收起AssociateActionModel.tsx/DisassociateActionModel.tsx关联 / 解除关联PopupCollectionActionModel.tsx弹窗数据表操作JSCollectionActionModel.tsx/JSRecordActionModel.tsx/JSItemActionModel.tsxJS 脚本类操作UpdateRecordActionModel.tsx更新记录从这些文件可以看到内置操作是如何组合使用static scene、defaultProps、registerFlow与define()的照着它们的模式写自定义操作是最稳妥的路径。十、完整源码与延伸阅读完整示例插件仓库中packages/plugins/nocobase-example/下提供了三种操作场景的完整示例实现可直接作为脚手架参考从零实战插件实战做一个自定义操作按钮 — 从创建插件骨架到启用插件的完整五步走前后端联动插件实战做一个前后端联动的数据管理插件 — 自定义操作 ctx.viewer.dialog在完整插件中的实际应用FlowEngine 基础FlowEngine 概述 — FlowModel 基础用法与基类选择扩展兄弟篇区块扩展、字段扩展Flow 完整参考FlowDefinition 流定义 —registerFlow的完整参数和事件类型FlowEngine 完整文档 — FlowModel、Flow、Context 的完整参考组件 vs FlowModelComponent vs FlowModel — 什么场景下才需要用 FlowModel 包装你的组件。小结自定义操作扩展的核心路径可以浓缩为四步继承ActionModel并声明static scene→ 用defaultProps定义按钮外观 → 用registerFlow({ on: click })定义点击行为 → 在 Plugin 的load()中通过registerModelLoaders注册。场景声明决定了按钮出现在「配置操作」菜单的哪个分组而 FlowEngine 会在渲染、配置面板与配置持久化三个层面接管按钮的完整生命周期——这正是 NocoBase 操作扩展「少写代码、可配置、可复用」的底层原因。【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表