# 表单配置语法

<cite>
**本文引用的文件**
- [packages/components/ProForm.vue](file://packages/components/ProForm.vue)
- [packages/core/src/components/ProForm.vue](file://packages/core/src/components/ProForm.vue)
- [src/views/ProForm.vue](file://src/views/ProForm.vue)
- [packages/components/ProTypeItem/ProTypeItem.vue](file://packages/components/ProTypeItem/ProTypeItem.vue)
- [packages/libs/util.js](file://packages/libs/util.js)
- [types/index.d.ts](file://types/index.d.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录：完整配置示例与最佳实践](#附录完整配置示例与最佳实践)

## 简介
本文件系统性阐述 ProForm 表单配置语法，聚焦字段配置对象的结构与属性，涵盖分组机制、显示控制（showForm）、布局配置（formLineNum）等关键能力，并结合源码中的实现细节给出可操作的配置建议与最佳实践。

## 项目结构
围绕表单配置语法的相关文件主要分布在以下位置：
- 组件实现：packages/components/ProForm.vue、packages/core/src/components/ProForm.vue
- 字段渲染封装：packages/components/ProTypeItem/ProTypeItem.vue
- 示例与用法：src/views/ProForm.vue
- 工具与格式化：packages/libs/util.js
- 类型声明：types/index.d.ts

```mermaid
graph TB
subgraph "表单组件层"
PF["ProForm.vue<br/>表单容器与布局"]
PTI["ProTypeItem.vue<br/>字段渲染封装"]
end
subgraph "视图与示例"
VF["src/views/ProForm.vue<br/>示例与用法"]
end
subgraph "工具与类型"
U["packages/libs/util.js<br/>通用工具"]
T["types/index.d.ts<br/>类型声明"]
end
VF --> PF
PF --> PTI
PF -. 使用 .-> U
T -. 类型约束 .-> PF
```

图表来源
- [packages/components/ProForm.vue:1-144](file://packages/components/ProForm.vue#L1-L144)
- [packages/components/ProTypeItem/ProTypeItem.vue:1-132](file://packages/components/ProTypeItem/ProTypeItem.vue#L1-L132)
- [src/views/ProForm.vue:1-198](file://src/views/ProForm.vue#L1-L198)
- [packages/libs/util.js:1-110](file://packages/libs/util.js#L1-L110)
- [types/index.d.ts:1-19](file://types/index.d.ts#L1-L19)

章节来源
- [packages/components/ProForm.vue:1-144](file://packages/components/ProForm.vue#L1-L144)
- [packages/core/src/components/ProForm.vue:1-174](file://packages/core/src/components/ProForm.vue#L1-L174)
- [src/views/ProForm.vue:1-198](file://src/views/ProForm.vue#L1-L198)

## 核心组件
- ProForm：负责表单容器、字段分组、网格布局、校验规则转换、字段显示控制、事件与请求集成。
- ProTypeItem：负责根据字段配置动态渲染具体 UI 组件或自定义 JSX 片段，并处理输入值格式化与回传。
- 示例视图：演示字段配置、渲染方式、校验规则、提交流程等。

章节来源
- [packages/components/ProForm.vue:156-213](file://packages/components/ProForm.vue#L156-L213)
- [packages/core/src/components/ProForm.vue:154-213](file://packages/core/src/components/ProForm.vue#L154-L213)
- [packages/components/ProTypeItem/ProTypeItem.vue:1-132](file://packages/components/ProTypeItem/ProTypeItem.vue#L1-L132)

## 架构总览
下图展示了 ProForm 如何解析字段配置、进行分组与网格布局、以及如何调用 ProTypeItem 渲染字段。

```mermaid
sequenceDiagram
participant View as "视图组件"
participant PF as "ProForm"
participant Group as "分组逻辑"
participant Grid as "网格布局"
participant PTI as "ProTypeItem"
participant Validator as "校验规则转换"
View->>PF : 传入 columns 配置与 modelValue
PF->>Group : 按 group 分组
Group-->>PF : 返回分组后的 columns
PF->>Grid : 计算 grid-template-columns 与 span
PF->>Validator : 规范化 rules/validate
loop 遍历每个字段
PF->>PTI : 传递 item/renderItem/outData
PTI-->>PF : 回传更新后的值
PF->>PF : 更新 modelValue 并触发单项校验
end
```

图表来源
- [packages/components/ProForm.vue:17-144](file://packages/components/ProForm.vue#L17-L144)
- [packages/components/ProForm.vue:203-205](file://packages/components/ProForm.vue#L203-L205)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)
- [packages/components/ProTypeItem/ProTypeItem.vue:51-124](file://packages/components/ProTypeItem/ProTypeItem.vue#L51-L124)

## 详细组件分析

### 字段配置对象结构与属性
字段配置对象用于描述单个表单项的行为与外观，常见属性如下（以源码行为为准）：

- key
  - 作用：绑定到 v-model 的路径，作为表单数据的键名；支持嵌套路径。
  - 影响：用于 prop 校验、数据读取与写入。
  - 参考实现：propItem、getValue、change。
  
- title
  - 作用：字段标签文本；当为空白时保留原样，否则追加冒号。
  - 参考实现：title 方法。
  
- formWidth
  - 作用：字段宽度，支持像素与百分比两种单位。
  - 实现：通过内联样式动态设置宽度。
  
- formLineNum
  - 作用：字段跨列数（网格跨度），影响 grid-column-start。
  - 实现：在容器中以 repeat(formLineNum, ...) 设置网格列模板。
  
- labelPosition
  - 作用：标签位置（如 left/top），影响 label 宽度与换行策略。
  - 实现：根据位置条件决定 label-width 与样式。
  
- group
  - 作用：字段分组键，相同 group 的字段会被归为一组并在界面中显示分组标题。
  - 实现：使用 lodash groupBy 按 group 聚合。
  
- showForm
  - 作用：控制字段在不同场景下的显示逻辑。
  - 支持类型：
    - 数组：仅在 type 匹配数组元素时显示。
    - 函数：接收 { value, type, config } 上下文，返回布尔值。
    - 默认：未设置时始终显示。
  - 实现：showColumns 方法。
  
- renderForm
  - 作用：自定义渲染字段，支持对象式与函数式两种形式。
  - 对象式：
    - type：组件名或 HTML 标签名
    - props：组件属性
    - on：事件监听
    - scopedSlots：作用域插槽（可数组）
    - style：样式（支持表达式）
    - format：值格式化函数或对象
  - 函数式：
    - 接收上下文参数，返回 JSX 片段；若未自动挂载 v-model，则会自动补全。
  - 实现：ProTypeItem 组件负责解析与渲染。
  
- rules / validate
  - 作用：表单校验规则，支持字符串正则自动转为 RegExp。
  - 实现：ruleChange 将 pattern 字符串转为正则对象。
  
- 其他常用属性（示例中出现）
  - icons.form：标签前图标显示标记
  - disabled / readonly：禁用/只读状态
  - notShowTable / notShowSearch / notShowForm：在不同视图中隐藏该字段
  - format：值格式化函数（配合 renderForm.format 使用）

章节来源
- [packages/components/ProForm.vue:208-209](file://packages/components/ProForm.vue#L208-L209)
- [packages/components/ProForm.vue:232-247](file://packages/components/ProForm.vue#L232-L247)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)
- [packages/components/ProForm.vue:260-276](file://packages/components/ProForm.vue#L260-L276)
- [packages/components/ProTypeItem/ProTypeItem.vue:51-124](file://packages/components/ProTypeItem/ProTypeItem.vue#L51-L124)
- [src/views/ProForm.vue:29-191](file://src/views/ProForm.vue#L29-L191)

### 字段分组机制（group）
- 分组依据：字段配置对象的 group 属性。
- 分组实现：使用 lodash 的 groupBy 将 columns 按 group 聚合为对象，键名为分组标题。
- 分组标题显示：当分组键存在且非 undefined 时，渲染对应标题文本。

```mermaid
flowchart TD
Start(["开始"]) --> GroupBy["按 group 调用 lodash.groupBy"]
GroupBy --> HasTitle{"分组键是否存在且非 undefined？"}
HasTitle --> |是| RenderTitle["渲染分组标题"]
HasTitle --> |否| SkipTitle["跳过分组标题"]
RenderTitle --> LoopItems["遍历该分组字段"]
SkipTitle --> LoopItems
LoopItems --> End(["结束"])
```

图表来源
- [packages/components/ProForm.vue:203-205](file://packages/components/ProForm.vue#L203-L205)
- [packages/components/ProForm.vue:21-25](file://packages/components/ProForm.vue#L21-L25)

章节来源
- [packages/components/ProForm.vue:203-205](file://packages/components/ProForm.vue#L203-L205)
- [packages/components/ProForm.vue:21-25](file://packages/components/ProForm.vue#L21-L25)

### 字段显示控制（showForm）
- 支持数组与函数两种模式：
  - 数组：仅在 type 值出现在数组中时显示。
  - 函数：接收上下文 { value, type, config }，返回布尔值决定显示。
- 默认行为：未设置时始终显示。
- 实现入口：showColumns 方法。

```mermaid
flowchart TD
S(["进入 showColumns"]) --> CheckShow{"item.showForm 是否存在？"}
CheckShow --> |否| ShowTrue["返回 true默认显示"]
CheckShow --> |是| IsArray{"是否为数组？"}
IsArray --> |是| InArray{"type 是否包含于数组？"}
InArray --> |是| ShowTrue
InArray --> |否| ShowFalse["返回 false"]
IsArray --> |否| IsFunc{"是否为函数？"}
IsFunc --> |是| CallFunc["调用函数(value,type,config)"]
CallFunc --> FuncResult{"返回值为真？"}
FuncResult --> |是| ShowTrue
FuncResult --> |否| ShowFalse
IsFunc --> |否| ShowTrue
```

图表来源
- [packages/components/ProForm.vue:232-247](file://packages/components/ProForm.vue#L232-L247)

章节来源
- [packages/components/ProForm.vue:232-247](file://packages/components/ProForm.vue#L232-L247)

### 字段布局配置（formLineNum 与网格）
- 全局列数：formLineNum 控制每行最大列数，用于计算网格列模板。
- 字段跨度：每个字段的 formLineNum 决定其 grid-column-start 的跨度。
- 宽度控制：formWidth 支持像素与百分比，用于字段宽度设置。

```mermaid
flowchart TD
Init(["初始化"]) --> CalcCols["计算 grid-template-columns = repeat(formLineNum, ...)"]
CalcCols --> SpanField["字段 span = item.formLineNum"]
SpanField --> WidthRule{"formWidth > 100 ? 像素 : 百分比"}
WidthRule --> ApplyWidth["应用宽度样式"]
ApplyWidth --> Render(["渲染完成"])
```

图表来源
- [packages/components/ProForm.vue:28-32](file://packages/components/ProForm.vue#L28-L32)
- [packages/components/ProForm.vue:50-57](file://packages/components/ProForm.vue#L50-L57)
- [packages/components/ProForm.vue:110-116](file://packages/components/ProForm.vue#L110-L116)

章节来源
- [packages/components/ProForm.vue:28-32](file://packages/components/ProForm.vue#L28-L32)
- [packages/components/ProForm.vue:50-57](file://packages/components/ProForm.vue#L50-L57)
- [packages/components/ProForm.vue:110-116](file://packages/components/ProForm.vue#L110-L116)

### 字段渲染与值格式化（ProTypeItem）
- 对象式渲染：
  - type、props、on、scopedSlots、style、format 等。
  - 支持表达式与作用域插槽，内部通过 h 渲染。
- 函数式渲染：
  - 自定义返回 JSX；若未挂载 v-model，将自动补全。
- 值格式化：
  - 若 renderItem.format 存在，将在输入时调用格式化函数，支持包裹式格式化（formatWapper）。
- 工具支持：
  - commonToFn：将字符串或对象形式的格式化函数转换为可执行函数。
  - isHTMLTag：识别是否为 HTML 标签名。

```mermaid
sequenceDiagram
participant PF as "ProForm"
participant PTI as "ProTypeItem"
participant Util as "util.js"
PF->>PTI : 传入 item/renderItem/outData
PTI->>Util : 解析 format/表达式/作用域插槽
PTI-->>PF : onUpdate : modelValue(value)
PF->>PF : 更新 modelValue 并单项校验
```

图表来源
- [packages/components/ProTypeItem/ProTypeItem.vue:51-124](file://packages/components/ProTypeItem/ProTypeItem.vue#L51-L124)
- [packages/libs/util.js:56-78](file://packages/libs/util.js#L56-L78)
- [packages/libs/util.js:80-94](file://packages/libs/util.js#L80-L94)

章节来源
- [packages/components/ProTypeItem/ProTypeItem.vue:51-124](file://packages/components/ProTypeItem/ProTypeItem.vue#L51-L124)
- [packages/libs/util.js:56-78](file://packages/libs/util.js#L56-L78)
- [packages/libs/util.js:80-94](file://packages/libs/util.js#L80-L94)

### 校验规则转换与提交流程
- 规则转换：将字符串正则自动转为 RegExp，确保校验引擎可用。
- 提交流程：先整体校验，通过后发起请求，回调 complete。

```mermaid
sequenceDiagram
participant PF as "ProForm"
participant Validator as "校验引擎"
participant Req as "customRequest"
PF->>Validator : validate()
Validator-->>PF : 校验结果
alt 通过
PF->>Req : 发起请求(datas=modelValue)
Req-->>PF : 返回响应
PF-->>PF : 调用 complete(res)
else 失败
PF-->>PF : 停止提交
end
```

图表来源
- [packages/components/ProForm.vue:215-224](file://packages/components/ProForm.vue#L215-L224)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)

章节来源
- [packages/components/ProForm.vue:215-224](file://packages/components/ProForm.vue#L215-L224)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)

## 依赖关系分析
- ProForm 依赖：
  - lodash-es：分组与深拷贝、取值、集合操作。
  - UI 适配器：通过 useUIAdapter 获取 Form、FormItem、Input、Button、Icon 等组件。
  - 自定义请求：customRequest 封装提交请求。
- ProTypeItem 依赖：
  - Vue 渲染：h、resolveComponent。
  - lodash-es：对象与集合操作。
  - util.js：commonToFn、isHTMLTag。
- 示例视图依赖：
  - dayjs：日期格式化示例。
  - pro-select、DatePicker 等组件：通过 renderForm 的对象式配置使用。

```mermaid
graph LR
PF["ProForm.vue"] --> Lodash["lodash-es"]
PF --> Adapter["useUIAdapter()"]
PF --> Req["customRequest"]
PTI["ProTypeItem.vue"] --> Vue["Vue(h, resolveComponent)"]
PTI --> Lodash
PTI --> Util["util.js"]
VF["src/views/ProForm.vue"] --> PF
VF --> DayJS["dayjs"]
```

图表来源
- [packages/components/ProForm.vue:149-151](file://packages/components/ProForm.vue#L149-L151)
- [packages/core/src/components/ProForm.vue:152](file://packages/core/src/components/ProForm.vue#L152)
- [packages/components/ProTypeItem/ProTypeItem.vue:1-6](file://packages/components/ProTypeItem/ProTypeItem.vue#L1-L6)
- [src/views/ProForm.vue:15-19](file://src/views/ProForm.vue#L15-L19)

章节来源
- [packages/components/ProForm.vue:149-151](file://packages/components/ProForm.vue#L149-L151)
- [packages/core/src/components/ProForm.vue:152](file://packages/core/src/components/ProForm.vue#L152)
- [packages/components/ProTypeItem/ProTypeItem.vue:1-6](file://packages/components/ProTypeItem/ProTypeItem.vue#L1-L6)
- [src/views/ProForm.vue:15-19](file://src/views/ProForm.vue#L15-L19)

## 性能考量
- 渲染优化：
  - 使用 grid 布局减少复杂定位计算，span 字段避免额外计算。
  - 仅在需要时渲染字段（v-if=showColumns），降低 DOM 数量。
- 校验优化：
  - 单项校验：每次变更后对当前字段进行 validateField，避免整表单重校验。
- 数据处理：
  - 深拷贝 modelValue 后再更新，避免直接修改引用导致的副作用。
- 工具函数：
  - commonToFn 将字符串/对象格式化函数编译为可执行函数，减少重复解析成本。

章节来源
- [packages/components/ProForm.vue:273-292](file://packages/components/ProForm.vue#L273-L292)
- [packages/libs/util.js:56-78](file://packages/libs/util.js#L56-L78)

## 故障排查指南
- 字段未显示
  - 检查 showForm 是否为 false 或函数返回 false。
  - 检查 type 与数组/函数条件是否匹配。
  - 参考：showColumns。
- 标签未正确显示
  - 检查 title 是否为空白字符；空白标题将被保留原样。
  - 参考：title。
- 校验规则无效
  - 检查 pattern 是否为字符串；ruleChange 会将其转为正则。
  - 参考：ruleChange。
- 值未更新或格式化异常
  - 检查 renderForm.format 是否正确；ProTypeItem 会在输入时调用格式化。
  - 参考：ProTypeItem 的 input/format 流程。
- 嵌套 key 报错
  - propItem 会对不存在的嵌套路径发出提示，请确认 modelValue 中已配置相应路径。
  - 参考：propItem。
- 提交失败
  - 先检查 validate 结果；通过后再发起请求。
  - 参考：submit。

章节来源
- [packages/components/ProForm.vue:232-247](file://packages/components/ProForm.vue#L232-L247)
- [packages/components/ProForm.vue:208-214](file://packages/components/ProForm.vue#L208-L214)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)
- [packages/components/ProTypeItem/ProTypeItem.vue:37-49](file://packages/components/ProTypeItem/ProTypeItem.vue#L37-L49)
- [packages/components/ProForm.vue:264-271](file://packages/components/ProForm.vue#L264-L271)
- [packages/components/ProForm.vue:215-224](file://packages/components/ProForm.vue#L215-L224)

## 结论
ProForm 的配置语法以字段配置对象为核心，通过 group、showForm、formLineNum、formWidth、labelPosition 等属性实现灵活的分组、显示控制与布局管理；借助 ProTypeItem 的对象式/函数式渲染与 util.js 的格式化工具，能够覆盖多样化的业务场景。遵循本文提供的最佳实践与排障建议，可显著提升配置效率与运行稳定性。

## 附录：完整配置示例与最佳实践

### 字段配置示例（路径参考）
- 文本输入（基础）
  - 参考：[src/views/ProForm.vue:29-31](file://src/views/ProForm.vue#L29-L31)
- 下拉选择（renderForm 函数式）
  - 参考：[src/views/ProForm.vue:36-44](file://src/views/ProForm.vue#L36-L44)
- 下拉选择（renderForm 对象式）
  - 参考：[src/views/ProForm.vue:49-56](file://src/views/ProForm.vue#L49-L56)
- 日期选择（带格式化）
  - 参考：[src/views/ProForm.vue:66-69](file://src/views/ProForm.vue#L66-L69)
- 自定义输入（函数式渲染 + 限制长度）
  - 参考：[src/views/ProForm.vue:78-92](file://src/views/ProForm.vue#L78-L92)
- 日期选择（对象式）
  - 参考：[src/views/ProForm.vue:97-112](file://src/views/ProForm.vue#L97-L112)

### 最佳实践
- 字段分组
  - 使用 group 对字段进行语义分组，便于用户阅读与维护。
  - 参考：groupColunms 与分组标题渲染。
- 显示控制
  - 使用 showForm 的函数式配置，结合 type 判断，实现“新增/编辑”等场景差异化显示。
  - 参考：showColumns。
- 布局与宽度
  - 合理设置 formLineNum 与 formWidth，保证在不同屏幕下的可读性与紧凑性。
  - 参考：grid-template-columns 与宽度设置。
- 校验规则
  - 使用字符串正则时，确保格式正确；必要时在前端转换为 RegExp。
  - 参考：ruleChange。
- 值格式化
  - 在 renderForm.format 中统一处理格式化逻辑，避免分散处理。
  - 参考：ProTypeItem 的 format 流程与 util.js 的 commonToFn。
- 错误处理
  - 对嵌套 key 缺失发出日志提示，及时补充 modelValue。
  - 参考：propItem。
  - 提交前先 validate，失败时阻断请求。
  - 参考：submit。

章节来源
- [packages/components/ProForm.vue:203-205](file://packages/components/ProForm.vue#L203-L205)
- [packages/components/ProForm.vue:232-247](file://packages/components/ProForm.vue#L232-L247)
- [packages/components/ProForm.vue:28-32](file://packages/components/ProForm.vue#L28-L32)
- [packages/components/ProForm.vue:110-116](file://packages/components/ProForm.vue#L110-L116)
- [packages/components/ProForm.vue:251-259](file://packages/components/ProForm.vue#L251-L259)
- [packages/components/ProTypeItem/ProTypeItem.vue:37-49](file://packages/components/ProTypeItem/ProTypeItem.vue#L37-L49)
- [packages/libs/util.js:56-78](file://packages/libs/util.js#L56-L78)
- [packages/components/ProForm.vue:264-271](file://packages/components/ProForm.vue#L264-L271)
- [packages/components/ProForm.vue:215-224](file://packages/components/ProForm.vue#L215-L224)
- [src/views/ProForm.vue:29-112](file://src/views/ProForm.vue#L29-L112)