Angular 中意大利 Fiscal Code 姓名字段校验方法咨询
Angular模板驱动表单校验意大利财政税码姓名匹配方案
一、意大利税码姓名字段生成规则
税码前6位的生成逻辑为:
- 前3位:取自姓氏的辅音,按原有顺序排列,不足3位时依次补充元音,超过3位取前3位,忽略姓名中的空格、连字符等特殊字符
- 后3位:取自名字的辅音,按原有顺序排列,若辅音≥4个则跳过第2个辅音取第1、3、4位,不足3位依次补充元音,超过3位取前3位
示例:姓氏Rossi(辅音R/S/S → 前3位RSS),名字Lorenzo(辅音L/R/N → 后3位LRN),组合后前6位为RSSLRN,与示例税码前缀匹配。
二、具体实现步骤
1. 新增姓名编码提取工具函数
新建fiscal-code.utils.ts文件,编写核心生成逻辑:
// 提取辅音,过滤元音 const getConsonants = (str: string): string => str.toUpperCase().replace(/[^BCDFGHJKLMNPQRSTVWXYZ]/g, ''); // 提取元音 const getVowels = (str: string): string => str.toUpperCase().replace(/[^AEIOU]/g, ''); // 生成姓氏对应的3位编码 export function generateSurnameCode(surname: string): string { const cleaned = surname.replace(/[^a-zA-Z]/g, ''); const consonants = getConsonants(cleaned); const vowels = getVowels(cleaned); let code = consonants; // 不足3位补元音,无字符补X while (code.length < 3) { code += vowels[code.length - consonants.length] || 'X'; } return code.slice(0, 3); } // 生成名字对应的3位编码 export function generateNameCode(name: string): string { const cleaned = name.replace(/[^a-zA-Z]/g, ''); const consonants = getConsonants(cleaned); const vowels = getVowels(cleaned); let code = consonants; // 辅音超过3个,跳过第二个辅音 if (consonants.length >= 4) { code = consonants[0] + consonants.slice(2, 4); } // 不足3位补元音,无字符补X while (code.length < 3) { code += vowels[code.length - consonants.length] || 'X'; } return code.slice(0, 3); } // 校验税码前6位是否与姓名匹配 export function validateFiscalCodeName(cf: string, name: string, surname: string): boolean { // 11位数字税号无需校验姓名 if (/^\d{11}$/.test(cf)) return true; if (cf.length < 6) return false; const cfPrefix = cf.slice(0, 6).toUpperCase(); const calculatedPrefix = generateSurnameCode(surname) + generateNameCode(name); return cfPrefix === calculatedPrefix; }
2. 编写模板驱动表单自定义校验指令
新建cf-name-validator.directive.ts文件:
import { Directive, Input } from '@angular/core'; import { NG_VALIDATORS, Validator, AbstractControl, ValidationErrors } from '@angular/forms'; import { validateFiscalCodeName } from './fiscal-code.utils'; @Directive({ selector: '[cfNameValidate]', providers: [{ provide: NG_VALIDATORS, useExisting: CfNameValidatorDirective, multi: true }] }) export class CfNameValidatorDirective implements Validator { @Input('cfName') name: string = ''; @Input('cfSurname') surname: string = ''; validate(control: AbstractControl): ValidationErrors | null { const cfValue = control.value || ''; // 空值、姓名未填时不触发校验 if (!cfValue || !this.name || !this.surname) return null; const isValid = validateFiscalCodeName(cfValue, this.name, this.surname); return isValid ? null : { cfNameMismatch: true }; } }
完成后需要在对应业务模块的declarations数组中注册该指令。
3. 修改原表单代码
调整模板代码,新增自定义校验和错误提示:
<div class="col-4"> <div>Codice fiscale</div> <span class="p-float-label"> <input type="text" pInputText placeholder="Inserisci codice fiscale" name="codiceFiscale" [(ngModel)]="data.fiscalCode" pattern="^([A-Za-z]{6}[0-9lmnpqrstuvLMNPQRSTUV]{2}[abcdehlmprstABCDEHLMPRST]{1}[0-9lmnpqrstuvLMNPQRSTUV]{2}[A-Za-z]{1}[0-9lmnpqrstuvLMNPQRSTUV]{3}[A-Za-z]{1})$|([0-9]{11})$" onKeyPress="if(this.value.length==16) return false;" cfNameValidate [cfName]="data.name" [cfSurname]="data.surname" #codiceFiscale="ngModel" /> </span> <!-- 错误提示 --> <div *ngIf="codiceFiscale.invalid && (codiceFiscale.dirty || codiceFiscale.touched)" class="text-danger mt-1"> <div *ngIf="codiceFiscale.errors?.['pattern']">税码格式不正确</div> <div *ngIf="codiceFiscale.errors?.['cfNameMismatch']">税码与姓名不匹配</div> </div> </div>
注意:将
[cfName]和[cfSurname]绑定的值替换为你实际存储名字、姓氏的变量即可。
三、测试验证
传入示例值:
- 姓氏:Rossi
- 名字:Lorenzo
- 税码:RSSLRN87A14L219U
工具函数生成的前缀为RSSLRN,与税码前6位一致,校验通过。
内容的提问来源于stack exchange,提问作者Sophia
相关产品推荐
相关产品推荐

