前端 通用的前端效驗工具2020-05-19 - 戴向天

大家好!我叫戴向天

QQ羣:602504799

QQ:809002582

/**
	@Author 戴向天
	@English Name Clover
	@Frist date 2019-08-08
	@Last update date 2020-05-19
	@Last date 2020-05-19
	@Tips
		Ver option's type undetermined
			date & json & funciton

	@arguments

		method one
			option
				data:需要判斷的數據 json | array | string | number | null | boolean

				ver:[	需要效驗的字段
						'name',		//需要效驗的key名
					{
						key:'age',		//需要效驗的key名
						type:'number',	//判斷數據是否爲指定爲類型	type的參數:String | number | string | array | date | tel | zuoji(座機|固話) | json | funciton | email
						tips:'請輸入正確的年齡',//數據錯誤回饋信息
					},{
						key:'createTime',
						type:'date'
					},{
						key:'telephone',
						type:'tel'
					},{
						key:'note',
						type:'string',
						trim:true
					}]

		method two
			arg[0]: 需要判斷的數據 json | array | string | number | null | boolean
			arg[1]: 需要效驗的字段 array | string | number | boolean

	Tips: 如果是ts文件 請把參數改爲 (a: any = null, b: any = null)
	
	2019-10-08 Update log 
		1.修復判斷不嚴謹的bug 不能深入查詢進行判斷
		2.新增type類型:date、json、function、
		3.當需要判斷的字段數據裏面沒有的時候會進行提錯誤,沒有指定的字段名
		4.ver 新增單字符串的字段
		
	2020-05-19 Update log 
	
		1.可多個效驗條件 --- type可爲數組,字符串 
		2.新增效驗條件: 漢字(純,包含),特殊字符串(包含),字母(純,包含),身份證號碼 
		3.加上限制提交(類似於禁止條件,例如禁止有漢子,禁止有特殊字符) 
		4.關於tips提示可以爲字符串和數據,(若是多個效驗條件,將按照一一對應的方式進行提示,若有多個效驗條件,而tips是字符串則只返回字符串)
		5.另外加上限制提示語 
		6.可自定義效驗方式:會將效驗的結果返回給 resulr 函數,參數(結果,當前正在效驗的值,當前的效驗條件)
*/

