vue-真实配置2

256 阅读10分钟

公共方法 common

import Vue from 'vue'
import { getStore } from 'js/store'
import Map from '@/assets/js/data/map';
let vm = new Vue({});
const BIN = require('bankcardinfo');
const printJS = require('print-js');

export default {
	install(Vue) {
		// 确认框 函数
		Vue.prototype.$delBtn = (delAjax, text) => {
			const str = text || '此操作将删除该数据, 是否继续?';
			vm.$confirm(str, '提示', {
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				cancelButtonClass: 'btn-custom-cancel',
				type: 'warning'
			}).then(() => {
				delAjax(); // 调用删除接口
			})
		}
		/**
		 * @description:  对上面确认框 函数的深化,直接用于数据删除、审核、反审等需要确认后发送请求的场景
		 * @param {Array} data [表格勾选的数据数组]
		 * @param {String} axiosFn [axios自定义的几种方法名get、post、put、del等]
		 * @param {String} url [请求的路径,其中参数id占位符需要大括号包裹如{id}]
		 * @param {String} txt [提示的文字]
		 * @return:
		 */
		Vue.prototype.$confirmAxios = function (data, axiosFn, url, txt) {
			vm.$delBtn(() => {
				const ids = this.$array.returnArrayByKey(data, "id").join(",");
				url = url.replace("{id}", ids);
				vm.axios[axiosFn](url)
					.then((res) => {
						vm.$message.success(res.message);
						this.getList();
					})
			}, txt)
		}
		/**
		 * @description: 根据选择数据验证btn是否可以使用
		 * @param {Array/ Object} data [用于验证按钮可用与否的数据]
		 * @param {String} text [不通过验证的提示文字]
		 * @param {Function} fn [验证函数,返回true、false]
		 * @return: true 满足条件  false 不满足条件
		 */
		Vue.prototype.$btnValidator = (data, text, fn) => {
			let warnObj = { text: text };
			let res = false;
			if (Array.isArray(data)) {
				res = data.some((item) => {
					if (fn(item, warnObj)) return true
				})
			} else if (typeof data === "object") {
				res = fn(data, warnObj)
			}
			if (res) {
				vm.$message({
					type: 'warning',
					message: warnObj.text
				});
			}
			return res;
		}

		// 解决传参 [key][0][val]  =>  key[0].val
		// 调用示例: $dataTransform(this.addOrEditData, 'buttons');
		Vue.prototype.$dataTransform = (object, property) => {
			if (Array.isArray(object[property])) {
				object[property].forEach((val, i) => {
					for (var j in val) {
						object[property + "[" + i + "]." + j] = val[j];
					}
				});
				delete object[property];
			}
			if (object[property] instanceof Object) {
				for (const key in object[property]) {
					if (object[property].hasOwnProperty(key)) {
						const element = object[property][key];
						object[property + "." + key] = element;
					}
				}
				delete object[property];
			}
		}
		/**
  		* @description: 判断数据不存在 或 为空值
  		* @param {所有数据类型} data [需要验证的数据]
  		* @return: [存在非空false,不存在或是空值true]
  		*/
		Vue.prototype.$dataIsNull = (data) => {
			if (typeof data === "undefined") {
				return true;
			} else if (data instanceof Array) {
				if (data.length === 0) return true;
			} else if (data instanceof Object) {
				if (JSON.stringify(data) === '{}') return true;
			} else if (data === 'null' || data === null || data === 'undefined' || data === '') {
				return true;
			} else {
				return false;
			}
		}
		/**
  		* @description: 用于后台获取的数据应用于页面数据,避免直接赋值带来的属性缺失
  		* @param {Object} pageData [页面初始化的数据,与接口相匹配]
  		* @param {Object} getData [后台获取的数据,由于未初始化的数据后台不做返回,可能缺失重要属性]
  		* @return: [补全必要字段的后台数据]
  		*/
		Vue.prototype.$mergeObject = (pageData, getData) => {
			for (const item in pageData) {
				if (!getData.hasOwnProperty(item)) {
					getData[item] = pageData[item];
				}
			}
			return getData
		}
		// 日期时间相关方法
		Vue.prototype.$date = {
			// 时间格式化
			format: (date, fmt = "yyyy-MM-dd hh:mm:ss") => {
				if (!date || date == null) {
					return date;
				}
				date = new Date(date)
				if (/(y+)/.test(fmt)) {
					fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
				}
				let o = {
					'M+': date.getMonth() + 1,
					'd+': date.getDate(),
					'h+': date.getHours(),
					'm+': date.getMinutes(),
					's+': date.getSeconds()
				};
				let padLeftZero = (str) => {
					return ('00' + str).substr(str.length);
				};
				for (let k in o) {
					if (new RegExp(`(${k})`).test(fmt)) {
						let str = o[k] + '';
						fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
					}
				}
				return fmt;
			},
			// 验证开始时间 结束时间 的关系
			validator: (start, end, symbol = ">=") => {
				if (start && end) {
					// eslint-disable-next-line no-eval
					if (eval(`${new Date(start).getTime()}${symbol}${new Date(end).getTime()}`)) {
						return false;
					} else {
						return true;
					}
				} else {
					return false;
				}
			},
			/**
    		* @description: 计算两天之间相差多少年月日
    		* @param {String}  sDate1 [开始日期yyyy-MM-dd]
    		* @param {String}  sDate2 [结束日期yyyy-MM-dd]
    		* @return: { y: y, m: m, d: d }
    		*/
			dateDiff: (sDate1, sDate2) => {
				var fixDate = function (sDate) {
					var aD = sDate.split('-');
					for (var i = 0; i < aD.length; i++) {
						aD[i] = fixZero(parseInt(aD[i]));
					}
					return aD.join('-');
				};
				var fixZero = function (n) {
					return n < 10 ? '0' + n : n;
				};
				var fixInt = function (a) {
					for (var i = 0; i < a.length; i++) {
						a[i] = parseInt(a[i]);
					}
					return a;
				};
				var getMonthDays = function (y, m) {
					var aMonthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
					// eslint-disable-next-line eqeqeq
					if ((y % 400 == 0) || (y % 4 == 0 && y % 100 != 0)) {
						aMonthDays[2] = 29;
					}
					return aMonthDays[m];
				};
				var y = 0;
				var m = 0;
				var d = 0;
				var sTmp;
				var aTmp;
				sDate1 = fixDate(sDate1);
				sDate2 = fixDate(sDate2);
				if (sDate1 > sDate2) {
					sTmp = sDate2;
					sDate2 = sDate1;
					sDate1 = sTmp;
				}
				var aDate1 = sDate1.split('-');
				aDate1 = fixInt(aDate1);
				var aDate2 = sDate2.split('-');
				aDate2 = fixInt(aDate2);
				//计算相差的年份
				/*aTmp = [aDate1[0]+1,fixZero(aDate1[1]),fixZero(aDate1[2])];
				while(aTmp.join('-') <= sDate2){
					y++;
					aTmp[0]++;
				}*/
				y = aDate2[0] - aDate1[0];
				if (sDate2.replace(aDate2[0], '') < sDate1.replace(aDate1[0], '')) {
					y = y - 1;
				}
				//计算月份
				aTmp = [aDate1[0] + y, aDate1[1], fixZero(aDate1[2])];
				while (true) {
					// eslint-disable-next-line eqeqeq
					if (aTmp[1] == 12) {
						aTmp[0]++;
						aTmp[1] = 1;
					} else {
						aTmp[1]++;
					}
					if (([aTmp[0], fixZero(aTmp[1]), aTmp[2]]).join('-') <= sDate2) {
						m++;
					} else {
						break;
					}
				}
				//计算天数
				aTmp = [aDate1[0] + y, aDate1[1] + m, aDate1[2]];
				if (aTmp[1] > 12) {
					aTmp[0]++;
					aTmp[1] -= 12;
				}
				while (true) {
					// eslint-disable-next-line eqeqeq
					if (aTmp[2] == getMonthDays(aTmp[0], aTmp[1])) {
						aTmp[1]++;
						aTmp[2] = 1;
					} else {
						aTmp[2]++;
					}
					sTmp = ([aTmp[0], fixZero(aTmp[1]), fixZero(aTmp[2])]).join('-');
					if (sTmp <= sDate2) {
						d++;
					} else {
						break;
					}
				}
				return { y: y, m: m, d: d };
			}
		}
		// 数字相关方法
		Vue.prototype.$number = {
			// 时间格式化
			format: (number, decimals, isThousandsSep) => {
				/*
				 * 参数说明:
				 * number:要格式化的数字
				 * decimals:保留几位小数
				 * isThousandsSep:是否加入千分位符号
				 * */
				number = (number + '').replace(/[^0-9+-Ee.]/g, '');
				// eslint-disable-next-line one-var
				let n = !isFinite(+number) ? 0 : +number,
					prec = !isFinite(+decimals) ? 2 : Math.abs(decimals),
					sep = ',',
					dec = '.',
					s = '',
					toFixedFix = function (n, prec) {
						var k = Math.pow(10, prec);
						return '' + Math.round(n * k) / k;
					};
				// console.log(toFixedFix(n, prec),Math.round(n));
				s = toFixedFix(n, prec).split('.');
				var re = /(-?\d+)(\d{3})/;
				// 判断是否加千位分隔符
				if (isThousandsSep) {
					while (re.test(s[0])) {
						s[0] = s[0].replace(re, "$1" + sep + "$2");
					}
				}
				if ((s[1] || '').length < prec) {
					s[1] = s[1] || '';
					s[1] += new Array(prec - s[1].length + 1).join('0');
				}
				return s.join(dec);
			},
			// 纯数字字符串转为数字 反之 不处理
			parseNumber: (val) => {
				return isNaN(Number(val)) ? val : Number(val)
			}
		}
		// 文本方法操作
		Vue.prototype.$text = {
			// 防止脚本注入 替换script标签
			stripScript: (str) => {
				return str.replace(/<script.*?>.*?<\/script>/ig, '');
			},
			// 取消文本两端的空格
			trim: (str) => {
				return str.replace(/(^\s*)|(\s*$)/g, "");
			}
		}
		// 数组方法
		Vue.prototype.$array = {
			/**
			 * @description: 获取数组中每个对象某个key的新集合
			 * @param {type}
			 * @return:
			 */
			returnArrayByKey: (originArr, key) => {
				let arr = [];
				if (Array.isArray(originArr)) {
					originArr.forEach((item) => {
						if (item[key]) arr.push(item[key]);
					});
				}
				return arr;
			}
		}
		// 对象数组深拷贝
		Vue.prototype.$clone = (obj) => {
			let clone = (obj) => {
				if (obj === null) return obj;
				if (typeof obj !== 'object') { return obj; }
				let cloneObj = {};
				switch (obj.constructor) {
					case Array:
						cloneObj = [];
						if (obj.length !== 0) {
							for (let i = 0, len = obj.length; i < len; i++) {
								cloneObj.push(clone(obj[i]));
							}
						}
						break;
					case Object:
						for (var property in obj) {
							cloneObj[property] = typeof obj[property] === 'object' ? clone(obj[property]) : obj[property];
						}
						break;
					case Map:
						cloneObj = new Map();
						obj.forEach((value, key) => {
							cloneObj.set(key, typeof value === 'object' ? clone(value) : value);
						});
						break;
					case Set:
						cloneObj = new Set();
						obj.forEach(value => {
							cloneObj.add(typeof value === 'object' ? clone(value) : value);
						});
						break;
				}
				return cloneObj;
			}
			return clone(obj)
		}
		// 获得树形数据ID数组
		Vue.prototype.$treeFn = {
			/**
			* @description:  线性数据转化为树
			* @param {Array} originArr [原始数组]
			* @param {Number} originId [初始化的顶级节点id]
			* @param {Object} config [数据配置项]
			* @return:
			*/
			toTree: (originArr, originId, config) => {
				const configName = config.name || "name";
				const configPId = config.pId || "pId";
				const configPName = config.pName || "pName";
				const configChildren = config.children || "children";
				const configOriginNode = config.originNode || "根节点";
				let obj = {};
				originArr.forEach((item, index) => {
					obj[item.id] = item
				})
				// let newObj = JSON.parse(JSON.stringify(obj));
				const toTreeFn = (arr, id) => {
					let tree = [];
					let temp = null;
					originArr.forEach((item, index) => {
						item[configPName] = obj[item[configPId]] ? obj[item[configPId]][configName] : configOriginNode;
						if (item[configPId] === id) {
							temp = toTreeFn(arr, item.id);
							if (temp.length > 0) {
								item[configChildren] = temp;
							}
							tree.push(item);
							delete originArr[index];
						}
					})
					return tree;
				}
				return toTreeFn(originArr, originId)
			},
			/**
			* @description:  获取树中  所有节点id
			* @param {Array} originArr [原始数组]
			* @param {Object} config [数据配置项]
			* @return:
			*/
			findAllId: (originArr, config) => {
				config = config || "children";
				let arr = [];
				const getId = (data1, arr1) => {
					data1.map((item) => {
						arr1.push(item.id);
						if (item[config]) {
							getId(item[config], arr1)
						}
					})
				}
				getId(originArr, arr);
				return arr
			},
			/**
			* @description:  获取当前节点及其所有父节点 id
			* @param {Array} originArr [原始数组]
			* @param {Number,String} findId [初始化的顶级节点id]
			* @param {Object} config [数据配置项]
			* @return:
			*/
			findAllPId: (originArr, findId, config) => {
				if (!findId) return [];
				if (!config) {
					config = {
						children: "children",
						pId: "pId"
					}
				}
				let { children, pId } = config;
				let result = [];
				const findNode = (arr, id) => {
					if (!Array.isArray(arr)) return;
					arr.some((item) => {
						if (item.id === id) {
							result.unshift(item.id);
							if (item[pId] !== 0) {
								findNode(originArr, item[pId]);
							};
						}
						if (item[children] && item[children].length !== 0) {
							findNode(item[children], id);
						}
					})
				}
				findNode(originArr, findId);
				// console.log("查找多叉树某节点所有父级id", result);
				return result;
			},
			/**
			* @description:  通过节点id找到节点数据
			* @param {Array} originArr [原始数组]
			* @param {Number,String} findId [初始化的顶级节点id]
			* @param {Object} config [数据配置项]
			* @return:
			*/
			findNodeById: (originArr, findId, config) => {
				if (!findId) return [];
				if (!config) {
					config = {
						children: "children"
					}
				}
				let { children } = config;
				let result = {};
				const findNode = (arr, id) => {
					if (!Array.isArray(arr)) return;
					arr.find((item) => {
						if (item.id === id) {
							result = item;
							return true;
						}
						if (item[children] && item[children].length !== 0) {
							findNode(item[children], id);
						}
					})
				}
				findNode(originArr, findId);
				// console.log("查找多叉树某节点所有父级id", result);
				return result;
			}
		}

		// 阿拉伯数字转中文大写
		Vue.prototype.$capital = (n) => {
			if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(n)) { return "数据非法"; }
			// eslint-disable-next-line one-var
			var unit = "千百拾亿千百拾万千百拾元角分",
				str = "";
			n += "00";
			var p = n.indexOf('.');
			// eslint-disable-next-line curly
			if (p >= 0)
				n = n.substring(0, p) + n.substr(p + 1, 2);
			unit = unit.substr(unit.length - n.length);
			// eslint-disable-next-line curly
			for (var i = 0; i < n.length; i++)
				str += '零壹贰叁肆伍陆柒捌玖'.charAt(n.charAt(i)) + unit.charAt(i);
			return str.replace(/零(千|百|拾|角)/g, "零").replace(/(零)+/g, "零").replace(/零(万|亿|元)/g, "$1").replace(/(亿)万|壹(拾)/g, "$1$2").replace(/^元零?|零分/g, "").replace(/元$/g, "元整");
		}

		// 下拉框相关
		Vue.prototype.$select = {
			/**
			 * @description: 根据codes获取相关数据
			 * @param arr {array} code组成的数组
			 * @return: option  {object} 数据结构如下
			 * {
			 * 		code:[
			 * 			{value: "0", text: "银行列表", isDefault: true, orderNo: 1}
			 *			{value: "1", text: "工商银行", isDefault: true, orderNo: 2}
			 *		]
			 * }
			 */
			getByCodes: (arr) => {
				if (!Array.isArray(arr)) return;
				const codes = arr.join(",");
				let option = {};
				return new Promise((resolve, reject) => {
					Vue.prototype.axios.get(`/api/common-service/select/${codes}/options`).then((res) => {
						// eslint-disable-next-line eqeqeq
						if (res.statusCode == 200) {
							// 组合option数据
							res.data.map((item) => {
								option[item.code] = item.options.map((item) => {
									// 判断是否为纯数字类型的字符串 是 将id转化为number
									// 保留value为初始值 类型string
									// 使用时根据具体情况选择 id或者 value
									if (/^[0-9]+$/.test(item.value)) {
										item.id = Number(item.value);
									} else {
										item.id = item.value;
									}
									item.label = item.text;
									return item;
								})
							})
							resolve(option);
						}
					});
				})
			}
		}

		// 银行相关
		Vue.prototype.$bank = {
			/**
			 * @description: 根据codes获取相关数据
			 * @param arr {array} code组成的数组
			 * @return: option  {object} 数据结构如下
			 * {
			 * 		code:[
			 * 			{value: "0", text: "银行列表", isDefault: true, orderNo: 1}
			 *			{value: "1", text: "工商银行", isDefault: true, orderNo: 2}
			 *		]
			 * }
			 */
			getInfo: (bankNo) => {
				return new Promise((resolve, reject) => {
					BIN.getBankBin(bankNo)
						.then(function (data) {
							resolve(data)
						})
						.catch(function (err) {
							reject(err)
						})
				})
			}
		}

		// 过滤函数
		Vue.prototype.$filters = {
			/**
			 * @description: 过滤字符串
			 * @param val {string}  value
			 * @param formatArr {Array} 格式化数组   [{value:1 , label: "A"}]
			 * @return: 过滤后的值
			 */
			string: function (val, formatArr) {
				if (vm.$dataIsNull(val)) return val;
				if (Array.isArray(formatArr)) {
					let obj = formatArr.find((item) => {
						// eslint-disable-next-line eqeqeq
						if (item.id == val || item.value == val) {
							obj = item;
							return true
						}
					})
					if (!obj) return val;
					if (obj.label) {
						return obj.label
					} else if (obj.name) {
						return obj.name
					} else if (obj.title) {
						return obj.title
					} else if (obj.text) {
						return obj.text
					} else {
						return val
					}
				}
				return val
			},
			/**
			 * @description: 过滤时间
			 * @param val {string}  value
			 * @param formatTxt {string} 格式化类型
			 * @return: 过滤后的值
			 */
			date: function (val, formatTxt) {
				if (val === undefined || val === null || val === "") return val;
				if (typeof formatTxt !== "string" || formatTxt === "") {
					formatTxt = "yyyy-MM-dd hh:mm:ss"
				}
				return Vue.prototype.$date.format(val, formatTxt)
			},
			/**
			 * @description: 过滤数字
			 * @param val {string}  value
			 * @param formatTxt {string} 格式化类型 number,Boolean  number表示保留几位小数 Boolean表示是否显示千分位分隔符
			 * @return: 过滤后的值
			 */
			number: function (val, formatTxt) {
				if (val === undefined || val === null || val === "") return val;
				if (typeof formatTxt === "string" && formatTxt !== "") {
					let [n, isTS] = formatTxt.split(",");
					if (isTS === "true") {
						isTS = true;
					} else {
						isTS = false;
					}
					return Vue.prototype.$number.format(val, n, isTS)
				}
				return val;
			},
			/**
			 * @description: 过滤地址
			 * @param val {string}  value
			 * @return: 过滤后的值
			 */
			area: function (val) {
				const thisId = Number(val);
				let result = null;
				const parseId = (arr, id) => {
					arr.map((item) => {
						if (item.value === id) {
							result = item.label;
							return item.label;
						}
						if (item.children && item.children.length !== 0) {
							parseId(item.children, id)
						}
					})
				}
				if (isNaN(thisId)) {
					return val
				} else {
					parseId(Map, thisId);
					return result === null ? val : result;
				}
			}
		}

		// 打印
		Vue.prototype.$print = {
			/**
			 * @description: 打印html
			 * @param ElementId {string} 元素Id
			 * @param header {string}  打印文件标题名称
			 * @return: 无
			 */
			html: (ElementId, header) => {
				printJS({
					printable: ElementId,
					type: 'html',
					header: header,
					headerStyle: 'font-weight:400; text-align:center',
					maxWidth: 1920,
					css: '/static/css/print.css',
					scanStyles: false
				})
			},
			/**
			 * @description: 打印table
			 * @param printData {Array}   打印的数据
			 * @param theaderData {Array}  表格thead数据
			 * @param header {string}  打印文件标题名称
			 * @return: 无
			 */
			table: (printData, theaderData, header) => {
				let data = Vue.prototype.$print.parseData(printData, theaderData);
				printJS({
					printable: data.body,
					properties: data.header,
					type: 'json',
					header: header,
					headerStyle: 'font-weight:400; text-align:center',
					maxWidth: 1920,
					css: '/static/css/print.css',
					scanStyles: false
				})
			},
			/**
			 * @description: 解析表格数据
			 * @param tbodyData {Array}   表格tbody数据
			 * @param theaderData {Array}  表格thead数据
			 * @return: result
			 */
			parseData: (tbodyData, theaderData) => {
				let result = {
					header: [],
					body: []
				};
				result.body = Vue.prototype.$clone(tbodyData);
				const parseData = (key, type, format) => {
					result.body.map((item) => {
						if (typeof item[key] === "undefined") item[key] = "";
						if (item[key] === true) item[key] = "√";
						if (item[key] === false) item[key] = "";
						if (type) item[key] = Vue.prototype.$filters[type](item[key], format);
						return item;
					})
				}
				theaderData.forEach(item => {
					result.header.push({
						field: item.prop,
						displayName: item.label
					})
					switch (item.type) {
						case 0: //文字
						case 12: //文字
							parseData(item.prop, "string", item.format);
							break;
						case 8: //日期
							parseData(item.prop, "date", item.format);
							break;
						case 9: //数字
							parseData(item.prop, "number", item.format);
							break;
						case 11: //地区
							parseData(item.prop, "area", item.format);
							break;
						default:
							parseData(item.prop);
							break;
					}
				})
				return result
			},
			/**
			 * @description: 打印pdf base64格式
			 * @param tbodyData {Array}   表格tbody数据
			 * @param theaderData {Array}  表格thead数据
			 * @return: result
			 */
			pdf: (base64string) => {
				printJS({ printable: base64string, type: 'pdf', base64: true })
			}
		}

		// 文件服务相关操作
		Vue.prototype.$file = {
			/**
			 * @description: 文件验证器
			 * @param file {string} 文件对象(element ui上传工具验证方法传入对象)
			 * @param typeArr {array} 文件类型组成的数组 ["jpg", "png"], 不传参表示任意类型文件
			 * @param size {number} 单位Mb , 不传参表示任意大小文件
			 * @return: 无
			 */
			validator: (file, typeArr, size) => {
				const testmsg = file.name.substring(file.name.lastIndexOf('.') + 1);
				let [extension, isLt] = [true, true];
				if (typeArr) {
					extension = typeArr.join(",").indexOf(testmsg) !== -1;
					if (!extension) {
						Vue.prototype.$message({
							message: `上传文件只能是 ${typeArr.join("/")} 格式!`,
							type: 'warning'
						});
					}
				}
				if (size) {
					isLt = file.size / 1024 / 1024 < size;
					if (!isLt) {
						Vue.prototype.$message({
							message: `上传文件大小不能超过 ${size} Mb!`,
							type: 'warning'
						});
					}
				}
				return extension && isLt
			},
			/**
			 * @description: 删除
			 * @param {Array} codesArr [code组成的数组]
			 * @param {String} encrypt [文件密文]
			 * @return: 无
			 */
			delete: (codesArr, encrypt) => {
				if (!Array.isArray(codesArr)) return;
				return new Promise((resolve, reject) => {
					Vue.prototype.axios.del(`/api/file-service/file/code`, {
						code: codesArr.join(","),
						encrypt: encrypt
					}).then((res) => {
						// eslint-disable-next-line eqeqeq
						if (res.statusCode == 200) {
							Vue.prototype.$message({
								message: '删除成功',
								type: 'success'
							});
							resolve(res);
						}
					});
				})
			},
			/**
			 * @description: 将code转化为url
			 * @param code {string} 文件存储的code
			 * @return: 无
			 */
			toUrl: (code) => {
				const fileIpService = getStore({
					name: "fileIpService"
				});
				const token = getStore({
					name: 'access_token'
				});
				return fileIpService.ip + fileIpService.file + code + "?access_token=" + token
			},
			/**
			 * @description: 将获取的fileList转化为表格可用的list数据
			 * @param  {Array} arr [后台获取的fileList数据]
			 * @return: 表格可用的list数据
			 */
			parseFileList: (arr) => {
				if (!(Array.isArray(arr) && arr.length !== 0)) return [];
				return arr.map((item) => {
					item.fileUrl = {
						label: item.fileName,
						url: Vue.prototype.$file.toUrl(item.code)
					}
					return item
				})
			},
			/**
			 * @description: 直接请求文件服务器 获取文件表格数据
			 * @param {String} encrypt [文件密文]
			 * @return: 表格可用的list数据
			 */
			getList: (encrypt) => {
				return new Promise((resolve, reject) => {
					vm.axios.post('/api/file-service/file/owner', {
						encrypt: encrypt
          }, "json"
          ).then((res) => {
						resolve(Vue.prototype.$file.parseFileList(res.data))
					})
				})
			}
		}

		// 常用ajax封装
		Vue.prototype.$ajax = {
			/**
    		* @description: 提交工作流
			* @param {String} workflowType [工作流类型,接口formKey]
		    * @param {Object} data [工作流类型,接口formKey]
    		* @param {String} workflowType [工作流类型,接口formKey]
    		* @return:
    		*/
			toWorkflow: (workflowType, data, title) => {
				return new Promise((resolve, reject) => {
					vm.axios.get(`/api/activiti-service/actdemodelmappings/${workflowType}`)
						.then((res) => {
							const userInfo = getStore({ name: "userInfo" });
							vm.axios.post(`/api/activiti-service/activiti/start`, {
								businessEntityId: data.id,
								callbaceURL: null,
								formData: {
									id: data.id,
									name: userInfo.name,
									orgName: userInfo.org_name,
									content: data
								},
								processDefinitionKey: res.data.processId,
								sheetName: title,
								sheetType: workflowType
							}, "json")
								.then((subres) => {
									vm.$message.success(subres.message);
									resolve()
								})
						});
				})
			}

		}

		/**
		 * @description: 处理分页获取数据 时间 总数 页面的方法
		 * @param {Object} res [请求列表数据返回的数据对象]
		 * @return:
		 */
		Vue.prototype.$handlerList = function (res) {
			this.time = res.resTime;
			this.total = res.data.total;
			this.currentPage = res.data.current;
		}
		/**
		 * @description: 搜索列表的统一处理方式
		 * @return:
		 */
		Vue.prototype.$search = function () {
			this.currentPage = 1;
			this.searchParam = this.$clone(this.searchData);
			this.getList();
		}
		/**
		 * @description: 重置搜索列表的统一处理方式
		 * @return:
		 */
		Vue.prototype.$resetSearch = function () {
			this.currentPage = 1;
			this.searchData = this.$options.data.call(this).searchData;
			this.searchParam = {};
			this.getList();
		}
		/**
		 * @description: 生成凭证
		 * @param {Number} id [数据id]
		 * @param {Number} type [0-预付款,1-采购,2-入库单,3-进项,4-付款,5-预收款,6-出库单,7-收款单,8-销项票,9-结转成本]
		 * @return:
		 */
		Vue.prototype.$genVoucher = function (id, type) {
			return new Promise((resolve, reject) => {
				Vue.prototype.axios.post(`/api/fin-service/voucher/generateData`, {
					id: id,
					type: type
				}).then((res) => {
					vm.$message.success(res.message);
					resolve(res);
				});
			})
		}
		/**
		 * @description: 是否有权限权限
		 * @param {String} code [权限码]
		 * @return:
		 */
		Vue.prototype.$isPermission = function (code) {
			const permissions = getStore({ name: "userInfo" }).permissions;
			return permissions.indexOf(code) !== -1
		}
		/**
		 * @description:  通过 prop 在 MainForm 组件配置数据中 找到相应的对象
		 * @param {String} prop [属性]
		 * @param {Array} configArr [mainform配置数组]
		 * @return:
		 */
		Vue.prototype.$findConfigByProp = function (prop, configArr) {
			let res = null;
			configArr.find((item1) => {
				item1.find((item2) => {
					res = item2.list.find((item3) => {
						if (item3.prop === prop) return true
					})
					if (res instanceof Object) return true
				})
				if (res instanceof Object) return true
			})
			return res
		}
	}
}

