add-form-validation-rule

为 Vue 3 + Ant Design Vue 表单系统新增自定义校验规则。支持正则校验、值范围校验、日期校验等。包含类型定义、校验实现、单元测试的完整流程。

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "add-form-validation-rule" with this command: npx skills add sakumyz/skills/sakumyz-skills-add-form-validation-rule

新增表单校验规则

本 skill 提供一套标准的工作流程,用于为项目的表单验证系统添加新的校验规则。

概述

项目采用 Ant Design Vue 4.x + 自定义规则引擎 的表单验证方案:

  • 类型定义src/components/atoms/AtmForm/index.ts 中的 BuiltInRules 接口
  • 规则实现src/hooks/useForm/getAntDFormRules.ts 中的规则转换逻辑
  • 验证函数src/utils/validation/ 目录下的具体验证实现
  • 单元测试src/hooks/useForm/getAntDFormRules.spec.ts 中的测试用例

核心流程

1. 添加类型定义

位置src/components/atoms/AtmForm/index.ts

BuiltInRules 接口中添加新的规则属性:

export interface BuiltInRules {
  // 示例:添加新规则
  myNewRule?: string | number | boolean | RegExp
}

规则类型指南

  • 简单布尔规则(无参数):boolean — 如 email?: boolean
  • 带参数的规则:根据参数类型 — 如 dateFormat?: stringmaxValue?: number
  • 多参数规则string(JSON格式)— 如 range?: '[1,10]'
  • 正则表达式RegExp 类型
  • 数组参数string[] | string — 如 fileExtension?: string | string[]

2. 实现规则逻辑

位置src/hooks/useForm/getAntDFormRules.ts

简单规则(simpleRules)- 正则/直接模式

用于无需参数的规则,在 simpleRules 对象中添加:

const simpleRules: Record<string, Rule> = {
  mySimpleRule: {
    pattern: /your-regex-pattern/,
    message: '错误提示文案',
    trigger: 'blur'
  }
}

复杂规则(getValidationRule)- 自定义验证器

getValidationRule 函数返回的规则对象中添加:

myComplexRule: {
  validator: (_, value) => {
    // 验证逻辑
    return validationHelper(validateResult, errorMessage);
  },
  trigger: rule?.trigger || 'blur',
  transform: rule?.transform
}

验证函数调用:优先使用已有验证函数(如 validateDateFormatvalidateNumberRange),减少新增文件。

2.1 更新 isBuiltInRule 函数

位置src/hooks/useForm/getAntDFormRules.ts 中的 isBuiltInRule 函数

在添加新规则属性到 BuiltInRules 接口后,必须isBuiltInRule 函数中的 ruleKeys 数组里添加对应的属性名:

function isBuiltInRule(value: any): value is RuleOptions {
  if (!isObject(value)) return false

  const ruleKeys = [
    'required',
    'pattern',
    // ... 其他现有属性 ...
    'myNewRule' // ← 添加新属性名
  ]

  // ... 后续逻辑保持不变 ...
}

⚠️ 这一步容易遗漏! 如果不更新 ruleKeys,新规则将被错误地识别为无效对象,导致规则处理失败。

3. 添加或重用验证函数

位置src/utils/validation/ 目录

