176 lines
6.1 KiB
TypeScript
176 lines
6.1 KiB
TypeScript
/**
|
||
* 验证规则编辑器
|
||
*/
|
||
|
||
import React from 'react';
|
||
import { Select, Input, InputNumber, Button, Space, Typography } from 'antd';
|
||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
|
||
import type { ValidationRule } from '../types';
|
||
|
||
const { Text } = Typography;
|
||
|
||
interface ValidationRuleEditorProps {
|
||
value?: ValidationRule[];
|
||
onChange?: (value: ValidationRule[]) => void;
|
||
}
|
||
|
||
const ValidationRuleEditor: React.FC<ValidationRuleEditorProps> = ({ value = [], onChange }) => {
|
||
const handleAddRule = () => {
|
||
const newRule: ValidationRule = {
|
||
type: 'required',
|
||
message: '',
|
||
trigger: 'blur',
|
||
};
|
||
onChange?.([...value, newRule]);
|
||
};
|
||
|
||
const handleDeleteRule = (index: number) => {
|
||
const newRules = value.filter((_, i) => i !== index);
|
||
onChange?.(newRules);
|
||
};
|
||
|
||
const handleRuleChange = (index: number, field: keyof ValidationRule, fieldValue: any) => {
|
||
const newRules = [...value];
|
||
newRules[index] = { ...newRules[index], [field]: fieldValue };
|
||
onChange?.(newRules);
|
||
};
|
||
|
||
const getRuleValueInput = (rule: ValidationRule, index: number) => {
|
||
switch (rule.type) {
|
||
case 'required':
|
||
return null;
|
||
case 'pattern':
|
||
return (
|
||
<Input
|
||
placeholder="输入正则表达式,如:^[a-zA-Z0-9]+$"
|
||
value={rule.value}
|
||
onChange={(e) => handleRuleChange(index, 'value', e.target.value)}
|
||
/>
|
||
);
|
||
case 'min':
|
||
case 'max':
|
||
case 'minLength':
|
||
case 'maxLength':
|
||
return (
|
||
<InputNumber
|
||
style={{ width: '100%' }}
|
||
placeholder={`请输入${rule.type === 'min' || rule.type === 'minLength' ? '最小' : '最大'}值`}
|
||
value={rule.value}
|
||
onChange={(val) => handleRuleChange(index, 'value', val)}
|
||
/>
|
||
);
|
||
case 'email':
|
||
case 'url':
|
||
case 'phone':
|
||
case 'idCard':
|
||
return null;
|
||
case 'custom':
|
||
return (
|
||
<Input
|
||
placeholder="输入自定义验证函数名"
|
||
value={rule.value}
|
||
onChange={(e) => handleRuleChange(index, 'value', e.target.value)}
|
||
/>
|
||
);
|
||
default:
|
||
return null;
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div>
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
|
||
<Text strong>验证规则</Text>
|
||
<Button type="dashed" size="small" icon={<PlusOutlined />} onClick={handleAddRule}>
|
||
添加规则
|
||
</Button>
|
||
</div>
|
||
|
||
{value.length === 0 ? (
|
||
<div style={{ padding: '24px 0', textAlign: 'center', color: '#8c8c8c', fontSize: 12 }}>
|
||
暂无验证规则,点击上方按钮添加
|
||
</div>
|
||
) : (
|
||
<Space direction="vertical" style={{ width: '100%' }} size="middle">
|
||
{value.map((rule, index) => (
|
||
<div
|
||
key={index}
|
||
style={{
|
||
padding: 12,
|
||
border: '1px solid #e8e8e8',
|
||
borderRadius: 4,
|
||
background: '#fafafa',
|
||
}}
|
||
>
|
||
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
|
||
<Text style={{ fontSize: 12, color: '#666' }}>规则 {index + 1}</Text>
|
||
<Button
|
||
type="text"
|
||
size="small"
|
||
danger
|
||
icon={<DeleteOutlined />}
|
||
onClick={() => handleDeleteRule(index)}
|
||
/>
|
||
</div>
|
||
|
||
<Space direction="vertical" style={{ width: '100%' }} size="small">
|
||
<div>
|
||
<Text style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>验证类型</Text>
|
||
<Select
|
||
style={{ width: '100%' }}
|
||
value={rule.type}
|
||
onChange={(val) => handleRuleChange(index, 'type', val)}
|
||
>
|
||
<Select.Option value="required">必填</Select.Option>
|
||
<Select.Option value="pattern">正则表达式</Select.Option>
|
||
<Select.Option value="min">最小值</Select.Option>
|
||
<Select.Option value="max">最大值</Select.Option>
|
||
<Select.Option value="minLength">最小长度</Select.Option>
|
||
<Select.Option value="maxLength">最大长度</Select.Option>
|
||
<Select.Option value="email">邮箱格式</Select.Option>
|
||
<Select.Option value="url">URL格式</Select.Option>
|
||
<Select.Option value="phone">手机号格式</Select.Option>
|
||
<Select.Option value="idCard">身份证格式</Select.Option>
|
||
<Select.Option value="custom">自定义验证</Select.Option>
|
||
</Select>
|
||
</div>
|
||
|
||
{getRuleValueInput(rule, index) && (
|
||
<div>
|
||
<Text style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>规则值</Text>
|
||
{getRuleValueInput(rule, index)}
|
||
</div>
|
||
)}
|
||
|
||
<div>
|
||
<Text style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>错误提示</Text>
|
||
<Input
|
||
placeholder="请输入验证失败时的提示信息"
|
||
value={rule.message}
|
||
onChange={(e) => handleRuleChange(index, 'message', e.target.value)}
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<Text style={{ fontSize: 12, marginBottom: 4, display: 'block' }}>触发时机</Text>
|
||
<Select
|
||
style={{ width: '100%' }}
|
||
value={rule.trigger}
|
||
onChange={(val) => handleRuleChange(index, 'trigger', val)}
|
||
>
|
||
<Select.Option value="blur">失去焦点</Select.Option>
|
||
<Select.Option value="change">值改变</Select.Option>
|
||
</Select>
|
||
</div>
|
||
</Space>
|
||
</div>
|
||
))}
|
||
</Space>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ValidationRuleEditor;
|
||
|