mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-07-23 00:40:42 +08:00
- 新增 typeMatchRules.ts,为编辑器自定义字段注册内置 typeMatch 校验规则 - 抽取 event.ts 事件工具函数 - form typeMatch 适配 TDesign 校验器签名,错误消息补充实际值 - rules.md 新增「Editor 字段内置规则」章节,16 个字段文档补充校验说明
207 lines
7.5 KiB
Markdown
207 lines
7.5 KiB
Markdown
# 表单校验
|
||
|
||
`@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 应为字符串';
|
||
}
|
||
},
|
||
},
|
||
});
|
||
```
|
||
|
||
### Editor 字段内置规则
|
||
|
||
安装 `@tmagic/editor` 时会自动 `registerTypeMatchRules` 注册编辑器自定义字段规则。服务数据(数据源 / 代码块 / 节点树)未就绪时,只做基础形态校验,不做枚举或存在性失败。
|
||
|
||
| 字段 type | 期望值 |
|
||
| --- | --- |
|
||
| `key-value` / `style-setter` | 普通对象;`key-value` + `advanced` 且值为 `function` 时放行 |
|
||
| `cond-op-select` | 已知算子;能解析字段类型时按类型收窄 |
|
||
| `code-select-col` | `string`;有代码块 DSL 时须为已有 codeId |
|
||
| `page-fragment-select` / `ui-select` | `string \| number`;有节点树时须为已有页面片 / 组件 id |
|
||
| `data-source-input` | `string`;`${...}` 绑定须指向已有数据源/字段 |
|
||
| `data-source-method-select` | `[dsId, methodName]`,方法须在该数据源可选方法集中 |
|
||
| `data-source-field-select` | 数据源路径 `string[]`;有 `fieldConfig` 且非路径值时跳过 |
|
||
| `data-source-select` | `value: 'id'` 为已有 ds id;否则为含 `isBindDataSource` + `dataSourceId` 的对象 |
|
||
| `code-select` | `{ hookType: 'code', hookData }` 的浅层结构校验(`codeId` 存在性 / 数据源方法存在性由内部 `code-select-col`、`data-source-method-select` 单元格各自校验,只标红出错单元格) |
|
||
| `data-source-fields` / `data-source-mocks` / `data-source-methods` | 数组 + 浅层结构(`name`/`type`、`title`/`enable`/`data`、`content`/`params` 等) |
|
||
| `event-select` | 数组;兼容新旧格式的浅层结构校验(`name` / 联动组件 `method` 是否 ∈ 可选项由字段内 `eventNameConfig.rules`、`compActionConfig.rules` 单独校验,只标红对应 select) |
|
||
| `display-conds` | 数组 + `cond[].field`/`op` 浅层结构校验(`op` 是否为已知算子、字段路径是否存在由内部 `cond-op-select`、`field` 单元格各自校验,只标红出错单元格) |
|
||
|
||
> 容器类字段(`event-select` / `code-select` / `display-conds`)遵循同一约定:容器级 typeMatch 只做结构校验,「枚举 / 存在性」下沉到内部单元格各自的 typeMatch/rules,避免单个子项非法导致整块表单标红。
|
||
|
||
业务仍可用 `registerTypeMatchRule` 覆盖上述任一 type。
|
||
|
||
## 示例
|
||
|
||
### 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}
|
||
:::
|