决策树

  1. 如果是正则模式(简单规则),直接在 simpleRules 中定义,不需要创建验证函数
  2. 如果需要复杂验证逻辑
    • 优先选择:现有的 .ts 文件(date.tsnumber.tsstring.tsfile.ts
    • 最后选择:创建新的验证文件,仅当逻辑完全不相关时

验证函数特征

  • 输入参数是值和规则配置
  • 返回 boolean{ valid: boolean; message?: string }
  • 处理 nullundefined 等边界情况

4. 编写单元测试

位置src/hooks/useForm/getAntDFormRules.spec.ts

测试模板

it('myNewRule 规则正确转换', () => {
  const rules: FormRules = {
    field: {
      myNewRule: true // 或对应的参数值
    }
  }

  const result = getAntDFormRules(rules)
  const fieldRules = result!.field as Rule[]

  expect(fieldRules).toContainEqual({
    pattern: expect.any(RegExp), // 或 validator: expect.any(Function)
    message: expect.any(String),
    trigger: 'blur'
  })
})

// 对于带参数的规则,添加验证器功能测试
it('myNewRule 验证器正确工作', async () => {
  const rules: FormRules = {
    field: {
      myNewRule: 'paramValue'
    }
  }

  const result = getAntDFormRules(rules)
  const fieldRules = result!.field as Rule[]
  const myRule = fieldRules.find(rule => rule.validator)

  // 成功情况
  await expect(myRule!.validator!({}, 'validValue', () => {})).resolves.toBeUndefined()

  // 失败情况
  await expect(myRule!.validator!({}, 'invalidValue', () => {})).rejects.toThrow('错误提示文案')
})

5. 执行测试

# 运行指定测试文件
npm test -- getAntDFormRules.spec.ts --run

# 运行所有表单相关测试
npm test -- useForm --run

# 查看测试覆盖率
npm test -- --coverage --run

代码示例

示例 1:简单的正则校验规则

添加一个汉字验证规则:

1. 类型定义 (AtmForm/index.ts):

export interface BuiltInRules {
  chineseCharacters?: boolean
}

2. 规则实现 (getAntDFormRules.ts):

const simpleRules: Record<string, Rule> = {
  chineseCharacters: {
    pattern: /^[\u4e00-\u9fff]+$/,
    message: '仅支持汉字输入',
    trigger: 'blur'
  }
}

3. 单元测试 (getAntDFormRules.spec.ts):

it('chineseCharacters 规则正确转换', () => {
  const rules: FormRules = {
    name: { chineseCharacters: true }
  }
  const result = getAntDFormRules(rules)
  expect(result!.name).toContainEqual({
    pattern: expect.any(RegExp),
    message: '仅支持汉字输入',
    trigger: 'blur'
  })
})

示例 2:带参数的自定义验证规则

添加一个字符串长度百分比验证规则(例如,验证实际输入不超过最大长度的80%):

1. 类型定义 (AtmForm/index.ts):

export interface BuiltInRules {
  percentageLength?: number // 0-100 表示百分比
}

2. 验证函数 (src/utils/validation/string.ts - 复用现有文件):

export function validatePercentageLength(value: unknown, percentage: number): boolean {
  if (!value || percentage <= 0 || percentage > 100) return true
  const maxLength = Math.ceil((value as string).length / (percentage / 100))
  return (value as string).length <= maxLength
}

3. 规则实现 (getAntDFormRules.ts):

// 在 getValidationRule 函数中添加
percentageLength: {
  validator: (_, value) => {
    if (isNumber(ruleValue)) {
      return validationHelper(
        validatePercentageLength(value, ruleValue),
        `输入长度不能超过最大值的${ruleValue}%`
      );
    }
    return Promise.reject(new Error('percentageLength 规则值必须为数字'));
  },
  trigger: rule?.trigger || 'blur',
  transform: rule?.transform
}

4. 单元测试 (getAntDFormRules.spec.ts):

it('percentageLength 验证器正确工作', async () => {
  const rules: FormRules = {
    field: { percentageLength: 80 }
  }
  const result = getAntDFormRules(rules)
  const fieldRules = result!.field as Rule[]
  const rule = fieldRules.find(r => r.validator)

  await expect(rule!.validator!({}, 'test', () => {})).resolves.toBeUndefined()

  await expect(rule!.validator!({}, 'x'.repeat(1000), () => {})).rejects.toThrow()
})

重要检查清单

  • 已在 BuiltInRules 接口中添加新属性(必须)
  • 已在 isBuiltInRule 函数的 ruleKeys 数组中添加对应属性名(必须)
  • 已在 getValidationRulesimpleRules 中实现规则逻辑(必须)
  • 如有新的验证函数,已添加到相应的 src/utils/validation/*.ts 文件(可选)
  • 已编写单元测试用例(必须)
  • 所有测试通过:npm test -- getAntDFormRules.spec.ts --run
  • 代码遵循项目的 TypeScript 和 ESLint 规范

关键注意事项

  1. isBuiltInRule 函数更新:这一步已在核心流程的第 2.1 步中详细说明,添加新规则属性后,必须getAntDFormRules.ts 中的 isBuiltInRule 函数的 ruleKeys 数组中添加新属性名,否则规则将被识别为无效对象。

  2. 错误消息本地化:所有错误消息应使用日语,可通过以下方式获取:

    • 使用 getMessageByCode() 调用已有的常数消息
    • 或直接编写日语文本
  3. 验证函数复用:优先复用 src/utils/validation/ 中已有的函数,减少代码重复和维护成本。

  4. 边界情况处理:验证函数必须正确处理以下情况:

    • nullundefined → 应返回 true(表示通过,因为非必填)
    • 空字符串 '' → 应返回 true(非必填字段)
    • 空数组 [] → 应返回 true
    • required: true 时才对空值进行拒绝
  5. 触发时机:根据规则类型选择合适的 trigger

    • 'blur' — 字符格式、文本长度等验证
    • 'change' — 文件上传、枚举选择等
    • 数组 ['blur', 'change'] — 需要多次触发的验证

常用验证函数参考

函数位置功能
validateDateFormatvalidation/date.ts验证日期格式
validateDateRangevalidation/date.ts验证日期在某个范围内
validateNumberRangevalidation/number.ts验证数值范围
validateEmailvalidation/string.ts验证邮箱格式
validateVisualLengthvalidation/string.ts验证可视长度(全角2字符、半角1字符计算)
valideFileExtensionvalidation/file.ts验证文件扩展名

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

excel-to-markdown

No summary provided by upstream source.

Repository SourceNeeds Review
General

perf-analyzer

No summary provided by upstream source.

Repository SourceNeeds Review
General

redmine-ticket-to-task

No summary provided by upstream source.

Repository SourceNeeds Review
General

component-scaffolder

No summary provided by upstream source.

Repository SourceNeeds Review