You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 18:54:01