function verification (a, b) {
  const
    // 獲取數據類型的方法
    getType = (o, s = null) => {
      let t = Object.prototype.toString.call(o).split(' ')[1]
      t = t.substring(0, t.length - 1).trim().toLowerCase()
      if (t === 'object' && Object.prototype.toString.call(o).toLowerCase() === '[object object]' && !o.length) t = 'json'
      return s ? t === s : t
    }
  // 獲取包含指定k的對象
  const findData = (item, k) => {
    let arr = []
    for (let d in item) {
      if (d === k) {
        arr.push(item[d])
      } else if (getType(item[d], 'json') || getType(item[d], 'array')) {
        arr = arr.concat(findData(item[d], k))
      }
    }
    return arr
  }
	const rule = (it,k,v,r)=>{
		let bool = true;
		let isJson = getType(it[k], 'json')
		switch (k) {
            case 'tel':	// 手機號
              bool = /^((\+?86)|(\(\+86\)))?(13[012356789][0-9]{8}|15[012356789][0-9]{8}|18[02356789][0-9]{8}|147[0-9]{8}|1349[0-9]{7})$/.test(v) || (isJson ? it[k].tips : it.tips || false)
              break
            case 'zuoji':	// 座機
              bool = /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(v) || (isJson ? it[k].tips : it.tips || false)
              break
            case 'email':	// 郵箱
              bool = /^([a-zA-Z]|[0-9])(\w|\\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(v) || (isJson ? it[k].tips : (it.tips || false))
              break
            case 'date':	// 日期
              bool = (isNaN(v) && !isNaN(Date.parse(v))) || (isJson ? it[k].tips : it.tips || false)
              break
            case 'json':	// json
              bool = getType(v, 'json') || (isJson ? it[k].tips : it.tips || false)
              break
            case 'function':	// 函數
              bool = getType(v, 'function') || (isJson ? it[k].tips : it.tips || false)
              break
            case 'number':		// 純數字
              bool = getType(+v, 'number') || (isJson ? it[k].tips : it.tips || false)
              break
			 case 'hasNumber':		// 包含數字
              bool = /\d/.test(v) || (isJson ? it[k].tips : it.tips || false)
              break
			case 'word':	// 純漢字
				bool = /^[\u4e00-\u9fa5]+$/.test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
			case 'hasWord':	// 包含漢字
				bool = /[\u4E00-\u9FA5]/g.test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
			case 'letter':	// 純字母
				bool = /^[a-zA-Z]+$/.test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
			case 'hasLetter':	// 包含字母
				bool = /[a-zA-Z]/g.test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
			case 'hasSpecialCharacters':	// 包含特殊符號
				bool = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>《》/?~!@#¥……&*()——|{}【】‘;:”“'。,、? ]").test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
			case 'id':	// 身份證號碼
				bool = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(v) || (isJson ? it[k].tips : (it.tips || false))
			break;
            default:	// 普通判斷
              bool = getType(v, k) || (isJson ? it[k].tips : it.tips || false)
          }
		 return r?(getType(bool,'array') || getType(bool,'string') || bool === false):bool;
	}
  // 單獨的效驗判斷 (還未完善)
  const judge = (item, v) => {
    let bool = true
    let getJudgeResult = (it, k) => {
      if (bool === true) {
        let isJson = getType(it[k], 'json')
        let val = isJson ? it[k].value : it[k]
        if (k === 'type') {
			let isTypeArray = getType(val,'array');
			if(isTypeArray){
				for(let s = 0;s<val.length;s++){
					if(bool === true){
						bool = rule(it,val[s],v)
						if(getType(bool,'array')){
							if(bool[s]){
								bool  = bool[s]
							}else if(bool[0]){
								bool  = bool[0]
							}
						}
					}else{
						break;
					}
				}
			}else{
				bool = rule(it,val,v)
			}
		
        } else if (it[k] && (it[k] + '').toString()) {
			if(condition[k]){
				bool = condition[k](val) || (isJson ? it[k].tips : it.tips || false)
			}else if(k === 'limit'){
				if(getType(it[k],'array')){
					for(let s = 0;s<val.length;s++){
						if(bool === true){
							bool = rule(it,val[s],v,true)
							if(!bool && it.limitTips){
								if(getType(it.limitTips,'array')){
									bool  = it.limitTips[s] || it.limitTips[0] || false
								}else{
									bool  = it.limitTips || false
								}
							}
						}else{
							break;
						}
					}
				}else{
					bool = rule(it,val,v,true)
					if(!bool && it.limitTips){
						if(getType(it.limitTips,'array')){
							bool  = it.limitTips[0] || false
						}else{
							bool  = it.limitTips || false
						}
					}
				}
			}else if(['limitTips'].indexOf(k) < 0){
				console.warn(`Have not ${k} attribute at present. You can join QQ Group Provide advice. QQ Group: 602504799. Welcome you join.`)
			}
        
        } else {
          bool = isJson ? it[k].tips : it.tips || false
        }
      }
      return bool
    }
    const condition = {
      // 數字判斷
      min: (val) => v >= val,
      max: (val) => v <= val,
      value: (val) => v == val,
      // 字符串判斷
      minLength: (val) => v.toString().length >= val,
      maxLength: (val) => v.toString().length <= val,
      length: (val) => v.toString().length === val
    }
    if (getType(item, 'string')) {
      bool = !!item
    } else {
      for (let key in item) {
        if (key === 'tips' || key === 'key') {
          const arr = findData(data, item.key)
          if (arr.length) {
            for (let i = 0; i < arr.length; i++) {
              if (bool === true && !arr[i]) {
                bool = item.tips || false
              }
            }
          } else {
           console.warn(`Data have not field is '${getType(item, 'string') ? item : item.key}'`)
          }
        } else {
          getJudgeResult(item, key)
        }
      }
    }
    return bool
  }
  // 獲取結果值
  const getResult = () => {
    let bool = true
    for (let k in ver) {
      const item = ver[k]
      if (bool === true) {
        const arr = getType(item, 'string') ? findData(data, item) : findData(data, item.key)
        if (arr.length) {
          for (let i = 0; i < arr.length; i++) {
            const v = arr[i] || ''
            bool = judge(item, v)
		    if(item.result&&getType(item.result,'function')){
			  bool = item.result(bool,v,item)
		    }
          }
        } else {
          console.warn(`Data have not field is '${getType(item, 'string') ? item : item.key}'`)
        }
      } else {
        return bool
      }
    }
    return bool
  }
  // 效驗條件處理
  const verHandle = {
    string: () => data === ver,
    number: () => data === ver,
    json: () => getResult(),
    array: () => getResult()
  }
  // 獲取所有的參數
  const arg = arguments
  // 如果沒有參數就直接返回false
  if (!arg.length) return false
  // 獲取正確的data
  const data = arg.length > 1 ? arg[0] : arg[0].data
  const ver = arg.length > 1 ? arg[1] : arg[0].ver
  return data
    ? ver
      ? verHandle[getType(ver)]()
      : console.warn(`verification error: param ver is ${ver},can't verification`)
    : console.warn(`verification error: param data is ${data},can't verification`)
}
// demo 數據
const data = {
  note: '無',
  tips: {
    name: '戴向天',
	grilfriend:'clover'
  },
  user: {
    parents: {
      father: {
        children: {
          fristName: '向天',
          lastName: '戴',
          telPhone: '15072939115',
          homeTel: '020-12345678',
		  birthd:'2019-10-09',
		  email:'[email protected]'
        }
      }
    }
  },
  formData: [
    [{
      age: '25'
    }]
  ],
  other:function(){}
}

// demo 數據
const data = {
  note: '無',
  tips: {
    name: '戴向天aa',
	englishName: 'aaaa',
	grilfriend:'clover',
	special: 'aaa!',
	id: '4202221996xxxxxxxxx'
  },
  user: {
    parents: {
      father: {
        children: {
          fristName: '向天',
          lastName: '戴',
          telPhone: '15072939115',
          homeTel: '020-12345678',
		  birthd:'2019-10-09',
		  email:'[email protected]'
        }
      }
    }
  },
  formData: [
    [{
      age: 25
    }]
  ],
  other:function(){}
}

// demo 驗證測試
const result = verification({
  data,
  ver: [
	'grilfriend',
  {
	key: 'special',
	type: 'hasSpecialCharacters',
	tips: '必須含有特殊字符'
  },{
	key: 'id',
	type: 'id',
	tips: 'id必須是身份證號碼'
  },
  {
    key: 'note',
    tips: '請輸入備註',
	result:(res,value,item)=>{
		return res
	}
  }, {
    key: 'name',
    tips: ['請輸入名字,並且包含漢字','請輸入名字,並且包含字母'],
	type: ['hasWord','hasLetter'],
	limit: 'hasSpecialCharacters',
	limitTips: '名字不允許含有特殊字符',
  }, {
	key: 'englishName',
	type: 'letter',
	tips: '英文名詞必須是全字母'
  },{
    key: 'age',
    tips: '請輸入年齡',
    type: {
      value: 'number',
      tips: '年齡必須是數字類型'
    },
    min: {
      value: 20,
      tips: '年齡不能小於20歲'
    },
    max: {
      value: 30,
      tips: '年齡不能大於30歲'
    },
    value: {
      value: 25,
      tips: '年齡必須是25歲'
    }
  }, {
    key: 'fristName',
    tips: '請輸入名'
  }, {
    key: 'lastName',
    tips: '請輸入姓'
  }, {
    key: 'telPhone',
    tips: '請輸入正確的手機號',
    type: 'tel'
  }, {
    key: 'homeTel',
    tips: '請輸入正確的座機號碼',
    type: 'zuoji'
  },{
	key:'birthd',
	type:'date',
	tips:'請選擇生日'
  },{
	  key:'email',
	  type:'email',
	  tips:'請輸入郵箱'
  },{
	  key:'children',
	  type:'json',
	  tips:'children字段必須是json格式'
  },{
	  key:'other',
	  type:'function',
	  tips:'other字段必須是一個函數'
  }]
})

// demo 輸出驗證結果
console.log('result=>', result)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章