Skip to content

动作与业务策略

当操作需要业务规则时,节点动作应返回命令,让 Core 继续负责校验、历史和 Schema 事件。贯穿示例为公告增加“设为精选”,并在删除前走确认拦截器:

ts
customActions: [{
  key: 'feature-notice',
  label: '设为精选',
  type: 'button',
  order: 500,
  visible: ctx => ctx.node.type === 'notice',
  disabled: ctx => ctx.node.props.featured === true,
  command: ctx => ({
    type: CommandType.UPDATE_PROPS,
    payload: { nodeId: ctx.node.id, props: { featured: true } },
  }),
}],
actionInterceptors: [
  createConfirmActionInterceptor({
    confirm: ({ title, message }) => typeof window === 'undefined'
      ? true
      // eslint-disable-next-line no-alert -- The tutorial uses the browser fallback in place of a host dialog.
      : window.confirm(message ?? title ?? '确认执行此操作?'),
    title: '确认删除',
    message: '删除后可以通过撤销恢复。',
  }),
],

command 适合写 Schema,handler 适合跳转、打开宿主弹窗或埋点。actionInterceptors 包裹内置和自定义动作,适合确认、权限和错误上报。eventHooks 则用于选择、拖拽和 hover 的交互通知。

需求入口
新增、覆盖或限制工具栏操作customActionsmeta.actions
确认、鉴权和审计actionInterceptors
监听选择、拖拽和 hovereventHooks
框架负责宿主负责
动作管线、内置 command、历史和交互事件权限、确认 UI、审计、错误提示和服务端授权

框架不会替宿主显示拦截器返回的业务原因,也不会替你实现权限策略。不要把任意自定义 command 当作标准 Designer 扩展;优先使用内置 command 或字段绑定。

Schema 托管物料

固定由页面模板、Schema import 或 migration 提供,但仍要在工作台中渲染、选中和配置的物料,使用 authoring: 'schema-managed'。它是设计态操作策略,不是对宿主代码或服务端的安全隔离。

先和普通物料一样注册 metadata 与组件:

ts
export const pageHeaderWidgetDefinition: WidgetDefinition<DesignerWidgetMeta> = {
  meta: {
    type: 'page-header',
    title: '活动页头',
    group: 'chrome',
    authoring: 'schema-managed',
    defaultProps: { title: '夏日活动页' },
    defaultLayout: {
      placement: {
        kind: 'chrome',
        edge: 'block-start',
        position: 'sticky',
        reserve: { mode: 'size', size: 48 },
      },
    },
    formSchema: {
      sections: [{
        title: '页头内容',
        fields: [{ key: 'title', label: '标题', component: 'Input' }],
      }],
    },
  },
  component: GuidePageHeaderWidget,
}

然后由 Schema producer 显式提供节点。defaultLayout 只用于创建节点;既有或初始节点仍须把自己的 layout 写入 Schema:

ts
{
  id: 'page-header-1',
  type: 'page-header',
  props: { title: '夏日活动页' },
  layout: {
    placement: {
      kind: 'chrome',
      edge: 'block-start',
      position: 'sticky',
      reserve: { mode: 'size', size: 48 },
    },
  },
},
能力默认值显式 override
标准物料面板、ADD_NODE、duplicate隐藏或拒绝不可开放
选中允许selectable
propsstyle允许configurable
容器 variant拒绝variantChangeable
拖拽、上移、下移拒绝draggable: true
sibling 下标锁不启用sortable: false
删除拒绝deletable: true

creatable: true 和同 key 的 duplicate extra action 都不会解除创建与复制禁令;注册时只会给出 warning。新增、复制与容器变体迁移会检查整棵候选子树;删除普通父节点也要求其所有 Schema 托管后代都允许删除。

这些 override 可以写成布尔值,或接收只读 nodeschema 的 predicate。predicate 抛错或返回非法值时会 fail closed,命令、历史和成功事件都不会提交。configurable 只控制 propsstylevariantChangeable 独立控制 container.variant;被拒绝的属性字段仍显示当前值但处于 disabled。移动限制只检查 MOVE_NODE 的直接 source,因此普通父容器可以携带 Schema 托管后代移动,其他 sibling 的被动下标变化也不会被拦截。

默认保留内置工具栏动作并全部显示为 disabled。Authoring Policy 未授权或因当前位置、容器约束暂不可用的内置动作都会保留并显示 disabled,使工具栏保持稳定。draggable: true 会启用拖拽和上下移动,deletable: true 会启用删除;actions.onlyactions.exclude 或 action 自身的 visible 才会改变显隐。全局 custom action 需要被 actions.only 点名,物料自己的 actions.extra 视为显式授权。duplicate 无法重新开放。显式显隐配置后的最终 action 列表为空时,节点不会渲染工具栏。

importSchema()、注册的 migration 和 custom command 是可信宿主入口,不受该策略的隔离承诺;Undo/redo 恢复已提交的快照时也不会重新裁决策略。精确公开接口见 Schema 与命令

完成检查:公告动作只能在允许的节点出现;删除时会先经过宿主确认,并且取消不会写入 Schema。

下一步:面板与画布;精确字段见 Designer 渲染与容器