vue中如何自定义Form表单rules校验方法(手机号/座机号、身份证号/社会统一信代码校验,支持多个,以英文逗号分隔)

  • 需求描述:
    1.相对方联系方式需要支持手机号、座机号填入保存,可能会填写多个都需要校验是否能通过
    2.相对方统一社会信用代码/身份证号码填入,可以是身份证号码也可以是社会统一信用代码,都得支持校验通过,并且容许填入多个以英文逗号分隔

1.首先定义一个js文件,用来编写上方对应代码(validateFromRules.js)

复制代码
// 验证手机号/座机号
// isMultiple区分多个/一个 true为多个 false为一个
// isSingleType 是否只验证一种类型的证件号 默认为 false
// type 验证的证件号类型,可以是 'phone'(手机号码)、'landline'(座机号码)或 'both'(两者都验证),默认为 'both'
export function validatePhone(isMultiple = true, isSingleType = false, type = 'both') {
  return function (rule, value, callback) {
    if (!value) {
      callback(new Error("相对方(经办人联系电话)不能为空"));
      return;
    }

    const phonePattern = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
    const landlinePattern = /^(\d{3,4}-)?\d{7,8}$/;

    if (isMultiple) {
      const phones = value.split(",").map((v) => v.trim());
      const errors = [];

      phones.forEach((phone) => {
        if (type === 'phone' && !phonePattern.test(phone)) {
          errors.push(`值 "${phone}" 无效: 请输入正确的手机号码`);
        } else if (type === 'landline' && !landlinePattern.test(phone)) {
          errors.push(`值 "${phone}" 无效: 请输入正确的座机号码`);
        } else if (type === 'both') {
          if (!phonePattern.test(phone) && !landlinePattern.test(phone)) {
            errors.push(`值 "${phone}" 无效: 请输入正确的手机号码或座机号码`);
          }
        }
      });

      if (errors.length > 0) {
        callback(new Error(errors.join("\n")));
      } else {
        callback();
      }
    } else {
      if (type === 'phone' && !phonePattern.test(value)) {
        callback(new Error("请输入正确的手机号码"));
      } else if (type === 'landline' && !landlinePattern.test(value)) {
        callback(new Error("请输入正确的座机号码"));
      } else if (type === 'both') {
        if (!phonePattern.test(value) && !landlinePattern.test(value)) {
          callback(new Error("请输入正确的手机号码或座机号码"));
        } else {
          callback();
        }
      }
    }
  };
}


// 社会统一信代码/身份证号
// isMultiple区分多个/一个 true为多个 false为一个
// isSingleType 是否只验证一种类型的证件号 默认为 false
// type 验证的证件号类型,可以是 'idCard'(身份证号)、'socialCreditCode'(统一社会信用代码)或 'both'(两者都验证),默认为 'both'
export function validateSocialId(isMultiple = true, isSingleType = false, type = 'both') {
  return function (rule, value, callback) {
    if (!value) {
      callback(new Error("统一社会信用代码/身份证号码不能为空!"));
      return;
    }

    const values = isMultiple ? value.split(",").map((v) => v.trim()) : [value];

    const errors = [];
    values.forEach((val) => {
      if (type === 'idCard' && !isIDCard(val)) {
        errors.push(`值 "${val}" 无效: 不符合身份证号码的格式`);
      } else if (type === 'socialCreditCode' && !isSocialCreditCode(val)) {
        errors.push(`值 "${val}" 无效: 不符合统一社会信用代码的格式`);
      } else if (type === 'both') {
        if (isIDCard(val)) {
          validateIDCard({}, val, (error) => {
            if (error) {
              errors.push(`值 "${val}" 无效: ${error.message}`);
            }
          });
        } else if (isSocialCreditCode(val)) {
          CheckSocialCreditCode({}, val, (error) => {
            if (error) {
              errors.push(`值 "${val}" 无效: ${error.message}`);
            }
          });
        } else {
          errors.push(
            `值 "${val}" 无效: 不符合统一社会信用代码或身份证号码的格式`
          );
        }
      }
    });

    if (errors.length > 0) {
      callback(new Error(errors.join("\n")));
    } else {
      callback();
    }
  };
}

function isSocialCreditCode(code) {
  return code.length === 18 && /^[0-9A-Z]+$/.test(code);
}

function isIDCard(idCard) {
  return idCard.length === 18 && /^[0-9Xx]+$/.test(idCard);
}

function CheckSocialCreditCode(rule, Code, callback) {
  if (Code.length !== 18) {
    callback(new Error("不是有效的统一社会信用代码!"));
    return;
  }

  const validChars = /^[0-9A-Z]+$/;
  if (!validChars.test(Code)) {
    callback(new Error("统一社会信用代码包含无效字符!"));
    return;
  }

  let total = 0;
  const weightedfactors = [
    1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28,
  ];
  const str = "0123456789ABCDEFGHJKLMNPQRTUWXY";

  for (let i = 0; i < Code.length - 1; i++) {
    const Ancodevalue = str.indexOf(Code.charAt(i));
    total += Ancodevalue * weightedfactors[i];
  }

  let logiccheckcode = 31 - (total % 31);
  if (logiccheckcode === 31) {
    logiccheckcode = 0;
  }
  const checkCode = str.charAt(logiccheckcode);

  const inputCheckCode = Code.charAt(17);
  if (inputCheckCode !== checkCode) {
    callback(new Error("不是有效的统一社会信用代码!"));
  } else {
    callback();
  }
}

function validateIDCard(rule, idCard, callback) {
  if (idCard.length !== 18) {
    callback(new Error("不是有效的身份证号码!"));
    return;
  }

  const validIdCardChars = /^[0-9Xx]+$/;
  if (!validIdCardChars.test(idCard)) {
    callback(new Error("身份证号码包含无效字符!"));
    return;
  }

  const weightFactors = [
    7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,
  ];
  const verifyCodes = "10X98765432";
  let sum = 0;

  for (let i = 0; i < 17; i++) {
    sum += parseInt(idCard.charAt(i), 10) * weightFactors[i];
  }

  const checkCode = verifyCodes[sum % 11];
  if (idCard.charAt(17).toUpperCase() !== checkCode) {
    callback(new Error("不是有效的身份证号码!"));
  } else {
    callback();
  }
}

2.在main.js中引入并注册成全局方法

复制代码
// 验证表单rules的js文件
import {
  validatePhone,
  validateSocialId
} from './utils/validateFromRules'; // 引入封装的验证方法

Vue.prototype.$validatePhone = validatePhone;
Vue.prototype.$validateSocialId  = validateSocialId ;

3.在对应的vue界面中使用,方法支持传入三个参数

  • 3.1第一个参数 isMultiple 是否容许传入多个参数,true:传入多个 false:只容许有一个

  • 3.2第二个参数 isSingleType 是否只验证一种类型 默认为 false,可以选择两种都验证,比如同时填入手机号和座机号

  • 3.3第三个参数 type 验证的证件号类型,可以是 'phone'(手机号码)、'landline'(座机号码)或 'both'(两者都验证),默认为 'both'

    复制代码
     rules: {
          partyBPhone: [
            {
              required: true,
              message: "相对方(经办人联系电话)不能为空",
              trigger: "blur",
            },
            {
              validator: this.$validatePhone(true, false, "both"),
              trigger: "blur",
            },
          ],
          partyBSocialId: [
            {
              required: true,
              message: "统一社会信用代码/身份证号码不能为空",
              trigger: "blur",
            },
            {
              validator: this.$validateSocialId(true, false, "both"),
              trigger: "blur",
            },
          ],
    
        },
相关推荐
mldong42 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen6 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu6 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss