/** * 字段验证规则配置和验证逻辑 * * 支持的验证规则: * - required: 必填验证 * - maxLength: 最大长度(text/textarea) * - minLength: 最小长度(text/textarea) * - min: 最小值(number) * - max: 最大值(number) * - pattern: 正则表达式验证 * - customMessage: 自定义错误提示 */ export interface ValidationRule { // 必填验证 required?: boolean requiredMessage?: string // 长度验证(text/textarea) minLength?: number minLengthMessage?: string maxLength?: number maxLengthMessage?: string // 数值范围验证(number) min?: number minMessage?: string max?: number maxMessage?: string // 正则表达式验证 pattern?: string patternMessage?: string // 通用自定义错误提示 customMessage?: string } export interface ValidationResult { valid: boolean errors: string[] } /** * 解析验证规则JSON字符串 */ export function parseValidationRules(validationsJson: string | null | undefined): ValidationRule | null { if (!validationsJson || validationsJson.trim() === '') { return null } try { const parsed = JSON.parse(validationsJson) if (typeof parsed !== 'object' || parsed === null) { return null } return parsed as ValidationRule } catch { console.warn('[FieldValidation] Failed to parse validation rules:', validationsJson) return null } } /** * 序列化验证规则为JSON字符串 */ export function serializeValidationRules(rules: ValidationRule | null): string { if (!rules) { return '' } // 清理空值 const cleanedRules: ValidationRule = {} if (rules.required) cleanedRules.required = true if (rules.requiredMessage) cleanedRules.requiredMessage = rules.requiredMessage if (typeof rules.minLength === 'number' && rules.minLength > 0) { cleanedRules.minLength = rules.minLength if (rules.minLengthMessage) cleanedRules.minLengthMessage = rules.minLengthMessage } if (typeof rules.maxLength === 'number' && rules.maxLength > 0) { cleanedRules.maxLength = rules.maxLength if (rules.maxLengthMessage) cleanedRules.maxLengthMessage = rules.maxLengthMessage } if (typeof rules.min === 'number') { cleanedRules.min = rules.min if (rules.minMessage) cleanedRules.minMessage = rules.minMessage } if (typeof rules.max === 'number') { cleanedRules.max = rules.max if (rules.maxMessage) cleanedRules.maxMessage = rules.maxMessage } if (rules.pattern) { cleanedRules.pattern = rules.pattern if (rules.patternMessage) cleanedRules.patternMessage = rules.patternMessage } if (rules.customMessage) cleanedRules.customMessage = rules.customMessage // 如果没有任何规则,返回空字符串 if (Object.keys(cleanedRules).length === 0) { return '' } return JSON.stringify(cleanedRules) } /** * 验证单个字段值 */ export function validateFieldValue( value: unknown, fieldType: string, rules: ValidationRule | null, fieldLabel?: string ): ValidationResult { const errors: string[] = [] const label = fieldLabel || '此字段' if (!rules) { return { valid: true, errors: [] } } const stringValue = value === null || value === undefined ? '' : String(value).trim() const isEmpty = stringValue === '' // 必填验证 if (rules.required && isEmpty) { errors.push(rules.requiredMessage || `${label}不能为空`) // 如果必填且为空,不继续其他验证 return { valid: false, errors } } // 如果值为空且非必填,跳过其他验证 if (isEmpty) { return { valid: true, errors: [] } } // 文本长度验证 if (fieldType === 'text' || fieldType === 'textarea') { if (typeof rules.minLength === 'number' && stringValue.length < rules.minLength) { errors.push(rules.minLengthMessage || `${label}长度不能少于${rules.minLength}个字符`) } if (typeof rules.maxLength === 'number' && stringValue.length > rules.maxLength) { errors.push(rules.maxLengthMessage || `${label}长度不能超过${rules.maxLength}个字符`) } } // 数值范围验证 if (fieldType === 'number') { const numValue = parseFloat(stringValue) if (isNaN(numValue)) { errors.push(`${label}必须是有效的数字`) } else { if (typeof rules.min === 'number' && numValue < rules.min) { errors.push(rules.minMessage || `${label}不能小于${rules.min}`) } if (typeof rules.max === 'number' && numValue > rules.max) { errors.push(rules.maxMessage || `${label}不能大于${rules.max}`) } } } // 正则表达式验证 if (rules.pattern) { try { const regex = new RegExp(rules.pattern) if (!regex.test(stringValue)) { errors.push(rules.patternMessage || `${label}格式不正确`) } } catch (e) { console.warn('[FieldValidation] Invalid regex pattern:', rules.pattern) } } return { valid: errors.length === 0, errors } } /** * 验证多个字段 */ export function validateFields( fields: Array<{ key: string label: string type: string validations?: string | null value: unknown }> ): Map { const results = new Map() for (const field of fields) { const rules = parseValidationRules(field.validations) const result = validateFieldValue(field.value, field.type, rules, field.label) results.set(field.key, result) } return results } /** * 检查验证规则是否有效(用于保存模板时) */ export function validateValidationRules(rules: ValidationRule): { valid: boolean; error?: string } { // 检查长度规则冲突 if (typeof rules.minLength === 'number' && typeof rules.maxLength === 'number') { if (rules.minLength > rules.maxLength) { return { valid: false, error: '最小长度不能大于最大长度' } } } // 检查数值范围规则冲突 if (typeof rules.min === 'number' && typeof rules.max === 'number') { if (rules.min > rules.max) { return { valid: false, error: '最小值不能大于最大值' } } } // 检查正则表达式是否有效 if (rules.pattern) { try { new RegExp(rules.pattern) } catch { return { valid: false, error: '正则表达式格式无效' } } } return { valid: true } } /** * 获取字段类型支持的验证规则 */ export function getSupportedValidations(fieldType: string): string[] { const common = ['required'] switch (fieldType) { case 'text': case 'textarea': return [...common, 'minLength', 'maxLength', 'pattern'] case 'number': return [...common, 'min', 'max'] case 'select': case 'checkbox': case 'radio': return common case 'date': return common case 'file': case 'image': return common default: return common } } /** * 默认验证规则 */ export const DEFAULT_VALIDATION_RULES: ValidationRule = { required: false, minLength: undefined, maxLength: undefined, min: undefined, max: undefined, pattern: undefined, }