- 修复路由守卫:未登录时直接跳转,不显示提示信息 - 修复API拦截器:401错误直接跳转,无需确认 - 移除不必要的ElMessageBox确认框 - 优化Token过期处理逻辑 - 修复文件管理API引入路径和URL前缀 - 修复调拨/回收管理API端点不匹配问题 - 修复通知管理API方法不匹配问题 - 统一系统配置API路径为单数形式 影响文件: - src/router/index.ts - src/api/request.ts - src/api/file.ts - src/api/index.ts 测试状态: - 前端构建通过 - 所有API路径已验证 - 登录流程测试通过 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
262 lines
6.2 KiB
TypeScript
262 lines
6.2 KiB
TypeScript
/**
|
|
* 动态字段验证器
|
|
* 根据字段配置进行表单验证
|
|
*/
|
|
|
|
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<string, string[]> {
|
|
const errors: Record<string, string[]> = {}
|
|
|
|
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<string, string> = {
|
|
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}验证失败`
|
|
}
|