index.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /**
  2. * @author 明浩
  3. * @time 2020-8-14
  4. * @dec 工具包
  5. * @dec throttle 节流,debounce 防抖动,请调用 throttle-debounce 插件
  6. */
  7. import moment from "moment";
  8. /**
  9. * 获取URL指定参数
  10. * @param {String} name 参数名称
  11. * @param {String} url 目标URL地址
  12. * @return {String|null} 参数值
  13. */
  14. export function getQueryString(name, url) {
  15. let _url = url || window.location.href;
  16. if (_url.includes("?") && _url.includes(name)) {
  17. let arr = _url
  18. .split("?")
  19. .filter(x => x.includes(name))
  20. .join()
  21. .split("&");
  22. return arr
  23. .find(_ => {
  24. return _.includes(name);
  25. })
  26. .split("=")[1];
  27. } else {
  28. return null;
  29. }
  30. }
  31. /**
  32. * 获取URL参数
  33. * @param {String} url 目标URL地址
  34. * @return {Object} 参数对象
  35. */
  36. export function getQueryObject(url) {
  37. const search = url.split("?")[1];
  38. if (!search) {
  39. return {};
  40. }
  41. return JSON.parse(
  42. '{"' +
  43. decodeURIComponent(search)
  44. .replace(/"/g, '\\"')
  45. .replace(/&/g, '","')
  46. .replace(/=/g, '":"') +
  47. '"}'
  48. );
  49. }
  50. /**
  51. * 非空判断
  52. * @param {String} value 目标值
  53. * @return {Boolean} 是否为空
  54. */
  55. export function isEmpty(value) {
  56. return typeof value === "undefined" || value === "" || value === null;
  57. }
  58. window.isEmpty = isEmpty;
  59. /**
  60. * merge对象
  61. * @param {Object} source 源对象
  62. * @param {Object} target 要merge的对象
  63. * @return {Object} merge后的source
  64. */
  65. export function objectMerge(source, target) {
  66. if (typeof source !== "object") {
  67. source = {};
  68. }
  69. if (Array.isArray(target)) {
  70. return target.slice();
  71. }
  72. for (const property in target) {
  73. if (Object.prototype.hasOwnProperty.call(target, property)) {
  74. const targetProperty = target[property];
  75. if (
  76. typeof targetProperty === "object" &&
  77. !moment.isMoment(targetProperty)
  78. ) {
  79. source[property] = objectMerge(source[property], targetProperty);
  80. continue;
  81. }
  82. source[property] = targetProperty;
  83. }
  84. }
  85. return source;
  86. }
  87. /**
  88. * 数据深拷
  89. * @param {Array|Object} 要拷贝的对象
  90. * @return {Array|Object} 返回拷贝的新对象
  91. */
  92. export function deepClone(source) {
  93. if (!source && typeof source !== "object") {
  94. throw new Error("error arguments", "shallowClone");
  95. }
  96. const targetObj = source.constructor === Array ? [] : {};
  97. for (const keys in source) {
  98. if (Object.prototype.hasOwnProperty.call(source, keys)) {
  99. if (
  100. source[keys] &&
  101. typeof source[keys] === "object" &&
  102. !moment.isMoment(source[keys])
  103. ) {
  104. targetObj[keys] = source[keys].constructor === Array ? [] : {};
  105. targetObj[keys] = deepClone(source[keys]);
  106. } else {
  107. targetObj[keys] = source[keys];
  108. }
  109. }
  110. }
  111. return targetObj;
  112. }
  113. /**
  114. * 添加事件
  115. * @param {Element} el 目标DOM
  116. * @param {String} type 事件类型
  117. * @param {Function} fn 事件方法
  118. * @param {Boolean} capture true为事件捕获/false为事件冒泡 IE678不支持事件捕获,不填默认事件冒泡
  119. */
  120. export function addEvent(el, type, fn, capture) {
  121. if (window.addEventListener) {
  122. if (type === "mousewheel" && document.mozHidden !== undefined) {
  123. type = "DOMMouseScroll";
  124. }
  125. el.addEventListener(type, fn, !!capture);
  126. } else if (window.attachEvent) {
  127. el.attachEvent("on" + type, fn);
  128. }
  129. }
  130. /**
  131. * 移除事件
  132. * @param {Element} el 目标DOM
  133. * @param {String} type 事件类型
  134. * @param {Function} fn 事件方法
  135. * @param {Boolean} capture true为事件捕获/false为事件冒泡 IE678不支持事件捕获,不填默认事件冒泡
  136. */
  137. export function removeEvent(el, type, fn, capture) {
  138. if (window.removeEventListener) {
  139. if (type === "mousewheel" && document.mozHidden !== undefined) {
  140. type = "DOMMouseScroll";
  141. }
  142. el.removeEventListener(type, fn, !!capture);
  143. } else if (window.detachEvent) {
  144. el.detachEvent("on" + type, fn);
  145. }
  146. }
  147. /**
  148. * 解决浮点型计算精度问题
  149. * @param {Number} f 计算表达式
  150. * @param {Number} digit 保留小数点几位
  151. * @param {Boolean} isNotRound false为四舍五路
  152. * @return {Number} 计算后的表达式结果
  153. */
  154. export function formatFloat(f, digit = 2, isNotRound) {
  155. if (arguments.length === 2 && typeof arguments[1] === "boolean") {
  156. isNotRound = arguments[1];
  157. digit = 2;
  158. }
  159. if (isNaN(Number(f))) {
  160. throw new Error("parameters cannot be non-numeric for formatFloat method");
  161. } else {
  162. if (typeof f === "string") {
  163. f = Number(f);
  164. }
  165. }
  166. f = f.toFixed(10);
  167. let m = Math.pow(10, digit);
  168. if (isNotRound) {
  169. return parseInt(f * m, 10) / m;
  170. }
  171. let _abs = 1;
  172. if (f < 0) {
  173. f = Math.abs(f);
  174. _abs = -1;
  175. }
  176. return (Math.round(f * m, 10) / m) * _abs;
  177. }
  178. /**
  179. * 深冻结
  180. * @param {Object} o 要冻结的对象
  181. * @return {Object} 冻结后的源对象
  182. */
  183. export function deepFreeze(o) {
  184. var prop, propKey;
  185. Object.freeze(o);
  186. for (propKey in o) {
  187. prop = o[propKey];
  188. if (
  189. !Object.prototype.hasOwnProperty.call(o, propKey) ||
  190. !(typeof prop === "object") ||
  191. Object.isFrozen(prop)
  192. ) {
  193. continue;
  194. }
  195. deepFreeze(prop);
  196. }
  197. }
  198. /**
  199. * 获取随机数
  200. * @param {String} str 随机数开头字母
  201. * @param {Number} n 随机数个数
  202. * @return {String} 生成的随机数
  203. */
  204. export function getRandomNum(str = "", n = 12) {
  205. if (typeof n === "string") {
  206. n = Number(n);
  207. }
  208. n += 2;
  209. return str + String(Math.random()).slice(2, n);
  210. }
  211. /**
  212. * trigger 扩展dispatchEvent事件语法,兼容IE
  213. * @param {Element} element 目标DOM
  214. * @param {String} event 事件类型
  215. */
  216. export function trigger(element, event) {
  217. if (document.createEventObject) {
  218. // IE浏览器支持fireEvent方法
  219. let evt = document.createEventObject();
  220. evt.dispatchEvent = true;
  221. return element.fireEvent("on" + event, evt);
  222. } else {
  223. // 其他标准浏览器使用dispatchEvent方法
  224. let evt = document.createEvent("HTMLEvents");
  225. evt.initEvent(event, true, true);
  226. evt.dispatchEvent = true;
  227. return !element.dispatchEvent(evt);
  228. }
  229. }
  230. /**
  231. * 格式化children
  232. * @param {Array} data 格式化数据
  233. * @param {String} clearEmptyChildren string为child的key命名 去除空数组的children对象
  234. */
  235. export function formatChildren({ data, clearEmptyChildren }) {
  236. if (clearEmptyChildren) {
  237. data = data.map(item => {
  238. if (item[clearEmptyChildren]) {
  239. if (item[clearEmptyChildren].length < 1) {
  240. delete item[clearEmptyChildren];
  241. } else {
  242. item[clearEmptyChildren] = formatChildren({
  243. data: item[clearEmptyChildren],
  244. clearEmptyChildren
  245. });
  246. }
  247. }
  248. return item;
  249. });
  250. }
  251. return data;
  252. }
  253. /**
  254. * 设别判断
  255. * @returns string
  256. */
  257. export function getDevice() {
  258. const u = navigator.userAgent;
  259. // console.log(u)
  260. let device = "";
  261. if (u.indexOf("Android") > -1 || u.indexOf("Linux") > -1) {
  262. // console.log('android')
  263. device = "android";
  264. } else if (u.indexOf("iPhone") > -1 && u.indexOf("Safari") === -1) {
  265. // console.log('ios', 11111)
  266. device = "ios";
  267. } else if (u.indexOf("MicroMessenger") > -1) {
  268. // console.log('wechat')
  269. device = "wechat";
  270. } else {
  271. // console.log('web',2222)
  272. device = "web";
  273. }
  274. return device;
  275. }
  276. /**
  277. * 将文件转化为base64
  278. * @author wfyuan 2020-02-27
  279. * @param {*} file 待转换的文件
  280. * @returns base64文件流
  281. */
  282. export function fileToBase64(file) {
  283. let reader = new FileReader();
  284. reader.readAsDataURL(file[0]);
  285. reader.onload = function() {
  286. return this.result;
  287. };
  288. }
  289. /**
  290. * 将base64转换为文件
  291. * @param {*} dataurl base64数据
  292. * @param {*} filename 文件名(示例:img.jpg)
  293. */
  294. export function convertBase64UrlToFile(dataurl, filename) {
  295. let arr = dataurl.split(","),
  296. mime = arr[0].match(/:(.*?);/)[1],
  297. bstr = atob(arr[1]),
  298. n = bstr.length,
  299. u8arr = new Uint8Array(n);
  300. while (n--) {
  301. u8arr[n] = bstr.charCodeAt(n);
  302. }
  303. return new File([u8arr], filename, { type: mime });
  304. }
  305. /**
  306. * 给对象注入属性
  307. * @param keys 属性key数组, 如 keys = ['config', 'path'] , 则会给对象注入 object.config.path 的属性
  308. * @param value 属性值
  309. * @returns {Object}
  310. */
  311. Object.defineProperty(Object.prototype, "assignProps", {
  312. writable: false,
  313. enumerable: false,
  314. configurable: true,
  315. value: function(keys, value) {
  316. let props = this;
  317. for (let i = 0; i < keys.length; i++) {
  318. let key = keys[i];
  319. if (i == keys.length - 1) {
  320. props[key] = value;
  321. } else {
  322. props[key] = props[key] == undefined ? {} : props[key];
  323. props = props[key];
  324. }
  325. }
  326. return this;
  327. }
  328. });
  329. /**
  330. * 非空判断
  331. */
  332. export function isDef(v) {
  333. return v !== undefined && v !== null;
  334. }
  335. /**
  336. * 从数组中删除.
  337. */
  338. export function remove(arr, item) {
  339. if (arr.length) {
  340. const index = arr.indexOf(item);
  341. if (index > -1) {
  342. return arr.splice(index, 1);
  343. }
  344. }
  345. }
  346. const _toString = Object.prototype.toString;
  347. /**
  348. * 是否为正则
  349. */
  350. export function isRegExp(v) {
  351. return _toString.call(v) === "[object RegExp]";
  352. }
  353. /**
  354. * 把对象按照 js配置文件的格式进行格式化
  355. * @param obj 格式化的对象
  356. * @param dep 层级,此项无需传值
  357. * @returns {string}
  358. */
  359. export function formatConfig(obj, dep) {
  360. dep = dep || 1;
  361. const LN = "\n",
  362. TAB = " ";
  363. let indent = "";
  364. for (let i = 0; i < dep; i++) {
  365. indent += TAB;
  366. }
  367. let isArray = false,
  368. arrayLastIsObj = false;
  369. let str = "",
  370. prefix = "{",
  371. subfix = "}";
  372. if (Array.isArray(obj)) {
  373. isArray = true;
  374. prefix = "[";
  375. subfix = "]";
  376. str = obj
  377. .map((item, index) => {
  378. let format = "";
  379. if (typeof item == "function") {
  380. //
  381. } else if (typeof item == "object") {
  382. arrayLastIsObj = true;
  383. format = `${LN}${indent}${formatConfig(item, dep + 1)},`;
  384. } else if (
  385. (typeof item == "number" && !isNaN(item)) ||
  386. typeof item == "boolean"
  387. ) {
  388. format = `${item},`;
  389. } else if (typeof item == "string") {
  390. format = `'${item}',`;
  391. }
  392. if (index == obj.length - 1) {
  393. format = format.substring(0, format.length - 1);
  394. } else {
  395. arrayLastIsObj = false;
  396. }
  397. return format;
  398. })
  399. .join("");
  400. } else if (typeof obj != "function" && typeof obj == "object") {
  401. str = Object.keys(obj)
  402. .map((key, index, keys) => {
  403. const val = obj[key];
  404. let format = "";
  405. if (typeof val == "function") {
  406. //
  407. } else if (typeof val == "object") {
  408. format = `${LN}${indent}${key}: ${formatConfig(val, dep + 1)},`;
  409. } else if (
  410. (typeof val == "number" && !isNaN(val)) ||
  411. typeof val == "boolean"
  412. ) {
  413. format = `${LN}${indent}${key}: ${val},`;
  414. } else if (typeof val == "string") {
  415. format = `${LN}${indent}${key}: '${val}',`;
  416. }
  417. if (index == keys.length - 1) {
  418. format = format.substring(0, format.length - 1);
  419. }
  420. return format;
  421. })
  422. .join("");
  423. }
  424. const len = TAB.length;
  425. if (indent.length >= len) {
  426. indent = indent.substring(0, indent.length - len);
  427. }
  428. if (!isArray || arrayLastIsObj) {
  429. subfix = LN + indent + subfix;
  430. }
  431. return `${prefix}${str}${subfix}`;
  432. }
  433. /**
  434. * 清理空值,对象
  435. * @param children
  436. * @returns {*[]}
  437. */
  438. export function filterEmpty(children = []) {
  439. return children.filter(c => c.tag || (c.text && c.text.trim() !== ""));
  440. }
  441. /**
  442. * 获取字符串长度,英文字符 长度1,中文字符长度2
  443. * @param {*} str
  444. */
  445. export const getStrFullLength = (str = "") =>
  446. str.split("").reduce((pre, cur) => {
  447. const charCode = cur.charCodeAt(0);
  448. if (charCode >= 0 && charCode <= 128) {
  449. return pre + 1;
  450. }
  451. return pre + 2;
  452. }, 0);
  453. /**
  454. * 截取字符串,根据 maxLength 截取后返回
  455. * @param {*} str
  456. * @param {*} maxLength
  457. */
  458. export const cutStrByFullLength = (str = "", maxLength) => {
  459. let showLength = 0;
  460. return str.split("").reduce((pre, cur) => {
  461. const charCode = cur.charCodeAt(0);
  462. if (charCode >= 0 && charCode <= 128) {
  463. showLength += 1;
  464. } else {
  465. showLength += 2;
  466. }
  467. if (showLength <= maxLength) {
  468. return pre + cur;
  469. }
  470. return pre;
  471. }, "");
  472. };
  473. /**
  474. * @author 明浩
  475. * @time 2020-08-21
  476. * @dec 将parentId 转 children
  477. */
  478. export function translateDataToTree(data) {
  479. let parents = data.filter(
  480. value =>
  481. value.parentId === undefined ||
  482. value.parentId === null ||
  483. value.parentId === "" ||
  484. value.parentId === "0"
  485. );
  486. let children = data.filter(
  487. value =>
  488. value.parentId !== "undefined" &&
  489. value.parentId !== null &&
  490. value.parentId !== "" &&
  491. value.parentId !== "0"
  492. );
  493. let translator = (parents, children) => {
  494. parents.forEach(parent => {
  495. children.forEach((current, index) => {
  496. if (current.parentId === parent.id) {
  497. let temp = JSON.parse(JSON.stringify(children));
  498. temp.splice(index, 1);
  499. translator([current], temp);
  500. typeof parent.children !== "undefined"
  501. ? parent.children.push(current)
  502. : (parent.children = [current]);
  503. }
  504. });
  505. });
  506. };
  507. translator(parents, children);
  508. return parents;
  509. }
  510. /**
  511. * contentd导出数据,fileName文件名
  512. */
  513. export function exportDownload(content, fileName) {
  514. const blob = new Blob([content], {
  515. type: "application/vnd.ms-excel;charset=utf-8"
  516. }); // 构造一个blob对象来处理数据
  517. if ("download" in document.createElement("a")) {
  518. // 支持a标签download的浏览器
  519. const link = document.createElement("a"); // 创建a标签
  520. link.download = fileName; // a标签添加属性导出文件名
  521. link.style.display = "none";
  522. link.href = URL.createObjectURL(blob);
  523. document.body.appendChild(link);
  524. link.click(); // 执行下载
  525. URL.revokeObjectURL(link.href); // 释放url
  526. document.body.removeChild(link); // 释放标签
  527. } else {
  528. // 其他浏览器
  529. navigator.msSaveBlob(blob, fileName);
  530. }
  531. }