planFieldValidation.js
5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/**
* 动态验证系统
*
* @description 提供可配置的字段验证功能,支持同步/异步验证
* @module utils/planFieldValidation
* @author Claude Code
* @created 2026-02-14
*/
/**
* 验证结果类型
* @typedef {Object} ValidationResult
* @property {boolean} valid - 是否通过
* @property {string} [error] - 错误信息
*/
/**
* 内置验证规则
*/
export const VALIDATION_RULES = {
REQUIRED: 'required',
MIN: 'min',
MAX: 'max',
RANGE: 'range',
PATTERN: 'pattern',
CUSTOM: 'custom'
}
/**
* 执行字段验证
*
* @param {*} value - 待验证的值
* @param {Object} rules - 验证规则配置
* @param {Object} context - 验证上下文(包含 formData 等)
* @returns {ValidationResult} 验证结果
*
* @example
* // 必填验证
* validateField(null, { required: true })
* // => { valid: false, error: '该字段为必填' }
*
* // 最小长度验证
* validateField('ab', { min: 3 })
* // => { valid: false, error: '至少需要3个字符' }
*
* // 自定义验证
* validateField(25, { custom: (value) => value >= 18 })
* // => { valid: false, error: '年龄必须满18岁' }
*/
export function validateField(value, rules = {}, context = {}) {
// 必填检查
if (rules.required) {
// 函数形式的 required - 执行自定义验证
if (typeof rules.required === 'function') {
const result = rules.required(value, context)
if (!result) {
return {
valid: false,
error: rules.requiredMessage || '该字段为必填'
}
}
} else if (!isNotEmpty(value)) {
// 布尔值形式的 required - 检查是否为空
return {
valid: false,
error: rules.requiredMessage || '该字段为必填'
}
}
}
// 最小长度
if (rules.min !== undefined && value && value.length < rules.min) {
return {
valid: false,
error: rules.minMessage || `至少需要${rules.min}个字符`
}
}
// 最大长度
if (rules.max !== undefined && value && value.length > rules.max) {
return {
valid: false,
error: rules.maxMessage || `最多${rules.max}个字符`
}
}
// 数值范围
if (rules.range) {
const numValue = parseFloat(value)
if (Number.isNaN(numValue)) {
return {
valid: false,
error: '请输入有效数字'
}
}
const [min, max] = rules.range
if ((min !== undefined && numValue < min) || (max !== undefined && numValue > max)) {
return {
valid: false,
error: rules.rangeMessage || `请输入${min || 0}-${max || '∞'}之间的数值`
}
}
}
// 正则表达式
if (rules.pattern && !new RegExp(rules.pattern).test(value)) {
return {
valid: false,
error: rules.patternMessage || '格式不正确'
}
}
// 自定义验证函数
if (rules.custom && typeof rules.custom === 'function') {
const result = rules.custom(value, context)
if (!result) {
return {
valid: false,
error: rules.customMessage || '验证失败'
}
}
}
// 全部通过
return { valid: true }
}
/**
* 批量验证表单数据
*
* @param {Object} formData - 表单数据
* @param {Object} fieldDefinitions - 字段定义
* @returns {Object} 验证结果 { valid: boolean, errors: Object }
*
* @example
* const result = validateForm(formData, fieldDefinitions)
* if (result.valid) {
* // 提交
* } else {
* // 显示错误
* console.log(result.errors)
* }
*/
export function validateForm(formData, fieldDefinitions) {
const errors = {}
for (const [key, value] of Object.entries(formData)) {
// 跳过空值(如果非必填)
if (value === null || value === undefined || value === '') {
const definition = fieldDefinitions[key]
if (definition?.validation) {
const rules = definition.validation
// 检查是否真正的必填:先调用 required 规则判断
const isRequired = rules.required ? typeof rules.required === 'function' ? rules.required(value) : true : false
// 如果是必填字段且值为空,验证失败
if (isRequired && !isNotEmpty(value)) {
errors[key] = '该字段为必填'
}
}
continue
}
// 验证非空值
const definition = fieldDefinitions[key]
if (definition?.validation) {
const rules = definition.validation
// 将 required 规则放在第一位,确保它被优先检查
const orderedRules = {}
if (rules.required) {
orderedRules.required = rules.required
}
for (const ruleKey in rules) {
if (ruleKey !== 'required') {
orderedRules[ruleKey] = rules[ruleKey]
}
}
const result = validateField(value, orderedRules, { formData, ...formData })
if (!result.valid) {
errors[key] = result.error
}
}
}
return {
valid: Object.keys(errors).length === 0,
errors
}
}
/**
* 检查值是否非空
*
* @param {*} value - 待检查的值
* @returns {boolean} 是否非空
*/
export function isNotEmpty(value) {
if (value === null || value === undefined) return false
if (typeof value === 'string' && value.trim() === '') return false
if (Array.isArray(value) && value.length === 0) return false
return true
}