---
description: DynamicForm 动态表单定义、挂载与 dig/forms 数据工厂约定
globs: "**/*.vue"
alwaysApply: false
---

# 动态表单（DynamicForm）使用约定

基于 `DynamicForm.vue`、`DynamicForm.ts`（`IDynamicFormOptions` / `IDynamicFormItem`）及 `pages/dig/forms/data/*.ts`（如 `overview.ts`）的实际用法。

## 组件侧

- 使用 `<DynamicForm :options="..." :model="..." :name="..." :globalParams="..." />`。`model` 与表单双向绑定；`globalParams` 可在条目回调的 `formGlobalParams` 中读取。
- 通过 `ref` 拿到 `IDynamicFormRef`：`validate` / `submit`、`setValueByPath` / `getValueByPath`（路径为点分字符串或数组转点分）、`getFormRef`、`getFormItemControlRef`、`dispatchMessage` / `dispatchReload`（常量 `MESSAGE_RELOAD`）、`initDefaultValuesToModel`、`getVisibleFormNames`。
- 顶层校验：在 `options.formRules`（async-validator `Rules`）或单项 `rules`（`RuleItem[]`）。可选 `formAdditionaProps`、`disabled`、`readonly`、`suppressRootError`、`suppressEmptyError`、`nestObjectMargin`、`emptyText`。

## 选项结构 `IDynamicFormOptions`

- **必填**：`formItems: IDynamicFormItem[]`。
- 全局默认：可改 `defaultDynamicFormOptions` 或调用 `configDefaultDynamicFormOptions`（勿传入 `formItems`），与单次 `options` 合并。

## 表单项 `IDynamicFormItem`

- **必填**：`name`（字段路径名）。**常用**：`label`、`type`（内置控件类型字符串）、`additionalProps`（传给具体控件）、`formProps`（传给 `Field`）、`defaultValue`、`rules`、`children`（嵌套对象/数组项）。
- **动态字段**：`label`、`additionalProps`、部分控件字段、`show`、`disabled` 等可写成 **`IDynamicFormItemCallback<T>`**：`{ callback: (model, rawModel, parentModel, params) => T }`。关联远端字段时优先用 **`rawModel`**；列表场景用 **`parentModel`**。`params` 含 `item`、`parent`、`form`（`IDynamicFormRef`）、`formGlobalParams`、`formRules`、`isFirst` / `isLast`。
- **生命周期 / 联动**：`mounted` / `beforeUnmount` / `watch`；跨项赋值在拿到表单 ref 时用 **`form.setValueByPath('field', value)`**（参见 `overview` 中 `select-city` 的 `onSelectedTownship`）。
- **布局容器**：`flat-group` 用于横向/分组排版（可配合 `childrenColProps`、`rowProps`）；子项仍占用模型上的 `name`。嵌套对象用带 `children` 的条目（由渲染层按 `type` 区分对象/数组等）。
- **数组子项**：可选 `newChildrenObject`、`deleteChildrenCallback` 控制增删；子层可用 `childrenColProps` / `colProps` / `nestObjectMargin`。
- **默认值**：`defaultValue` 可为字面量或 **`() => value`**（惰性初始化）；`initDefaultValuesToModel` 只对仍为 `undefined`/`null` 的路径写入。
- **消息**：条目可实现 `message`，根上 `dispatchMessage` 分发；预置 `MESSAGE_RELOAD` 用于刷新类逻辑。

## dig 业务表单数据（`GroupForm` / `SingleForm`）

- 形态：`Record<number, SingleForm>`，每项为 **`[数据模型类, (formRef) => IDynamicFormOptions, { title, typeName, order?, ... }]`**（见 `forms.ts`）。
- 工厂函数里若需表单实例（联动、路径赋值），签名应为 **`(form: Ref<IDynamicFormRef>) => ({ formItems: [...] })`**，与 `overview.ts` 中 `(form) => ({ formItems })` 一致。
- 复用片段：可将公共 `formItems` 抽成函数返回片段，再用展开合并 **`...(xxx(f, opts)).formItems`**。
- 选择类控件：`additionalProps.loadData` 异步拉选项并映射为 `{ value, text }`；按需 **`as PickerIdFieldProps` / `RadioIdFieldProps` / `CheckBoxListProps` / `FieldProps`** 等与控件 Props 对齐。
- 条件显示：`show: { callback: (_, m) => ... }` 中用 **`m`（通常为当前层 rawModel）** 判断兄弟字段（见「其他服务业」等项）。

## 建议避免

- 勿猜测未注册的 `type`；新增类型需在动态表单渲染链路中已有对应组件映射。
- 回调里访问兄弟节点不要用错层级：`model` 是当前项值，`rawModel` 是整表根数据（跨深层字段时尤其要用根路径或 `setValueByPath`）。
