utils.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /**
  2. * 简单处理对象拷贝
  3. * @param {Obejct} 被拷贝对象
  4. * @@return {Object} 拷贝对象
  5. */
  6. export const deepCopy = (val) => {
  7. return JSON.parse(JSON.stringify(val))
  8. }
  9. /**
  10. * 过滤数字类型
  11. * @param {String} format 数字类型
  12. * @@return {Boolean} 返回是否为数字类型
  13. */
  14. export const typeFilter = (format) => {
  15. return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
  16. }
  17. /**
  18. * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
  19. * @param {String} key 字段名
  20. * @param {any} value 字段值
  21. * @param {Object} rules 表单校验规则
  22. */
  23. export const getValue = (key, value, rules) => {
  24. const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
  25. const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
  26. // 输入类型为 number
  27. if (!!isRuleNumType) {
  28. if (!value && value !== 0) {
  29. value = null
  30. } else {
  31. value = isNumber(Number(value)) ? Number(value) : value
  32. }
  33. }
  34. // 输入类型为 boolean
  35. if (!!isRuleBoolType) {
  36. value = isBoolean(value) ? value : false
  37. }
  38. return value;
  39. }
  40. /**
  41. * 获取表单数据
  42. * @param {String|Array} name 真实名称,需要使用 realName 获取
  43. * @param {Object} data 原始数据
  44. * @param {any} value 需要设置的值
  45. */
  46. export const setDataValue = (field, formdata, value) => {
  47. formdata[field] = value
  48. return value || ''
  49. }
  50. /**
  51. * 获取表单数据
  52. * @param {String|Array} field 真实名称,需要使用 realName 获取
  53. * @param {Object} data 原始数据
  54. */
  55. export const getDataValue = (field, data) => {
  56. return objGet(data, field)
  57. }
  58. /**
  59. * 获取表单类型
  60. * @param {String|Array} field 真实名称,需要使用 realName 获取
  61. */
  62. export const getDataValueType = (field, data) => {
  63. const value = getDataValue(field, data)
  64. return {
  65. type: type(value),
  66. value
  67. }
  68. }
  69. /**
  70. * 获取表单可用的真实name
  71. * @param {String|Array} name 表单name
  72. * @@return {String} 表单可用的真实name
  73. */
  74. export const realName = (name, data = {}) => {
  75. const base_name = _basePath(name)
  76. if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
  77. const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
  78. return realname
  79. }
  80. return base_name[0] || name
  81. }
  82. /**
  83. * 判断是否表单可用的真实name
  84. * @param {String|Array} name 表单name
  85. * @@return {String} 表单可用的真实name
  86. */
  87. export const isRealName = (name) => {
  88. const reg = /^_formdata_#*/
  89. return reg.test(name)
  90. }
  91. /**
  92. * 获取表单数据的原始格式
  93. * @@return {Object|Array} object 需要解析的数据
  94. */
  95. export const rawData = (object = {}, name) => {
  96. let newData = JSON.parse(JSON.stringify(object))
  97. let formData = {}
  98. for(let i in newData){
  99. let path = name2arr(i)
  100. objSet(formData,path,newData[i])
  101. }
  102. return formData
  103. }
  104. /**
  105. * 真实name还原为 array
  106. * @param {*} name
  107. */
  108. export const name2arr = (name) => {
  109. let field = name.replace('_formdata_#', '')
  110. field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
  111. return field
  112. }
  113. /**
  114. * 对象中设置值
  115. * @param {Object|Array} object 源数据
  116. * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
  117. * @param {String} value 需要设置的值
  118. */
  119. export const objSet = (object, path, value) => {
  120. if (typeof object !== 'object') return object;
  121. _basePath(path).reduce((o, k, i, _) => {
  122. if (i === _.length - 1) {
  123. // 若遍历结束直接赋值
  124. o[k] = value
  125. return null
  126. } else if (k in o) {
  127. // 若存在对应路径,则返回找到的对象,进行下一次遍历
  128. return o[k]
  129. } else {
  130. // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
  131. o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
  132. return o[k]
  133. }
  134. }, object)
  135. // 返回object
  136. return object;
  137. }
  138. // 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
  139. function _basePath(path) {
  140. // 若是数组,则直接返回
  141. if (Array.isArray(path)) return path
  142. // 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
  143. return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
  144. }
  145. /**
  146. * 从对象中获取值
  147. * @param {Object|Array} object 源数据
  148. * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
  149. * @param {String} defaultVal 如果无法从调用链中获取值的默认值
  150. */
  151. export const objGet = (object, path, defaultVal = 'undefined') => {
  152. // 先将path处理成统一格式
  153. let newPath = _basePath(path)
  154. // 递归处理,返回最后结果
  155. let val = newPath.reduce((o, k) => {
  156. return (o || {})[k]
  157. }, object);
  158. return !val || val !== undefined ? val : defaultVal
  159. }
  160. /**
  161. * 是否为 number 类型
  162. * @param {any} num 需要判断的值
  163. * @return {Boolean} 是否为 number
  164. */
  165. export const isNumber = (num) => {
  166. return !isNaN(Number(num))
  167. }
  168. /**
  169. * 是否为 boolean 类型
  170. * @param {any} bool 需要判断的值
  171. * @return {Boolean} 是否为 boolean
  172. */
  173. export const isBoolean = (bool) => {
  174. return (typeof bool === 'boolean')
  175. }
  176. /**
  177. * 是否有必填字段
  178. * @param {Object} rules 规则
  179. * @return {Boolean} 是否有必填字段
  180. */
  181. export const isRequiredField = (rules) => {
  182. let isNoField = false;
  183. for (let i = 0; i < rules.length; i++) {
  184. const ruleData = rules[i];
  185. if (ruleData.required) {
  186. isNoField = true;
  187. break;
  188. }
  189. }
  190. return isNoField;
  191. }
  192. /**
  193. * 获取数据类型
  194. * @param {Any} obj 需要获取数据类型的值
  195. */
  196. export const type = (obj) => {
  197. var class2type = {};
  198. // 生成class2type映射
  199. "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
  200. class2type["[object " + item + "]"] = item.toLowerCase();
  201. })
  202. if (obj == null) {
  203. return obj + "";
  204. }
  205. return typeof obj === "object" || typeof obj === "function" ?
  206. class2type[Object.prototype.toString.call(obj)] || "object" :
  207. typeof obj;
  208. }
  209. /**
  210. * 判断两个值是否相等
  211. * @param {any} a 值
  212. * @param {any} b 值
  213. * @return {Boolean} 是否相等
  214. */
  215. export const isEqual = (a, b) => {
  216. //如果a和b本来就全等
  217. if (a === b) {
  218. //判断是否为0和-0
  219. return a !== 0 || 1 / a === 1 / b;
  220. }
  221. //判断是否为null和undefined
  222. if (a == null || b == null) {
  223. return a === b;
  224. }
  225. //接下来判断a和b的数据类型
  226. var classNameA = toString.call(a),
  227. classNameB = toString.call(b);
  228. //如果数据类型不相等,则返回false
  229. if (classNameA !== classNameB) {
  230. return false;
  231. }
  232. //如果数据类型相等,再根据不同数据类型分别判断
  233. switch (classNameA) {
  234. case '[object RegExp]':
  235. case '[object String]':
  236. //进行字符串转换比较
  237. return '' + a === '' + b;
  238. case '[object Number]':
  239. //进行数字转换比较,判断是否为NaN
  240. if (+a !== +a) {
  241. return +b !== +b;
  242. }
  243. //判断是否为0或-0
  244. return +a === 0 ? 1 / +a === 1 / b : +a === +b;
  245. case '[object Date]':
  246. case '[object Boolean]':
  247. return +a === +b;
  248. }
  249. //如果是对象类型
  250. if (classNameA == '[object Object]') {
  251. //获取a和b的属性长度
  252. var propsA = Object.getOwnPropertyNames(a),
  253. propsB = Object.getOwnPropertyNames(b);
  254. if (propsA.length != propsB.length) {
  255. return false;
  256. }
  257. for (var i = 0; i < propsA.length; i++) {
  258. var propName = propsA[i];
  259. //如果对应属性对应值不相等,则返回false
  260. if (a[propName] !== b[propName]) {
  261. return false;
  262. }
  263. }
  264. return true;
  265. }
  266. //如果是数组类型
  267. if (classNameA == '[object Array]') {
  268. if (a.toString() == b.toString()) {
  269. return true;
  270. }
  271. return false;
  272. }
  273. }