Skip to content

框架如何协作 ​

DragCraft 的公开入口是一个可视化工作台,但页面数据始终由无 UI 的 authoring engine 管理。理解这条边界后,你可以判断一个需求应该放进物料、字段、Designer 扩展还是宿主服务。

从一次属性修改开始 ​

在右栏修改公告文案时,实际经过以下路径:

text
业务字段组件
  -> Field adapter 归一化值
  -> FormGenerator 发出 change
  -> Designer 将 bindTo 翻译为 AuthoringAction
  -> Designer 校验并原子提交 DocumentSchema
  -> history 保存新快照
  -> Designer Presentation 读取新文档并更新画布

表单引擎不直接依赖 authoring engine,Presentation 也不能直接修改 Schema。Designer 负责把 UI 意图翻译为 action,因此字段绑定、节点动作和拖放最终共享相同的历史与校验语义。

区分五类职责 ​

模块持有什么不负责什么
Authoring EngineDocumentSchema、action、history、diagnosticsVue 组件和 DOM
Designer三栏工作台、字段绑定、扩展点组装草稿服务和生产发布
Designer Presentation设计态组件树、选择、拖拽、工具栏业务状态和生产页面
Form Generator字段状态、联动、验证、adapter 调用Schema 持久化和 action 执行
宿主应用物料、权限、仓储、发布、生产运行时绕过 AuthoringAction 修改编辑状态

公开应用只从 @dragcraft/designer 使用前四类能力的聚合接口。@dragcraft/device-frames 和 @dragcraft/fields-* 是另外两类公开 adapter;其余 workspace package 属于实现模块。

创建实例时发生什么 ​

完整活动页的组装代码如下:

ts
import type { DocumentSchema } from '@dragcraft/designer'
import { createDesigner } from '@dragcraft/designer'
import { guideMaterials } from '../domain/materials'
import { createGuideFieldComponentMap } from '../forms'
import { createGuideActionInterceptors, guideCustomActions } from './actions'
import { createGuideExtensions } from './extensions'
import { guideGlobalConfigSchema } from './global-config'
import { createGuideSchema } from './initial-schema'
import { guideMessages } from './messages'

export interface CreatePageDesignerOptions {
  initialSchema?: DocumentSchema
}

export function createPageDesigner(options: CreatePageDesignerOptions = {}) {
  const initialSchema = options.initialSchema ?? createGuideSchema()
  return createDesigner({
    schema: initialSchema,
    materials: guideMaterials,
    maxHistoryEntries: 50,
    fieldComponentMap: createGuideFieldComponentMap(),
    globalConfigSchema: guideGlobalConfigSchema,
    workspace: {
      compactBreakpoint: 1080,
      keyboardShortcuts: true,
    },
    customActions: guideCustomActions,
    actionInterceptors: createGuideActionInterceptors(),
    extensions: createGuideExtensions(),
    messages: guideMessages,
  })
}
export { createGuideSchema } from './initial-schema'

实例创建遵循固定顺序:

  1. 调用 createDesigner({ schema, materials, ... })。
  2. MaterialDefinition[] 同时提供 Schema、authoring、inspector 和 Presentation。
  3. 初始 Schema 由同一解析管线校验。
  4. 将实例传给 DcDesigner。

如果初始 Schema 使用未注册的 type,文档会进入 degraded 并保留可恢复的未知节点。createDesigner() 的配置错误(例如重复 type 或 visual 物料缺少 preview)会直接抛出 DesignerConfigurationError;它和可恢复的 Schema 诊断是两类问题。

选择扩展位置 ​

需求放置位置
改变页面业务内容物料 Vue 组件和 props
改变可编辑字段FormSchema 与字段 adapter
改变页面结构所有权Layout 或 ContainerDefinition
写入页面 Schema字段绑定或 designer.execute(action)
增加确认、权限和审计actionInterceptors 与宿主服务
改变工作台视觉主题 token、公开 data hook 或 Presentation 扩展
保存和发布页面宿主仓储、校验与发布流程

组件内部的持久化修改通过受控 Authoring Action 执行,不应以本地 DOM 状态模拟应该持久化的页面状态。

不受支持的路径 ​

  • 直接修改 designer.document 或冻结快照。
  • 从公开应用导入内部 package,绕过 Designer 聚合入口。
  • 把设计态 DcDesigner 当成生产页面运行时。
  • 依赖私有 .dc-* class 修改交互结构。
  • 绕过 designer.execute() 直接写入 Schema。

需要继续理解数据时,阅读 Schema 与样式作用域;需要理解写入保证时,阅读 状态、动作、历史与事件。