| /** | 
|  * 简单处理对象拷贝 | 
|  * @param {Obejct} 被拷贝对象 | 
|  * @@return {Object} 拷贝对象 | 
|  */ | 
| export const deepCopy = (val) => { | 
|     return JSON.parse(JSON.stringify(val)) | 
| } | 
| /** | 
|  * 过滤数字类型 | 
|  * @param {String} format 数字类型 | 
|  * @@return {Boolean} 返回是否为数字类型 | 
|  */ | 
| export const typeFilter = (format) => { | 
|     return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp'; | 
| } | 
|   | 
| /** | 
|  * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined | 
|  * @param {String} key 字段名 | 
|  * @param {any} value 字段值 | 
|  * @param {Object} rules 表单校验规则 | 
|  */ | 
| export const getValue = (key, value, rules) => { | 
|     const isRuleNumType = rules.find(val => val.format && typeFilter(val.format)); | 
|     const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool'); | 
|     // 输入类型为 number | 
|     if (!!isRuleNumType) { | 
|         if (!value && value !== 0) { | 
|             value = null | 
|         } else { | 
|             value = isNumber(Number(value)) ? Number(value) : value | 
|         } | 
|     } | 
|   | 
|     // 输入类型为 boolean | 
|     if (!!isRuleBoolType) { | 
|         value = isBoolean(value) ? value : false | 
|     } | 
|   | 
|     return value; | 
| } | 
|   | 
| /** | 
|  * 获取表单数据 | 
|  * @param {String|Array} name 真实名称,需要使用 realName 获取 | 
|  * @param {Object} data 原始数据 | 
|  * @param {any} value  需要设置的值 | 
|  */ | 
| export const setDataValue = (field, formdata, value) => { | 
|     formdata[field] = value | 
|     return value || '' | 
| } | 
|   | 
| /** | 
|  * 获取表单数据 | 
|  * @param {String|Array} field 真实名称,需要使用 realName 获取 | 
|  * @param {Object} data 原始数据 | 
|  */ | 
| export const getDataValue = (field, data) => { | 
|     return objGet(data, field) | 
| } | 
|   | 
| /** | 
|  * 获取表单类型 | 
|  * @param {String|Array} field 真实名称,需要使用 realName 获取 | 
|  */ | 
| export const getDataValueType = (field, data) => { | 
|     const value = getDataValue(field, data) | 
|     return { | 
|         type: type(value), | 
|         value | 
|     } | 
| } | 
|   | 
| /** | 
|  * 获取表单可用的真实name | 
|  * @param {String|Array} name 表单name | 
|  * @@return {String} 表单可用的真实name | 
|  */ | 
| export const realName = (name, data = {}) => { | 
|     const base_name = _basePath(name) | 
|     if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) { | 
|         const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_') | 
|         return realname | 
|     } | 
|     return base_name[0] || name | 
| } | 
|   | 
| /** | 
|  * 判断是否表单可用的真实name | 
|  * @param {String|Array} name 表单name | 
|  * @@return {String} 表单可用的真实name | 
|  */ | 
| export const isRealName = (name) => { | 
|     const reg = /^_formdata_#*/ | 
|     return reg.test(name) | 
| } | 
|   | 
| /** | 
|  * 获取表单数据的原始格式 | 
|  * @@return {Object|Array} object 需要解析的数据 | 
|  */ | 
| export const rawData = (object = {}, name) => { | 
|     let newData = JSON.parse(JSON.stringify(object)) | 
|     let formData = {} | 
|     for(let i in newData){ | 
|         let path = name2arr(i) | 
|         objSet(formData,path,newData[i]) | 
|     } | 
|     return formData | 
| } | 
|   | 
| /** | 
|  * 真实name还原为 array | 
|  * @param {*} name  | 
|  */ | 
| export const name2arr = (name) => { | 
|     let field = name.replace('_formdata_#', '') | 
|     field = field.split('#').map(v => (isNumber(v) ? Number(v) : v)) | 
|     return field | 
| } | 
|   | 
| /** | 
|  * 对象中设置值 | 
|  * @param {Object|Array} object 源数据 | 
|  * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c'] | 
|  * @param {String} value 需要设置的值 | 
|  */ | 
| export const objSet = (object, path, value) => { | 
|     if (typeof object !== 'object') return object; | 
|     _basePath(path).reduce((o, k, i, _) => { | 
|         if (i === _.length - 1) {  | 
|             // 若遍历结束直接赋值 | 
|             o[k] = value | 
|             return null | 
|         } else if (k in o) {  | 
|             // 若存在对应路径,则返回找到的对象,进行下一次遍历 | 
|             return o[k] | 
|         } else {  | 
|             // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象 | 
|             o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {} | 
|             return o[k] | 
|         } | 
|     }, object) | 
|     // 返回object | 
|     return object; | 
| } | 
|   | 
| // 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用 | 
| function _basePath(path) { | 
|     // 若是数组,则直接返回 | 
|     if (Array.isArray(path)) return path | 
|     // 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']' | 
|     return path.replace(/\[/g, '.').replace(/\]/g, '').split('.') | 
| } | 
|   | 
| /** | 
|  * 从对象中获取值 | 
|  * @param {Object|Array} object 源数据 | 
|  * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c'] | 
|  * @param {String} defaultVal 如果无法从调用链中获取值的默认值 | 
|  */ | 
| export const objGet = (object, path, defaultVal = 'undefined') => { | 
|     // 先将path处理成统一格式 | 
|     let newPath = _basePath(path) | 
|     // 递归处理,返回最后结果 | 
|     let val = newPath.reduce((o, k) => { | 
|         return (o || {})[k] | 
|     }, object); | 
|     return !val || val !== undefined ? val : defaultVal | 
| } | 
|   | 
|   | 
| /** | 
|  * 是否为 number 类型  | 
|  * @param {any} num 需要判断的值 | 
|  * @return {Boolean} 是否为 number | 
|  */ | 
| export const isNumber = (num) => { | 
|     return !isNaN(Number(num)) | 
| } | 
|   | 
| /** | 
|  * 是否为 boolean 类型  | 
|  * @param {any} bool 需要判断的值 | 
|  * @return {Boolean} 是否为 boolean | 
|  */ | 
| export const isBoolean = (bool) => { | 
|     return (typeof bool === 'boolean') | 
| } | 
| /** | 
|  * 是否有必填字段 | 
|  * @param {Object} rules 规则 | 
|  * @return {Boolean} 是否有必填字段 | 
|  */ | 
| export const isRequiredField = (rules) => { | 
|     let isNoField = false; | 
|     for (let i = 0; i < rules.length; i++) { | 
|         const ruleData = rules[i]; | 
|         if (ruleData.required) { | 
|             isNoField = true; | 
|             break; | 
|         } | 
|     } | 
|     return isNoField; | 
| } | 
|   | 
|   | 
| /** | 
|  * 获取数据类型 | 
|  * @param {Any} obj 需要获取数据类型的值 | 
|  */ | 
| export const type = (obj) => { | 
|     var class2type = {}; | 
|   | 
|     // 生成class2type映射 | 
|     "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) { | 
|         class2type["[object " + item + "]"] = item.toLowerCase(); | 
|     }) | 
|     if (obj == null) { | 
|         return obj + ""; | 
|     } | 
|     return typeof obj === "object" || typeof obj === "function" ? | 
|         class2type[Object.prototype.toString.call(obj)] || "object" : | 
|         typeof obj; | 
| } | 
|   | 
| /** | 
|  * 判断两个值是否相等 | 
|  * @param {any} a 值   | 
|  * @param {any} b 值   | 
|  * @return {Boolean} 是否相等 | 
|  */ | 
| export const isEqual = (a, b) => { | 
|     //如果a和b本来就全等 | 
|     if (a === b) { | 
|         //判断是否为0和-0 | 
|         return a !== 0 || 1 / a === 1 / b; | 
|     } | 
|     //判断是否为null和undefined | 
|     if (a == null || b == null) { | 
|         return a === b; | 
|     } | 
|     //接下来判断a和b的数据类型 | 
|     var classNameA = toString.call(a), | 
|         classNameB = toString.call(b); | 
|     //如果数据类型不相等,则返回false | 
|     if (classNameA !== classNameB) { | 
|         return false; | 
|     } | 
|     //如果数据类型相等,再根据不同数据类型分别判断 | 
|     switch (classNameA) { | 
|         case '[object RegExp]': | 
|         case '[object String]': | 
|             //进行字符串转换比较 | 
|             return '' + a === '' + b; | 
|         case '[object Number]': | 
|             //进行数字转换比较,判断是否为NaN | 
|             if (+a !== +a) { | 
|                 return +b !== +b; | 
|             } | 
|             //判断是否为0或-0 | 
|             return +a === 0 ? 1 / +a === 1 / b : +a === +b; | 
|         case '[object Date]': | 
|         case '[object Boolean]': | 
|             return +a === +b; | 
|     } | 
|     //如果是对象类型 | 
|     if (classNameA == '[object Object]') { | 
|         //获取a和b的属性长度 | 
|         var propsA = Object.getOwnPropertyNames(a), | 
|             propsB = Object.getOwnPropertyNames(b); | 
|         if (propsA.length != propsB.length) { | 
|             return false; | 
|         } | 
|         for (var i = 0; i < propsA.length; i++) { | 
|             var propName = propsA[i]; | 
|             //如果对应属性对应值不相等,则返回false | 
|             if (a[propName] !== b[propName]) { | 
|                 return false; | 
|             } | 
|         } | 
|         return true; | 
|     } | 
|     //如果是数组类型 | 
|     if (classNameA == '[object Array]') { | 
|         if (a.toString() == b.toString()) { | 
|             return true; | 
|         } | 
|         return false; | 
|     } | 
| } |