forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
9.6 KiB
482 lines
9.6 KiB
|
3 months ago
|
# rule
|
||
|
|
|
||
|
|
> Form validation rule classes extending Element Plus validation schema.
|
||
|
|
|
||
|
|
## Source
|
||
|
|
|
||
|
|
**File**: `plugs/element/rule.ts`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
All rule classes follow Element Plus rule schema:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
required?: boolean;
|
||
|
|
trigger?: 'blur' | 'change' | ['blur', 'change'];
|
||
|
|
validator?: (rule: any, value: any, callback: Function) => void;
|
||
|
|
// ... other Element Plus rule properties
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
All classes include i18n integration via `plugs/i18n`.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SimpleRequired
|
||
|
|
|
||
|
|
Validates required fields with optional selection mode for dropdowns.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class SimpleRequired {
|
||
|
|
required = true;
|
||
|
|
trigger = 'blur' | 'change';
|
||
|
|
name?: string;
|
||
|
|
selection?: boolean;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
constructor(name?: string, selection?: boolean);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { SimpleRequired } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
// Text input
|
||
|
|
new SimpleRequired('Username').validator;
|
||
|
|
// -> { required: true, trigger: 'blur', ... }
|
||
|
|
|
||
|
|
// Dropdown selection
|
||
|
|
new SimpleRequired('Country', true).validator;
|
||
|
|
// -> { required: true, trigger: 'change', ... }
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Scenario | Message |
|
||
|
|
|----------|---------|
|
||
|
|
| Empty text input | `t('rule.pleaseEnter') + t(this.name).toLowerCase()` |
|
||
|
|
| Empty dropdown | `t('rule.pleaseSelect') + t(this.name).toLowerCase()` |
|
||
|
|
| Null/undefined | `t('rule.notNull')` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SimpleCharacter
|
||
|
|
|
||
|
|
Validates string length constraints.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class SimpleCharacter {
|
||
|
|
max: number;
|
||
|
|
min?: number;
|
||
|
|
trigger = 'blur';
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
constructor(max?: number, min?: number);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { SimpleCharacter } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
new SimpleCharacter(100); // Max 100 chars
|
||
|
|
new SimpleCharacter(10, 3); // 3-10 chars
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Scenario | Message Key | Example |
|
||
|
|
|----------|-------------|---------|
|
||
|
|
| Too long | `rule.maxLen` | `'Maximum 100 characters'` |
|
||
|
|
| Too short | `rule.minLen` | `'Minimum 3 characters'` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Character
|
||
|
|
|
||
|
|
Base class for regex pattern validation.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Character {
|
||
|
|
pattern: RegExp;
|
||
|
|
trigger = 'blur';
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
constructor(pattern: RegExp);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Character } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
new Character(/^[A-Z]{3}$/); // Exactly 3 uppercase letters
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Message
|
||
|
|
|
||
|
|
`t('rule.formatErr')` - generic format error when pattern fails.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## SimpleNumber
|
||
|
|
|
||
|
|
Validates integer input with optional range.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class SimpleNumber {
|
||
|
|
trigger = 'blur';
|
||
|
|
min?: number;
|
||
|
|
max?: number;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
constructor(min?: number, max?: number);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { SimpleNumber } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
new SimpleNumber(1, 100); // Integer 1-100
|
||
|
|
new SimpleNumber(0); // Non-negative integer
|
||
|
|
new SimpleNumber(); // Any integer
|
||
|
|
```
|
||
|
|
|
||
|
|
### Validation Rules
|
||
|
|
|
||
|
|
1. Must match `/^(0|-?[1-9]\d*)$/` (integers only, including 0)
|
||
|
|
2. Range check against `this.min` and `this.max`
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Scenario | Message |
|
||
|
|
|----------|---------|
|
||
|
|
| Non-integer | `t('rule.pleaseEnter') + t('rule.int').toLowerCase()` |
|
||
|
|
| Below min | `t('rule.min', [this.min])` |
|
||
|
|
| Above max | `t('rule.max', [this.max])` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Hexadecimal
|
||
|
|
|
||
|
|
Validates hexadecimal string input.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Hexadecimal {
|
||
|
|
trigger = 'blur';
|
||
|
|
min?: number;
|
||
|
|
max?: number;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
constructor(min?: number, max?: number);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Hexadecimal } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
new Hexadecimal(6, 8); // 6-8 character hex string
|
||
|
|
new Hexadecimal(); // Any length hex string
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pattern
|
||
|
|
|
||
|
|
`/^[0-9a-fA-F\s]+$/` - allows digits, letters a-f/A-F, and whitespace.
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Scenario | Message Key |
|
||
|
|
|----------|-------------|
|
||
|
|
| Invalid characters | `rule.hexadecimal` |
|
||
|
|
| Below min length | `rule.minLen` |
|
||
|
|
| Above max length | `rule.maxLen` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Geographic Coordinates
|
||
|
|
|
||
|
|
### Longitude
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Longitude extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `/^-?((0|1?[0-7]?[0-9]?)(([.][0-9]{1,6})?)|180(([.][0]{1,6})?))$/`
|
||
|
|
Range: -180 to 180
|
||
|
|
|
||
|
|
### Latitude
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Latitude extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `/^[\-\+]?((0|([1-8]\d?))(\.\d{1,10})?|90(\.0{1,10})?)$/`
|
||
|
|
Range: -90 to 90
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Longitude, Latitude } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
{ validator: new Longitude().validator }
|
||
|
|
{ validator: new Latitude().validator }
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Network Identifiers
|
||
|
|
|
||
|
|
### Email
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Email extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/`
|
||
|
|
|
||
|
|
### Phone
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Phone extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `/^(0|86|17951)?(13[0-9]|15[012356789]|17[0135678]|18[0-9]|14[57])[0-9]{8}$/`
|
||
|
|
Supports: China mobile numbers with optional prefixes (0, 86, 17951)
|
||
|
|
|
||
|
|
### Ipv4
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Ipv4 extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `/^((25[0-5]|2[0-4]\d|[01]?\d\d?)($|(?!\.$)\.)){4}$/`
|
||
|
|
|
||
|
|
### Ipv6
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Ipv6 extends Character;
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: Full IPv6 regex per RFC 5952.
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Email, Phone, Ipv4, Ipv6 } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
{ validator: new Email().validator }
|
||
|
|
{ validator: new Phone().validator }
|
||
|
|
{ validator: new Ipv4().validator }
|
||
|
|
{ validator: new Ipv6().validator }
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## IdCard
|
||
|
|
|
||
|
|
Chinese Resident ID card number validation.
|
||
|
|
|
||
|
|
### Signature
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class IdCard {
|
||
|
|
trigger = 'blur';
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Validation Steps
|
||
|
|
|
||
|
|
1. **Format check**: `/^\d{17}(\d|x)$/i`
|
||
|
|
2. **Area code validation**: First 2 digits map to Chinese provinces
|
||
|
|
3. **Birthdate validation**: Parses and validates YYYY-MM-DD format
|
||
|
|
4. **Checksum**: Uses weighted sum algorithm (ISO 7064:1983)
|
||
|
|
|
||
|
|
### Area Code Map (partial)
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const aCity = {
|
||
|
|
11: '北京', 12: '天津', 13: '河北', 14: '山西',
|
||
|
|
31: '上海', 32: '江苏', 33: '浙江', 34: '安徽',
|
||
|
|
51: '四川', 52: '贵州', 53: '云南', 91: '香港', ...
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Check | Message Key |
|
||
|
|
|-------|-------------|
|
||
|
|
| Invalid format | `rule.idCard.format` |
|
||
|
|
| Unknown area | `rule.idCard.area` |
|
||
|
|
| Invalid birthdate | `rule.idCard.birth` |
|
||
|
|
| Invalid checksum | `rule.idCard.error` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Passwords
|
||
|
|
|
||
|
|
### SimplePassword
|
||
|
|
|
||
|
|
Basic password validation (6-18 chars, no spaces).
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class SimplePassword {
|
||
|
|
required = true;
|
||
|
|
trigger = 'blur';
|
||
|
|
min = 8;
|
||
|
|
max = 16;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Password
|
||
|
|
|
||
|
|
Strong password (8-20 chars, must contain 0-9, a-z, A-Z).
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Password {
|
||
|
|
required = true;
|
||
|
|
trigger = 'blur';
|
||
|
|
min = 8;
|
||
|
|
max = 16;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
Pattern: `^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).*$`
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { SimplePassword, Password } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
{ validator: new SimplePassword().validator }
|
||
|
|
// Valid: 'abc123', 'password'
|
||
|
|
|
||
|
|
{ validator: new Password().validator }
|
||
|
|
// Valid: 'Pass1234', 'Abc12345'
|
||
|
|
// Invalid: 'password', '12345678', 'PASSWORD'
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Scenario | Message |
|
||
|
|
|----------|---------|
|
||
|
|
| Empty | `t('rule.pleaseEnter') + t('pwd.pwd').toLowerCase()` |
|
||
|
|
| Length (SimplePassword) | `t('pwd.length', [6, 18])` |
|
||
|
|
| Length (Password) | `t('pwd.length', [8, 20])` |
|
||
|
|
| Missing complexity | `t('pwd.required')` - "Must contain numbers and uppercase/lowercase" |
|
||
|
|
| Has space | `t('pwd.noSpace')` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Username
|
||
|
|
|
||
|
|
Alphanumeric username with underscore rules.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Username {
|
||
|
|
required = true;
|
||
|
|
trigger = 'blur';
|
||
|
|
min = 4;
|
||
|
|
max = 16;
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Rules
|
||
|
|
|
||
|
|
1. Length: 4-16 characters
|
||
|
|
2. Pattern: `/^[a-zA-Z0-9]{4,16}$/`
|
||
|
|
3. No leading underscore
|
||
|
|
4. No consecutive underscores
|
||
|
|
5. No trailing underscore
|
||
|
|
6. No spaces
|
||
|
|
|
||
|
|
### Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { Username } from 'plugs/element/rule';
|
||
|
|
|
||
|
|
{ validator: new Username().validator }
|
||
|
|
```
|
||
|
|
|
||
|
|
### Error Messages
|
||
|
|
|
||
|
|
| Rule | Message Key |
|
||
|
|
|------|-------------|
|
||
|
|
| Invalid chars/length | `rule.username.0` |
|
||
|
|
| Leading/trailing/consecutive underscores | `rule.username.1` |
|
||
|
|
| Contains space | `rule.username.2` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Name
|
||
|
|
|
||
|
|
Chinese and English name validation.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export class Name {
|
||
|
|
pattern = new RegExp('^[a-zA-Z\u4e00-\u9fa5]{1,10}$');
|
||
|
|
trigger = 'blur';
|
||
|
|
validator: (rule, value, callback) => void;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Rules
|
||
|
|
|
||
|
|
1. Length: 1-10 characters
|
||
|
|
2. Pattern: Letters and Chinese characters only
|
||
|
|
3. No numbers, no special characters
|
||
|
|
|
||
|
|
### Error Message
|
||
|
|
|
||
|
|
`t('rule.name')` - when pattern fails
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Quick Reference Table
|
||
|
|
|
||
|
|
| Class | Pattern | Trigger | Use Case |
|
||
|
|
|-------|---------|---------|----------|
|
||
|
|
| `SimpleRequired` | - | blur/change | Required fields |
|
||
|
|
| `SimpleCharacter` | length | blur | Text fields with limits |
|
||
|
|
| `Character` | regex | blur | Custom patterns |
|
||
|
|
| `SimpleNumber` | integer + range | blur | Number inputs |
|
||
|
|
| `Hexadecimal` | hex chars | blur | Color codes, offsets |
|
||
|
|
| `Longitude` | -180 to 180 | blur | GPS coordinates |
|
||
|
|
| `Latitude` | -90 to 90 | blur | GPS coordinates |
|
||
|
|
| `Email` | email format | blur | Email fields |
|
||
|
|
| `Phone` | CN mobile | blur | Phone fields |
|
||
|
|
| `Ipv4` | IPv4 format | blur | IP inputs |
|
||
|
|
| `Ipv6` | IPv6 format | blur | IP inputs |
|
||
|
|
| `IdCard` | CN ID | blur | ID number |
|
||
|
|
| `SimplePassword` | 6-18 chars | blur | Basic passwords |
|
||
|
|
| `Password` | 8-20 + complexity | blur | Strong passwords |
|
||
|
|
| `Username` | alphanumeric + underscore | blur | Login names |
|
||
|
|
| `Name` | letters + Chinese | blur | Person names |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Related
|
||
|
|
|
||
|
|
- `plugs/element/index.ts` exports all rule classes
|
||
|
|
- Uses `plugs/i18n` for localization
|
||
|
|
- Validator signature matches Element Plus `FormInstance.validate()`
|