roymondchen 734e6a8ee6 feat(form): 支持 rules.typeMatch 按字段 type 校验值类型与选项匹配
新增可扩展的 typeMatch 校验能力,兼容 async-validator 规则体系,并补充文档与单元测试。
2026-07-13 15:52:56 +08:00

184 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 表单校验
`@tmagic/form` 字段可通过 `rules` 配置校验规则,兼容 [async-validator](https://github.com/yiminghe/async-validator)Element Plus 内部使用)的常见能力,并额外支持按字段 `type` 做值类型 / 选项匹配校验(`typeMatch`)。
## 基础用法
```ts
{
name: 'title',
text: '名称',
rules: [
{ required: true, message: '请输入名称' },
{ typeMatch: true, message: '名称类型不合法' },
],
}
```
`rules` 类型见下方 [`Rule`](#类型定义)。未配置 `typeMatch` 时,现有表单行为不变。
## typeMatch
开启 `typeMatch: true` 后,表单会按字段 `config.type`(及关联配置)校验当前值是否合法。空值(`undefined` / `null` / `''`,多选类空数组 `[]`)直接通过,必填请继续使用 `required`
### 内置映射
| 字段 type | 期望值 |
| --- | --- |
| `text` / `textarea` / `color-picker` / `html` / 默认无 type | `string`;若 `filter: 'number'` 则为 `number``filter` 为自定义函数时跳过内置类型校验 |
| `display` / `hidden` | 不校验 |
| `number` | `number`(非 NaN |
| `number-range` | 长度为 2 的数字数组 |
| `date` / `datetime` / `time` | 按 `valueFormat` 校验;`x` / `timestamp` 期望 `number`,其余按 [Day.js format](https://day.js.org/docs/en/display/format) 严格解析字符串 |
| `daterange` / `timerange` | 无 `names` 时为长度为 2 的数组,元素按 `valueFormat` 校验;有 `names` 时跳过 |
| `switch` / `checkbox` | 值必须是解析后的 `activeValue` / `inactiveValue` 之一(显式配置优先;未配置且 `filter === 'number'` 时为 `1`/`0`;否则为 `true`/`false` |
| `select` | 单选:值 ∈ options`multiple`:数组且每项 ∈ options`allowCreate` / `remote`:只校验基础形态,不做 options 枚举 |
| `radio-group` / `radioGroup` | 值 ∈ options |
| `checkbox-group` / `checkboxGroup` | 数组且每项 ∈ options |
| `cascader` | 有 `valueSeparator` 时可为 `string``array`;默认 `emitPath` 为路径数组;`emitPath: false` 为叶子值;`multiple` 为数组;静态 options 校验路径/叶子;`remote` 只做形态校验 |
| `table` / `group-list` / `groupList` | `array` |
| 容器类(`row` / `tab` / `fieldset` / `panel` / `step` / `flex-layout` / `link` / `component` / `dynamic-field` 等) | 不校验 |
日期类默认 `valueFormat` 与字段组件一致:
- `date``YYYY/MM/DD`
- `datetime` / `daterange``YYYY/MM/DD HH:mm:ss`
- `time` / `timerange``HH:mm:ss`
### 与自定义 validator 共存
同一条 rule 同时配置了 `typeMatch``validator` 时,会先做类型匹配校验,通过后再执行自定义 `validator`
```ts
{
name: 'age',
type: 'number',
rules: [
{
typeMatch: true,
message: '年龄必须是数字',
validator: ({ value, callback }) => {
if (value < 0) {
callback(new Error('年龄不能小于 0'));
return;
}
callback();
},
},
],
}
```
## 扩展自定义 type 规则
业务可覆盖内置规则,或为自定义字段 type 注册校验。自定义规则优先于内置规则。
### 运行时注册
```ts
import {
registerTypeMatchRule,
registerTypeMatchRules,
deleteTypeMatchRule,
clearTypeMatchRules,
} from '@tmagic/form';
// 覆盖内置 text
registerTypeMatchRule('text', (value, { message }) => {
if (typeof value !== 'string') {
return message || '值类型应为字符串';
}
});
// 扩展业务字段
registerTypeMatchRule('vs-code', (value, { message }) => {
if (typeof value !== 'string') {
return message || '代码字段应为字符串';
}
});
// 批量注册
registerTypeMatchRules({
foo: (value) => (Array.isArray(value) ? undefined : '应为数组'),
});
// 删除 / 清空
deleteTypeMatchRule('foo');
clearTypeMatchRules();
```
自定义校验器签名:`(value, context) => string | undefined`。返回错误文案表示失败,返回 `undefined` 表示通过。`context` 包含 `fieldType``mForm``props``message`
### 安装时注册
```ts
import MagicForm from '@tmagic/form';
app.use(MagicForm, {
typeMatchRules: {
'my-field': (value, { message }) => {
if (typeof value !== 'string') {
return message || 'my-field 应为字符串';
}
},
},
});
```
## 示例
### select 选项匹配
```ts
{
name: 'status',
type: 'select',
options: [
{ text: '启用', value: 1 },
{ text: '禁用', value: 0 },
],
rules: [
{ required: true, message: '请选择状态' },
{ typeMatch: true, message: '状态值不合法' },
],
}
```
### date 按 valueFormat 校验
```ts
{
name: 'birthday',
type: 'date',
valueFormat: 'YYYY-MM-DD',
rules: [{ typeMatch: true, message: '日期格式不正确' }],
}
```
### text + filter: number
```ts
{
name: 'width',
type: 'text',
filter: 'number',
rules: [{ typeMatch: true, message: '宽度应为数字' }],
}
```
## 类型定义
::: details 查看 Rule 类型定义
<<< @/../packages/form-schema/src/base.ts#Rule{ts}
:::
::: details 查看 TypeMatchValidator / TypeMatchValidateContext 类型定义
<<< @/../packages/form/src/utils/typeMatch.ts#TypeMatchValidator{ts}
<<< @/../packages/form/src/utils/typeMatch.ts#TypeMatchValidateContext{ts}
:::
::: details 查看 FormInstallOptions 类型定义
<<< @/../packages/form/src/plugin.ts#FormInstallOptions{ts}
:::