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",
            },
          ],
    
        },
    
相关推荐
如若12318 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~1 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语1 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport1 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg1 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww1 小时前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_748254881 小时前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭2 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript