diff --git a/docs/api/editor/props.md b/docs/api/editor/props.md index 6cc48c27..ea3ce73a 100644 --- a/docs/api/editor/props.md +++ b/docs/api/editor/props.md @@ -1558,52 +1558,71 @@ const onLayerNodeDblclick = (event, data) => { - 返回 `false` 时,会同时阻断默认的"展开/收起"行为以及向上抛出的 [`layer-node-dblclick`](./events.md#layer-node-dblclick) 事件;返回其他值则继续触发默认行为并抛出事件。 ::: -## extendFormState +## 表单业务上下文 - **详情:** - - 扩展表单状态 - 用于在属性表单中注入自定义的状态数据,这些数据可以在表单配置的各个字段为函数时的第一个参数中获取 + 编辑器会把 `services` 与当前 `stage` 通过 `FORM_CONTEXT_KEY` provide 下去,编辑器内所有 `MForm`(属性面板、历史差异对比表单、侧边栏、以及 Link / FormBox 里的嵌套子表单)都自动继承。 -- **默认值:** `undefined` - -- **类型:** `(state: FormState) => Record | Promise>` - -- **示例:** + 业务方要往里追加自己的字段,在 `` 外层再 provide 一层即可,同名字段覆盖内置的: ```html ``` -:::tip -扩展的状态可以在表单配置中通过 `state` 访问,例如: + 补类型用模块增强: + +```ts +declare module '@tmagic/form-schema' { + interface FormContext { + currentUser?: { name: string; role: string }; + } +} +``` + + 表单配置里统一从第一个参数 `mForm` 读:formState 是读穿 Proxy,`mForm` 上没有的字段自动落到 context,所以回调签名不变,后端下发的存量配置无需改动。 ```js { name: 'title', text: '标题', - // 根据扩展的状态动态设置 - disabled: (state) => state.currentUser.role !== 'admin', + disabled: (mForm) => mForm.currentUser?.role !== 'admin', + display: (mForm) => mForm.env === 'prod', } ``` + +::: warning 从 extendFormState 迁移 +`extendFormState` prop 已移除,同时移除的还有 `PropsPanel` / `FormPanel` / `HistoryDiffDialog` / `CompareForm` / `ViewForm` 的 `extendState`、`CompareForm` 的 `baseFormState`、`useHistoryRevert` 的 `extendState` 与 `getPropsPanelFormState`。 + +改法是把「返回数据的函数」换成「数据本身」: + +```ts +// before +const extendFormState = (state) => ({ env: store.env }); +// + +// after +provide(FORM_CONTEXT_KEY, computed(() => ({ env: store.env }))); +``` + +原先返回 Promise 的写法,改由宿主自己决定挂载时机(`v-if="ready"`),或先 provide 一个空 context、数据到位后更新——后者不保证 `defaultValue` / `onInitValue` 首轮能读到。 + +配置里的 `mForm.xxx` 读法不受影响,读穿 Proxy 保留。 ::: ## historyListExtraTabs diff --git a/docs/api/form/form-props.md b/docs/api/form/form-props.md index 6cf1e6bb..858aa400 100644 --- a/docs/api/form/form-props.md +++ b/docs/api/form/form-props.md @@ -219,8 +219,25 @@ - **类型:** `boolean` -## extendState +## context -- **详情:** 扩展 formState 的钩子函数,返回的对象会被合并到 formState 上 +- **详情:** 宿主业务上下文。可用本 prop 直接传,也可由祖先 `provide(FORM_CONTEXT_KEY)` 下发;同名字段本 prop 优先。 + + 嵌套表单(Link 的子表单、`MFormBox`、`MFormDialog`)会自动继承最近祖先的 context,不需要层层透传。 + + 配置回调统一通过第一个参数 `mForm` 读取:formState 是一个读穿 Proxy,`mForm` 上找不到的字段会自动落到 context。回调签名因此保持不变,后端 eval 下发的存量配置无需改动。 + +- **类型:** `FormContext` + +- **示例:** + +```ts +// 模板: +const formContext = computed(() => ({ username: store.username })); + +// 配置回调:mForm.username 读穿到 context +{ + display: (mForm) => mForm.username === 'admin', +} +``` -- **类型:** `(state: FormState) => Record | Promise>` diff --git a/docs/api/form/submit-form.md b/docs/api/form/submit-form.md index 3227b0c6..d044f707 100644 --- a/docs/api/form/submit-form.md +++ b/docs/api/form/submit-form.md @@ -131,7 +131,7 @@ function submitForm(options: SubmitFormOptions): Promise; | `popperClass` | `string` | — | 弹层 className | | `preventSubmitDefault` | `boolean` | — | 是否阻止表单原生 submit | | `useFieldTextInError` | `boolean` | `true` | 校验失败时错误提示前缀是否使用字段的 `text` 文案;`false` 时直接使用字段 `name` | -| `extendState` | `(state: FormState) => Record \| Promise>` | — | 扩展 `formState` | +| `context` | `FormContext` | — | 宿主业务上下文,与 MForm 的 `context` 语义一致;配置回调通过 `mForm.xxx` 读穿取用 | | `native` | `boolean` | `false` | 透传给 `Form.submitForm`。`true` 时返回内部响应式 `values`,否则返回 `cloneDeep(toRaw(values))` | | `returnChangeRecords` | `boolean` | `false` | `true` 时 resolve 结果为 `{ values, changeRecords }`,携带表单变更记录;否则仅 resolve `values` | | `appContext` | `AppContext \| null` | `null` | 父级 Vue 应用上下文。仅 `dialog: true` 时生效,用于继承全局组件、指令、provide 等,常通过 `app._context` 或 `getCurrentInstance()?.appContext` 获取 | diff --git a/docs/guide/advanced/history-list.md b/docs/guide/advanced/history-list.md index 9ced53e2..afae8c70 100644 --- a/docs/guide/advanced/history-list.md +++ b/docs/guide/advanced/history-list.md @@ -101,7 +101,6 @@ onCodeBlockDiff(id, index); | 字段 | 必填 | 说明 | | --- | --- | --- | | `appContext` | 否 | 父级应用上下文,用于让动态挂载的差异确认弹窗继承全局组件 / 指令 / provide / 插件(Element Plus、`@tmagic/form` 字段组件等)。在组件 `setup` 中调用时会自动取当前组件的 `appContext`,无需手动传;仅当在组件 setup 之外调用时才需显式传入(如 `editorApp._context`)。 | -| `extendState` | 否 | 透传给差异确认弹窗的 `extendState`(同 Editor 的 [`extendFormState`](#自定义对比判断)),使对比表单中依赖业务上下文的 `display` / `disabled` 等 `filterFunction` 正常工作。 | | `dialogWidth` | 否 | 内置页面 / 数据源 / 代码块的差异 / 回滚确认弹窗默认宽度(透传给 `TMagicDialog` 的 `width`),如 `'1200px'` / `'80%'`。缺省时使用弹窗内置默认宽度(`900px`)。业务自有历史可在 `viewDiff` / `confirmAndRevert` 调用时通过各自入参的 `width` 单独覆盖。 | > 若只需要无确认、无校验的静默回滚,直接用上面的 `editorService.revertPageStep` 等即可,无需 `useHistoryRevert`。 @@ -164,7 +163,7 @@ const historyListExtraTabs = [ ## 自定义对比判断 -差异对话框中的「表单对比」最终透传到 `MForm`,你可以通过 Editor 顶层注入的 `extendFormState` 让对比表单拿到完整业务上下文,从而让依赖上下文的 `display` / `disabled` 等 `filterFunction` 正常工作。 +差异对话框中的「表单对比」最终透传到 `MForm`。Editor 会把 `services` / `stage` provide 为 `FORM_CONTEXT_KEY`,对比表单自动继承;业务字段在 `` 外层再 provide 一层即可,详见 [表单业务上下文](/api/editor/props.html#表单业务上下文)。配置回调通过 `mForm.xxx` 读穿取用。 若某些字段语义上相等但结构不同(例如 `code-select` 字段中 `''` 与 `{ hookType: 'code', hookData: [] }` 应视为相等),可借助 `@tmagic/form` 的 [`showDiff`](/api/form/form-props.html#showdiff) 自定义判断函数避免被误判为差异。 diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index 7c838400..79d6f423 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -101,7 +101,6 @@