表单验证规则 rule

/*
 * @Description: 表单验证规则 rule
 */

export default {
	install(Vue) {
		Vue.prototype.$rules = { //常量
			/**
			* @description: 设置必选内容
			* @param text {string}  验证提示内容
			* @param trigger {string}  触发类型 默认 blur
			* @return: 无
			*/
			setRequired: (text, trigger) => {
				trigger = trigger || 'blur';
				return {
					required: true,
					message: text,
					trigger: trigger
				}
			},
			// 设置文本长度
			setLength: (min, max) => {
				min = Number(min);
				max = Number(max);
				return {
					min: min,
					max: max,
					message: `长度在 ${min}${max} 个字符`,
					trigger: 'blur'
				}
			},
			// 设置账号 编码
			setCode: (min, max) => {
				let text = `以字母开头,长度在 ${min} - ${max} 之间, 只能包含字母、数字和下划线`;
				min = Number(min) - 1;
				max = Number(max) - 1;
				let reg = new RegExp(`^[a-zA-Z][0-9a-zA-Z_]{${min},${max}}$`);
				return {
					pattern: reg,
					message: text,
					trigger: 'blur'
				}
			},
			// 设置普通密码
			setPassword: (min, max) => {
				let text = `只能输入 ${min} - ${max} 个字母、数字、下划线!`;
				min = Number(min);
				max = Number(max);
				let reg = new RegExp(`^[0-9a-zA-Z_]{${min},${max}}$`);
				return {
					pattern: reg,
					message: text,
					trigger: 'blur'
				}
			},
			/**
    		* @description: 设置新密码  与下面的确认密码一起使用
    		* @param {Object} vm [当前组件的实例指针this]
    		* @param {String} formRef [from的ref属性名称]
    		* @param {String} dataName [confirmPassword属性所在对象的名称]
    		* @param {String} confirmPassword [confirmPassword属性的名称]
    		* @return:
    		*/
			setNewPassword: (vm, formRef, dataName, confirmPassword, isRequired = true, min = 6, max = 16) => {
				let text = `只能输入 ${min} - ${max} 个字母、数字、下划线!`;
				min = Number(min);
				max = Number(max);
				let reg = new RegExp(`^[0-9a-zA-Z_]{${min},${max}}$`);
				const rule = (rule, value, callback) => {
					if (vm.$dataIsNull(value)) {
						if (isRequired) {
							callback(new Error('请输入密码'));
						} else {
							callback();
						}
					} else if (!reg.test(value)) {
						callback(new Error(text));
					} else {
						if (!vm.$dataIsNull(vm[dataName][confirmPassword])) {
							vm.$refs[formRef].validateField(confirmPassword);
						}
						callback();
					}
				}
				return {
					required: isRequired,
					validator: rule,
					trigger: 'blur'
				}
			},
			// 设置确认密码
			/**
    		* @description: 设置确认密码  与上面设置新密码一起使用
    		* @param {Object} vm [当前组件的实例指针this]
    		* @param {String} dataName [newPassword属性所在对象的名称]
    		* @param {String} newPassword [newPassword属性的名称]
    		* @return:
    		*/
			setConfirmPassword: (vm, dataName, newPassword, isRequired = true) => {
				const rule = (rule, value, callback) => {
					if (vm.$dataIsNull(value)) {
						if (isRequired) {
							callback(new Error('请再次输入密码'));
						} else {
							callback();
						}
					} else if (value !== vm[dataName][newPassword]) {
						callback(new Error('两次输入密码不一致!'));
					} else {
						callback();
					}
				}
				return {
					required: isRequired,
					validator: rule,
					trigger: 'blur'
				}
			},
			/**
			* @description: 设置数字验证(用于数字密码或者数字编号,可以0开头)
			* @param {Number} min [最小位数]
			* @param {Number} max [最大位数] 不填时限制为满足最小位数的
			* @return:
			*/
			setNumber: (min, max) => {
				let [text, reg] = [null, null];
				min = Number(min);
				if (max) {
					text = `由 ${min} - ${max} 位数字组成`;
					max = Number(max);
					reg = new RegExp(`^[0-9]{${min},${max}}$`);
				} else {
					text = `由 ${min} 位数字组成`;
					reg = new RegExp(`^[0-9]{${min}}$`);
				}
				return {
					pattern: reg,
					message: text,
					trigger: 'blur'
				}
			},
			// 设置以数字开头数字结尾,逗号链接的字符串
			setNumberList: () => {
				return {
					pattern: /^[1-9]([0-9]*,)([0-9]+,)*[0-9]+$/,
					message: "非0数字开头,数字结尾,必须逗号连接",
					trigger: 'blur'
				}
			},
			// 设置不能包含特殊符号和空格的字符串
			setNoSpaceOrSpecial: () => {
				return {
					pattern: /^[\u4e00-\u9fa5_a-zA-Z0-9]+$/,
					message: "不能由特殊符号和空格组成",
					trigger: 'blur'
				}
			},
			// 设置不能包含空格的字符串
			setNoSpace: () => {
				return {
					pattern: /^[^\s]*$/,
					message: "不能由空格组成",
					trigger: 'blur'
				}
			},

			// 设置以数字开头+,+ture/false
			setNumberFormat: () => {
				return {
					pattern: /^([0-9]*,)(true|false){1}$/,
					message: "保留小数点个数,true/fasle(是否千位分隔)",
					trigger: 'blur'
				}
			},
			//统一社会信用代码
			checkUnCreditCode: (rule, value, callback) => {
				const firstarray = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
				const firstkeys = [3, 7, 9, 10, 5, 8, 4, 2];
				// 验证码计算后获得结果 转化的映射关系
				const secondarray = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'T', 'U', 'W', 'X', 'Y'];
				// 加权因子
				const secondkeys = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28];
				const calc = function (code, array1, array2, b) {
					var count = 0;
					for (var i = 0; i < array2.length; i++) {
						var a = code[i];
						count += array2[i] * array1.indexOf(a);
					}
					return b - count % b;
				}
				const verify = function (str) {
					var code = str.toUpperCase();

					// 统一代码由十八位的阿拉伯数字或大写英文字母( 不使用I、 O、 Z、 S、 V) 组成。
					// 第1位: 登记管理部门代码( 共一位字符)
					// 第2位: 机构类别代码( 共一位字符)
					// 第3位~第8位: 登记管理机关行政区划码( 共六位阿拉伯数字)
					// 第9位~第17位: 主体标识码( 组织机构代码)( 共九位字符)
					// 第18位: 验证码共一位字符
					// eslint-disable-next-line eqeqeq
					if (code.length != 18) {
						return false;
					}
					var reg = /^\w\w\d{6}\w{9}\w$/;
					if (!reg.test(code)) {
						return false;
					}
					// 登记管理部门代码:使用阿拉伯数字或大写英文字母表示。
					// 机构编制:1
					// 民政: 2
					// 工商:9
					// 其他: Y
					reg = /^[1,5,9,Y]\w\d{6}\w{9}\w$/;
					if (!reg.test(code)) {
						return false;
					}

					// 机构类别代码: 使用阿拉伯数字或大写英文字母表示。
					// 机构编制机关: 11 打头
					// 机构编制事业单位: 12打头
					// 机构编制中央编办直接管理机构编制的群众团体: 13打头
					// 机构编制其他: 19打头
					// 民政社会团体: 51 打头
					// 民政民办非企业单位: 52 打头
					// 民政基金会: 53 打头
					// 民政其他: 59 打头
					// 工商企业: 91 打头
					// 工商个体工商户: 92 打头
					// 工商农民专业合作社: 93 打头
					// 其他: Y1打头

					reg = /^(11|12|13|19|51|52|53|59|91|92|93|Y1)\d{6}\w{9}\w$/;
					if (!reg.test(code)) {
						return false;
					}

					// 登记管理机关行政区划码: 只能使用阿拉伯数字表示。 按照GB / T 2260 编码
					// 例如: 四川省成都市本级就是510100; 四川省自贡市自流井区就是510302

					reg = /^(11|12|13|19|51|52|53|59|91|92|93|Y1)\d{6}\w{9}\w$/;
					if (!reg.test(code)) {
						return false;
					}

					// 主体标识码( 组织机构代码): 使用阿拉伯数字或英文大写字母表示。 按照GB 11714 编码。

					// 在实行统一社会信用代码之前, 以前的组织机构代码证上的组织机构代码由九位字符组成。 格式为XXXXXXXX - Y。 前面八位被称为“ 本体代码”; 最后一位被称为“ 校验码”。 校验码和本体代码由一个连字号( - )连接起来。 以便让人很容易的看出校验码。 但是三证合一后, 组织机构的九位字符全部被纳入统一社会信用代码的第9位至第17位, 其原有组织机构代码上的连字号不带入统一社会信用代码。

					// 原有组织机构代码上的“ 校验码” 的计算规则是:

					// 例如: 某公司的组织机构代码是: 59467239 - 9。 那其最后一位的组织机构代码校验码9是如何计算出来的呢?

					// 第一步: 取组织机构代码的前八位本体代码为基数。 5 9 4 6 7 2 3 9
					// 提示: 如果本体代码中含有英文大写字母。 则A的基数是10, B的基数是11, C的基数是12, 依此类推, 直到Z的基数是35。
					// 第二步: 取加权因子数值,因为组织机构代码的本体代码一共是八位字符。 则这八位的加权因子数值从左到右分别是: 3、 7、 9、 10、 5、 8、 4、 2。
					// 第三步: 本体代码基数与对应位数的因子数值相乘
					// 5× 3= 15, 9× 7= 63, 4× 9= 36, 6× 10= 60,
					// 7× 5= 35, 2× 8= 16, 3× 4 = 12, 9× 2= 18
					// 第四步: 将乘积求和相加
					// 15 + 63 + 36 + 60 + 35 + 16 + 12 + 18 = 255
					// 第五步: 将和数除以11, 求余数。
					// 255÷ 11 = 33, 余数是2。

					var firstkey = calc(code.substr(8), firstarray, firstkeys, 11);
                    /*
					第六步:用阿拉伯数字11减去余数,得求校验码的数值。当校验码的数值为10时,校验码用英文大写字母X来表示;当校验码的数值为11时,校验码用0来表示;其余求出的校验码数值就用其本身的阿拉伯数字来表示。
                     11-2=9,因此此公司完整的组织机构代码为 59467239-9。
                    */
					// 主题识别码 在主题验证码最后一位(index 8 - 16) 在整体的倒数第二位
					var firstword;
					if (firstkey < 10) {
						firstword = firstkey;
					}
					// eslint-disable-next-line eqeqeq
					if (firstkey == 10) {
						firstword = 'X';
						// eslint-disable-next-line eqeqeq
					} else if (firstkey == 11) {
						firstword = '0';
					}
					// eslint-disable-next-line eqeqeq
					if (firstword != code.substr(16, 1)) {
						debugger
						return false;
					}
                    /*
                         校验码:使用阿拉伯数字或大写英文字母来表示。校验码的计算方法参照 GB/T 17710。
                         例如:某公司的统一社会信用代码为91512081MA62K0260E,那其最后一位的校验码E是如何计算出来的呢?
						 第一步:取统一社会信用代码的前十七位为基数。9 1 5 1 2 0 8 1 21 10 6 2 19 0 2 6 0提示:如果前十七位统一社会信用代码含有英文大写字母(不使用I、O、Z、S、V这五个英文字母)。
						 则英文字母对应的基数分别为:A=10、B=11、C=12、D=13、E=14、F=15、G=16、H=17、J=18、K=19、L=20、M=21、N=22、P=23、Q=24、R=25、T=26、U=27、W=28、X=29、Y=30
						 第二步: 取加权因子数值。 因为统一社会信用代码前面前面有十七位字符。 则这十七位的加权因子数值从左到右分别是, 1、 3、 9、 27、 19、 26、 16、 17、 20、 29、 25、 13、 8、 24、 10、30 、28
                         第三步:基数与对应位数的因子数值相乘。
                         9×1=9,1×3=3,5×9=45,1×27=27,2×19=38,0×26=0,8×16=128
                         1×17=17,21×20=420,10×29=290,6×25=150,2×13=26,19×8=152
                         0×23=0,2×10=20,6×30=180,0×28=0
                         第四步:将乘积求和相加。9+3+45+27+38+0+128+17+420+290+150+26+152+0+20+180+0=1495
                         第五步:将和数除以31,求余数
                         1495÷31=48,余数是17。
                    */
					// 校验码 在整体的最后一位
					var secondkey = calc(code, secondarray, secondkeys, 31);
					// 当数值等31的时候 将值设置为 0
					secondkey = secondkey === 31 ? 0 : secondkey;
                    /*
					 第六步:用阿拉伯数字31减去余数,得求校验码的数值。当校验码的数值为0~9时,就直接用该校验码的数值作为最终的统一社会信用代码的校验码;如果校验码的数值是10~30,
					 则校验码转换为对应的大写英文字母。对应关系为:A=10、B=11、C=12、D=13、E=14、F=15、G=16、H=17、J=18、K=19、L=20、M=21、N=22、P=23、Q=24、R=25、T=26、U=27、W=28、X=29、Y=30
                     因为,31-17=14,所以该公司完整的统一社会信用代码为 91512081MA62K0260E.
                    */
					var secondword = secondarray[secondkey];
					// eslint-disable-next-line eqeqeq
					if (!secondword || secondword != code.substr(17, 1)) {
						return false;
					}
					var word = code.substr(0, 16) + firstword + secondword;
					// eslint-disable-next-line eqeqeq
					if (code != word) {
						return false;
					}
					return true;
				}
				if (!value) {
					return callback(new Error('请填写统一社会信用代码'))
				} else if (!verify(value)) {
					return callback(new Error('格式不正确'))
				} else {
					callback()
				}
			},
			// 国内手机号
			checkPhone: (rule, value, callback) => {
				const reg = /^1[3|4|5|7|8][0-9]{9}$/
				if (!value) {
					return callback()
				} else if (!reg.test(value)) {
					return callback(new Error('手机号格式不正确'))
				} else {
					callback()
				}
			},
			/**
    		* @description: 电话或者手机号的验证
			* 匹配格式:
			*   11位手机号码
			*   3-4位区号,7-8位直播号码,1-4位分机号
			*   如:12345678901、1234-12345678-1234
    		*/
			checkTel: (isRequired = true) => {
				const validator = (rule, value, callback) => {
					const reg = /((\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)/
					if (!value) {
						if (isRequired) {
							return callback(new Error('不能为空'))
						} else {
							return callback()
						}
					} else if (!reg.test(value)) {
						return callback(new Error('电话或者手机号格式不正确'))
					} else {
						callback()
					}
				};
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// email邮箱
			checkEmail: (isRequired = true) => {
				const validator = (rule, value, callback) => {
					const reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
					if (!value) {
						if (isRequired) {
							return callback(new Error('不能为空'))
						} else {
							return callback()
						}
					} else if (!reg.test(value)) {
						return callback(new Error('邮箱格式不正确'))
					} else {
						callback()
					}
				};
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 正整数(默认不包含0)
			checkInterNum: (isRequired = true, text = '请输入', maxLength = 8, includeZero = false) => {
				const validator = (rule, value, callback) => {
					const reg = /^[1-9][0-9]*$/;
					const max = Math.pow(10, maxLength);
					if (!value) {
						if (isRequired) {
							return callback(new Error(text))
						} else {
							return callback()
						}
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && includeZero) {
						// 允许输入 0
						return callback()
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && !includeZero) {
						// 不允许输入 0
						return callback(new Error(`不能为0`))
					} else if (Number(value) > max) {
						return callback(new Error(`请输入小于等于${max}的数`))
					} else if (!reg.test(value)) {
						return callback(new Error(`请输入的整数`))
					} else {
						callback()
					}
				}
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 验证浮点数   主要用于税率 税率(包含0)
			checkFloatNum: (isRequired = true, text = '请输入', maxLength = 5, includeZero = true) => {
				const max = Math.pow(10, maxLength);
				const validator = (rule, value, callback) => {
					const reg = /(^[1-9](\d+)?(\.\d{1,5})?$)|(^\d\.\d{1,5}$)/;
					if (!value) {
						if (isRequired) {
							return callback(new Error(text))
						} else {
							return callback()
						}
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && includeZero) {
						// 允许输入 0
						return callback()
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && !includeZero) {
						// 不允许输入 0
						return callback(new Error(`不能为0`))
					} else if (Number(value) > max) {
						return callback(new Error(`请输入小于等于${max}的数`))
					} else if (!reg.test(value)) {
						return callback(new Error(`最多为5位小数`))
					} else {
						callback()
					}
				}
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 验证最大值为某个变量的浮点数
			checkFloatNumMax: (max = 999999999, isRequired = true, text = '请输入', includeZero = true) => {
				console.log(max);
				const validator = (rule, value, callback) => {
					const reg = /(^[1-9](\d+)?(\.\d{1,5})?$)|(^\d\.\d{1,5}$)/;
					if (!value) {
						if (isRequired) {
							return callback(new Error("必填项"))
						} else {
							return callback()
						}
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && includeZero) {
						// 允许输入 0
						return callback()
						// eslint-disable-next-line eqeqeq
					} else if (value == 0 && !includeZero) {
						// 不允许输入 0
						return callback(new Error(`不能为0`))
					} else if (Number(value) > max) {
						return callback(new Error(text))
					} else if (!reg.test(value)) {
						return callback(new Error('最多为5位小数'))
					} else {
						callback()
					}
				}
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 身份证
			checkIdNum: (isRequired = true) => {
				const validator = (rule, value, callback) => {
					const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
					if (!value) {
						if (isRequired) {
							return callback(new Error('证件号码不能为空'))
						} else {
							return callback()
						}
					} else if (!reg.test(value)) {
						return callback(new Error('证件号码格式不正确'))
					} else {
						callback()
					}
				};
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 护照
			checkPassport: (isRequired = true) => {
				const validator = (rule, value, callback) => {
					const reg = /^1[45][0-9]{7}|([P|p|S|s]\d{7})|([S|s|G|g]\d{8})|([Gg|Tt|Ss|Ll|Qq|Dd|Aa|Ff]\d{8})|([H|h|M|m]\d{8,10})$/;
					if (!value) {
						if (isRequired) {
							return callback(new Error('护照号码不能为空'))
						} else {
							return callback()
						}
					} else if (!reg.test(value)) {
						return callback(new Error('护照号码格式不正确'))
					} else {
						callback()
					}
				};
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 银行卡长度校验
			checkBankNo: (isRequired = true) => {
				const validator = (rule, value, callback) => {
					const reg = /^\d*$/;
					if (!value) {
						if (isRequired) {
							return callback(new Error('卡号不能为空'))
						} else {
							return callback()
						}
					} else if (!reg.test(value)) {
						return callback(new Error('卡号必须全为数字'))
					} else if (value.length < 16 || value.length > 19) {
						return callback(new Error('卡号长度必须在16到19之间'))
					} else {
						callback()
					}
				};
				return { required: isRequired, validator: validator, trigger: 'blur' }
			},
			// 类似金钱,首位不为0,最多2位小数
			checkMoney: (rule, value, callback) => {
				const reg = /(^[1-9]([0-9]{1,10})?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/
				return {
					pattern: reg,
					message: '整数位应小于等于11位,小数位为2位',
					trigger: 'blur'
				}
			},
			// 4位数验证码
			checkVerificationCode: (rule, value, callback) => {
				const reg = /^\d{6}$/
				if (!value) {
					return callback(new Error('请输入验证码'))
				} else if (!reg.test(value)) {
					return callback(new Error('请输入正确的验证码'))
				} else {
					callback()
				}
			}

		}
	}
}

存储localStorage

import {
	validatenull
} from 'js/validate'
/**
 * 存储localStorage
 */
export const setStore = (params) => {
	const {
		name,
		content,
		type
	} = params;
	const obj = {
		dataType: typeof (content),
		content: content,
		type: type,
		datetime: new Date().getTime()
	}
	if (type) window.sessionStorage.setItem(name, JSON.stringify(obj))
	else window.localStorage.setItem(name, JSON.stringify(obj))
}
/**
 * 获取localStorage
 */
export const getStore = (params) => {
	const { name } = params;
	let obj = {};
	let content = null;
	// 默认取localStorage
	obj = window.localStorage.getItem(name)
	// 判断为空 取sessionStorage
	if (validatenull(obj)) obj = window.sessionStorage.getItem(name);
	// sessionStorage为空 返回null
	if (validatenull(obj)) return null;
	obj = JSON.parse(obj)
	if (obj.dataType === 'number') {
		content = Number(obj.content)
	} else if (obj.dataType === 'boolean') {
		// eslint-disable-next-line no-eval
		content = eval(obj.content)
	} else {
		content = obj.content
	}
	return content;
}
/**
 * 删除localStorage
 */
export const removeStore = params => {
	let {
		name
	} = params;
	window.localStorage.removeItem(name);
	window.sessionStorage.removeItem(name);
}

正则校验 validate

//正则校验

export function isvalidUsername(str) {
	const valid_map = ['admin', 'editor']
	return valid_map.indexOf(str.trim()) >= 0
}

/* 合法uri*/
export function validateURL(textval) {
	const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
	return urlregex.test(textval)
}

/* 小写字母*/
export function validateLowerCase(str) {
	const reg = /^[a-z]+$/
	return reg.test(str)
}

/* 大写字母*/
export function validateUpperCase(str) {
	const reg = /^[A-Z]+$/
	return reg.test(str)
}

/* 大小写字母*/
export function validatAlphabets(str) {
	const reg = /^[A-Za-z]+$/
	return reg.test(str)
}
/*验证pad还是pc*/
export const vaildatePc = function () {
	const userAgentInfo = navigator.userAgent;
	const Agents = ["Android", "iPhone",
		"SymbianOS", "Windows Phone",
		"iPad", "iPod"
	];
	let flag = true;
	for (var v = 0; v < Agents.length; v++) {
		if (userAgentInfo.indexOf(Agents[v]) > 0) {
			flag = false;
			break;
		}
	}
	return flag;
}
/**
 * validate email
 * @param email
 * @returns {boolean}
 */
export function validateEmail(email) {
	const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
	return re.test(email)
}

/**
 * 判断身份证号码
 */
export function cardid(code) {
	let list = [];
	let result = true;
	let msg = '';
	var city = {
		11: "北京",
		12: "天津",
		13: "河北",
		14: "山西",
		15: "内蒙古",
		21: "辽宁",
		22: "吉林",
		23: "黑龙江 ",
		31: "上海",
		32: "江苏",
		33: "浙江",
		34: "安徽",
		35: "福建",
		36: "江西",
		37: "山东",
		41: "河南",
		42: "湖北 ",
		43: "湖南",
		44: "广东",
		45: "广西",
		46: "海南",
		50: "重庆",
		51: "四川",
		52: "贵州",
		53: "云南",
		54: "西藏 ",
		61: "陕西",
		62: "甘肃",
		63: "青海",
		64: "宁夏",
		65: "新疆",
		71: "台湾",
		81: "香港",
		82: "澳门",
		91: "国外 "
	};
	if (!validatenull(code)) {
		if (code.length == 18) {
			if (!code || !/(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(code)) {
				msg = "证件号码格式错误";
			} else if (!city[code.substr(0, 2)]) {
				msg = "地址编码错误";
			} else {
				//18位身份证需要验证最后一位校验位
				code = code.split('');
				//∑(ai×Wi)(mod 11)
				//加权因子
				var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
				//校验位
				var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, 'x'];
				var sum = 0;
				var ai = 0;
				var wi = 0;
				for (var i = 0; i < 17; i++) {
					ai = code[i];
					wi = factor[i];
					sum += ai * wi;
				}
				var last = parity[sum % 11];
				if (parity[sum % 11] != code[17]) {
					msg = "证件号码校验位错误";
				} else {
					result = false;
				}

			}
		} else {
			msg = "证件号码长度不为18位";
		}

	} else {
		msg = "证件号码不能为空";
	}
	list.push(result);
	list.push(msg);
	return list;
}
/**
 * 判断手机号码是否正确
 */
export function isvalidatemobile(phone) {
	let list = [];
	let result = true;
	let msg = '';
	var isPhone = /^0\d{2,3}-?\d{7,8}$/;
	//增加134 减少|1349[0-9]{7},增加181,增加145,增加17[678]
	var isMob = /^((\+?86)|(\(\+86\)))?(13[0123456789][0-9]{8}|15[012356789][0-9]{8}|18[012356789][0-9]{8}|14[57][0-9]{8}|17[3678][0-9]{8})$/;
	if (!validatenull(phone)) {
		if (phone.length == 11) {
			if (isPhone.test(phone)) {
				msg = '手机号码格式不正确';
			} else {
				result = false;
			}
		} else {
			msg = '手机号码长度不为11位';
		}
	} else {
		msg = '手机号码不能为空';
	}
	list.push(result);
	list.push(msg);
	return list;
}
/**
 * 判断姓名是否正确
 */
export function validatename(name) {
	var regName = /^[\u4e00-\u9fa5]{2,4}$/;
	if (!regName.test(name)) return false;
	return true;
};
/**
 * 判断是否为整数
 */
export function validatenum(num, type) {
	let regName = /[^\d.]/g;
	if (type == 1) {
		if (!regName.test(num)) return false;
	} else if (type == 2) {
		regName = /[^\d]/g;
		if (!regName.test(num)) return false;
	}
	return true;
};
/**
 * 判断是否为小数
 */
export function validatenumord(num, type) {
	let regName = /[^\d.]/g;
	if (type == 1) {
		if (!regName.test(num)) return false;
	} else if (type == 2) {
		regName = /[^\d.]/g;
		if (!regName.test(num)) return false;
	}
	return true;
};
/**
 * 判断是否为空
 */
export function validatenull(val) {
	if (val instanceof Array) {
		if (val.length == 0) return true;
	} else if (val instanceof Object) {
		if (JSON.stringify(val) === '{}') return true;
	} else {
		if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true;
		return false;
	}
	return false;

};

计算设置布局高度 setLayoutHeight

/*
 * @Description: 计算设置布局高度
 * @Author: jiaxin
 * @Date: 2019-05-20 16:12:11
 * @LastEditors: jiaxin
 * @LastEditTime: 2019-08-15 10:42:18
 */
import { mapGetters } from 'vuex';
export default {
	data() {
		return {
			// 整个内容区域高度
			contentH: 500,
			// 主表格高度
			tableMaxH: 500,
			// 上部分表格高度
			TopTableMaxH: 500,
			// 下部分表格高度
			BottomTableMaxH: 500
		}
	},
	mounted() {
		this.resetLayout();
	},
	computed: {
		...mapGetters(["windowH"])
	},
	watch: {
		windowH() {
			this.resetLayout();
		}
	},
	methods: {
		resetLayout() {
			this.$nextTick(() => {
				// 内容高度
				this.contentH = $("#content").height();
				// 单表格页面布局部分
				const pagesH = $(".el-pagination").height() || 0;
				const pagesMT = $(".el-pagination").css("margin-top") || 0;
                //10 预设下部边缘的边距
				this.tableMaxH = $("#content").height() - $(".setup-box").height() - pagesH - parseInt(pagesMT) - 10;

				// 上下布局部分 ------------------------------------------
				// 上部分高度
				const contentTop = $("#top-list").height();
				// 下部分高度
				const contentBottom = $("#bot-list").height();
				// 搜索和按钮高度
				const setupBox = $("#top-list .setup-box").height() || 0;
				// 分页及其边距高度
				const topPagesH = $("#top-list .pagination").height() || 0;
				// TABS高度
				const tabH = $("#bot-list .el-tabs").height() || 0;

				//上部表高度
				this.TopTableMaxH = contentTop - setupBox - topPagesH;
				// 下部表高度
				this.BottomTableMaxH = contentBottom - tabH - 5;
			})
		}
	}
}