/** * 动态字段验证器 * 根据字段配置进行表单验证 */ import type { FieldConfig, ValidationResult, FormData } from '@/types/form' /** * 验证单个字段 * @param value 字段值 * @param field 字段配置 * @param allFormData 所有表单数据(用于自定义验证) * @returns 验证结果 */ export function validateField( value: any, field: FieldConfig, allFormData: FormData = {} ): ValidationResult { const errors: string[] = [] // 1. 必填验证 if (field.required) { if (value === undefined || value === null || value === '') { errors.push(`${field.label}不能为空`) return { isValid: false, errors } } } // 如果值为空且非必填,则跳过后续验证 if (!field.required && (value === undefined || value === null || value === '')) { return { isValid: true, errors: [] } } // 2. 根据字段类型进行验证 switch (field.fieldType) { case 'text': case 'textarea': validateText(value, field, errors) break case 'number': validateNumber(value, field, errors) break case 'email': validateEmail(value, field, errors) break case 'phone': validatePhone(value, field, errors) break case 'url': validateUrl(value, field, errors) break case 'select': case 'multiselect': case 'boolean': case 'date': case 'tree': // 这些类型一般不需要额外验证 break } // 3. 自定义正则验证 if (field.validationRules?.pattern && value) { try { const regex = new RegExp(field.validationRules.pattern) if (!regex.test(value)) { errors.push(field.validationRules.customMessage || `${field.label}格式不正确`) } } catch (error) { console.error('正则表达式验证失败:', error) } } // 4. 自定义验证函数 if (field.validationRules?.custom) { try { const result = field.validationRules.custom(value, allFormData) if (result !== true) { errors.push(typeof result === 'string' ? result : `${field.label}验证失败`) } } catch (error) { console.error('自定义验证失败:', error) errors.push(`${field.label}验证出错`) } } return { isValid: errors.length === 0, errors } } /** * 验证所有字段 * @param data 表单数据 * @param fields 字段配置列表 * @returns 字段级错误信息 */ export function validateFields( data: FormData, fields: FieldConfig[] ): Record { const errors: Record = {} fields.forEach((field) => { const value = data[field.name] const result = validateField(value, field, data) if (!result.isValid) { errors[field.name] = result.errors } }) return errors } /** * 文本类型验证 */ function validateText(value: any, field: FieldConfig, errors: string[]): void { if (typeof value !== 'string') { errors.push(`${field.label}必须是文本`) return } const { min, max } = field.validationRules || {} if (min && value.length < min) { errors.push(`${field.label}长度不能少于${min}个字符`) } if (max && value.length > max) { errors.push(`${field.label}长度不能超过${max}个字符`) } } /** * 数字类型验证 */ function validateNumber(value: any, field: FieldConfig, errors: string[]): void { const num = Number(value) if (isNaN(num)) { errors.push(`${field.label}必须是数字`) return } const { min, max } = field.validationRules || {} if (min !== undefined && num < min) { errors.push(`${field.label}不能小于${min}`) } if (max !== undefined && num > max) { errors.push(`${field.label}不能大于${max}`) } } /** * 邮箱验证 */ function validateEmail(value: any, field: FieldConfig, errors: string[]): void { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ if (!emailRegex.test(value)) { errors.push(`${field.label}邮箱格式不正确`) } } /** * 手机号验证 */ function validatePhone(value: any, field: FieldConfig, errors: string[]): void { // 中国大陆手机号验证 const phoneRegex = /^1[3-9]\d{9}$/ if (!phoneRegex.test(value)) { errors.push(`${field.label}手机号格式不正确`) } } /** * URL验证 */ function validateUrl(value: any, field: FieldConfig, errors: string[]): void { try { new URL(value) } catch { errors.push(`${field.label}URL格式不正确`) } } /** * 创建VeeValidate验证规则 * @param field 字段配置 * @returns VeeValidate规则对象 */ export function createValidationRule(field: FieldConfig): any { const rules: any = {} // 必填规则 if (field.required) { rules.required = true } // 根据字段类型添加规则 switch (field.fieldType) { case 'text': case 'textarea': if (field.validationRules?.min) { rules.min = field.validationRules.min } if (field.validationRules?.max) { rules.max = field.validationRules.max } if (field.validationRules?.pattern) { rules.regex = new RegExp(field.validationRules.pattern) } break case 'number': if (field.validationRules?.min !== undefined) { rules.min_value = field.validationRules.min } if (field.validationRules?.max !== undefined) { rules.max_value = field.validationRules.max } break case 'email': rules.email = true break case 'phone': rules.regex = /^1[3-9]\d{9}$/ break case 'url': rules.url = true break } return rules } /** * 获取字段错误消息 * @param field 字段配置 * @param errorType 错误类型 * @returns 错误消息 */ export function getFieldErrorMessage(field: FieldConfig, errorType: string): string { const messages: Record = { required: `${field.label}不能为空`, min: `${field.label}长度/值不能小于${field.validationRules?.min}`, max: `${field.label}长度/值不能大于${field.validationRules?.max}`, email: `${field.label}邮箱格式不正确`, url: `${field.label}URL格式不正确`, regex: `${field.label}格式不正确` } return messages[errorType] || `${field.label}验证失败` }