index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /**
  2. * 解析参数
  3. * @param {string} url
  4. * @returns {Object}
  5. */
  6. export function getQueryObject(url) {
  7. url = url == null ? window.location.href : url
  8. const search = url.substring(url.lastIndexOf('?') + 1)
  9. const obj = {}
  10. const reg = /([^?&=]+)=([^?&=]*)/g
  11. search.replace(reg, (rs, $1, $2) => {
  12. const name = decodeURIComponent($1)
  13. let val = decodeURIComponent($2)
  14. val = String(val)
  15. obj[name] = val
  16. return rs
  17. })
  18. return obj
  19. }
  20. /**
  21. * 返回字符串的大小byte
  22. * @param {string} input value
  23. * @returns {number} output value
  24. */
  25. export function byteLength(str) {
  26. // returns the byte length of an utf8 string
  27. let s = str.length
  28. for (var i = str.length - 1; i >= 0; i--) {
  29. const code = str.charCodeAt(i)
  30. if (code > 0x7f && code <= 0x7ff) s++
  31. else if (code > 0x7ff && code <= 0xffff) s += 2
  32. if (code >= 0xDC00 && code <= 0xDFFF) i--
  33. }
  34. return s
  35. }
  36. /**
  37. * @param {Array} actual
  38. * @returns {Array}
  39. */
  40. export function cleanArray(actual) {
  41. const newArray = []
  42. for (let i = 0; i < actual.length; i++) {
  43. if (actual[i]) {
  44. newArray.push(actual[i])
  45. }
  46. }
  47. return newArray
  48. }
  49. /**
  50. * 将json换成get传参
  51. * @param {Object} json
  52. * @returns {Array}
  53. */
  54. export function param(json) {
  55. if (!json) return ''
  56. return cleanArray(
  57. Object.keys(json).map(key => {
  58. if (json[key] === undefined) return ''
  59. return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
  60. })
  61. ).join('&')
  62. }
  63. /**
  64. * 将url参数提取出来
  65. * @param {string} url
  66. * @returns {Object}
  67. */
  68. export function param2Obj(url) {
  69. const search = url.split('?')[1]
  70. if (!search) {
  71. return {}
  72. }
  73. return JSON.parse(
  74. '{"' +
  75. decodeURIComponent(search)
  76. .replace(/"/g, '\\"')
  77. .replace(/&/g, '","')
  78. .replace(/=/g, '":"')
  79. .replace(/\+/g, ' ') +
  80. '"}'
  81. )
  82. }
  83. /**
  84. * @param {string} val
  85. * @returns {string}
  86. */
  87. export function html2Text(val) {
  88. const div = document.createElement('div')
  89. div.innerHTML = val
  90. return div.textContent || div.innerText
  91. }
  92. /**
  93. * 对象去重合并
  94. * @param {Object} target
  95. * @param {(Object|Array)} source
  96. * @returns {Object}
  97. */
  98. export function objectMerge(target, source) {
  99. if (typeof target !== 'object') {
  100. target = {}
  101. }
  102. if (Array.isArray(source)) {
  103. return source.slice()
  104. }
  105. Object.keys(source).forEach(property => {
  106. const sourceProperty = source[property]
  107. if (typeof sourceProperty === 'object') {
  108. target[property] = objectMerge(target[property], sourceProperty)
  109. } else {
  110. target[property] = sourceProperty
  111. }
  112. })
  113. return target
  114. }
  115. /**
  116. * 移除和添加className
  117. * @param {HTMLElement} element
  118. * @param {string} className
  119. */
  120. export function toggleClass(element, className) {
  121. if (!element || !className) {
  122. return
  123. }
  124. let classString = element.className
  125. const nameIndex = classString.indexOf(className)
  126. if (nameIndex === -1) {
  127. classString += ' ' + className
  128. } else {
  129. classString =
  130. classString.substr(0, nameIndex) +
  131. classString.substr(nameIndex + className.length)
  132. }
  133. element.className = classString
  134. }
  135. /**
  136. * @param {string} type
  137. * @returns {Date}
  138. */
  139. export function getTime(type) {
  140. if (type === 'start') {
  141. return new Date().getTime() - 3600 * 1000 * 24 * 90
  142. } else {
  143. return new Date(new Date().toDateString())
  144. }
  145. }
  146. /**
  147. * 防抖
  148. * @param {Function} func
  149. * @param {number} wait
  150. * @param {boolean} immediate
  151. * @return {*}
  152. */
  153. export function debounce(func, wait, immediate) {
  154. let timeout, args, context, timestamp, result
  155. const later = function() {
  156. // 据上一次触发时间间隔
  157. const last = +new Date() - timestamp
  158. // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
  159. if (last < wait && last > 0) {
  160. timeout = setTimeout(later, wait - last)
  161. } else {
  162. timeout = null
  163. // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
  164. if (!immediate) {
  165. result = func.apply(context, args)
  166. if (!timeout) context = args = null
  167. }
  168. }
  169. }
  170. return function(...args) {
  171. context = this
  172. timestamp = +new Date()
  173. const callNow = immediate && !timeout
  174. // 如果延时不存在,重新设定延时
  175. if (!timeout) timeout = setTimeout(later, wait)
  176. if (callNow) {
  177. result = func.apply(context, args)
  178. context = args = null
  179. }
  180. return result
  181. }
  182. }
  183. /**
  184. * This is just a simple version of deep copy
  185. * Has a lot of edge cases bug
  186. * If you want to use a perfect deep copy, use lodash's _.cloneDeep
  187. * 深拷贝
  188. * @param {Object} source
  189. * @returns {Object}
  190. */
  191. export function deepClone(source) {
  192. if (!source && typeof source !== 'object') {
  193. throw new Error('error arguments', 'deepClone')
  194. }
  195. const targetObj = source.constructor === Array ? [] : {}
  196. Object.keys(source).forEach(keys => {
  197. if (source[keys] && typeof source[keys] === 'object') {
  198. targetObj[keys] = deepClone(source[keys])
  199. } else {
  200. targetObj[keys] = source[keys]
  201. }
  202. })
  203. return targetObj
  204. }
  205. /**
  206. * 去重
  207. * @param {Array} arr
  208. * @returns {Array}
  209. */
  210. export function uniqueArr(arr) {
  211. return Array.from(new Set(arr))
  212. }
  213. /**
  214. * 创建唯一随机数
  215. * @returns {string}
  216. */
  217. export function createUniqueString() {
  218. const timestamp = +new Date() + ''
  219. const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  220. return (+(randomNum + timestamp)).toString(32)
  221. }
  222. /**
  223. * Check if an element has a class
  224. * 判断是否含有该className
  225. * @param {HTMLElement} elm
  226. * @param {string} cls
  227. * @returns {boolean}
  228. */
  229. export function hasClass(ele, cls) {
  230. return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
  231. }
  232. /**
  233. * Add class to element
  234. * 添加className
  235. * @param {HTMLElement} elm
  236. * @param {string} cls
  237. */
  238. export function addClass(ele, cls) {
  239. if (!hasClass(ele, cls)) ele.className += ' ' + cls
  240. }
  241. /**
  242. * Remove class from element
  243. * 移除classNmae
  244. * @param {HTMLElement} elm
  245. * @param {string} cls
  246. */
  247. export function removeClass(ele, cls) {
  248. if (hasClass(ele, cls)) {
  249. const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
  250. ele.className = ele.className.replace(reg, ' ')
  251. }
  252. }
  253. /**
  254. * 根据树子节点ID查找所有父节点ID
  255. * @param {array} dataSource 树形结构数据源
  256. * @param {number} nodeId 子节点ID
  257. * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序
  258. */
  259. export function findParentIds(dataSource, nodeId) {
  260. const parentIds = []; // 用于存储所有父节点ID的数组
  261. // 定义一个递归函数,用于遍历整棵树并查找子节点的所有父节点
  262. function traverse(node, nodeId) {
  263. if (node.id === nodeId) { // 如果当前节点的ID等于子节点的ID,则表示已经找到了子节点,可以开始向上查找父节点
  264. return true; // 返回true表示已经找到了子节点
  265. }
  266. if (node.children) { // 如果当前节点有子节点,则继续遍历子节点
  267. for (const childNode of node.children) {
  268. if (traverse(childNode, nodeId)) { // 如果在子节点中找到了子节点的父节点,则将当前节点的ID添加到父节点ID数组中,并返回true表示已经找到了子节点
  269. parentIds.unshift(node.id);
  270. return true;
  271. }
  272. }
  273. }
  274. return false; // 如果当前节点不是子节点的父节点,则返回false
  275. }
  276. // 从根节点开始遍历整棵树,并调用递归函数查找子节点的所有父节点
  277. for (const node of dataSource) {
  278. if (traverse(node, nodeId)) { // 如果在当前节点的子树中找到了子节点的父节点,则直接退出循环
  279. break;
  280. }
  281. }
  282. parentIds.push(nodeId);
  283. return parentIds; // 返回所有父节点ID的数组
  284. }
  285. /**
  286. * 获取所有子集
  287. * @param {array} dataSource 树形结构数据源
  288. * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序
  289. */
  290. export function steamroller(dataSource) {
  291. let newArr = []
  292. let flat = function(item) {
  293. for (var i = 0; i < item.length; i++) {
  294. if (Array.isArray(item[i].children)) {
  295. flat(item[i].children)
  296. } else {
  297. newArr.push(item[i])
  298. }
  299. }
  300. }
  301. flat(dataSource);
  302. return newArr
  303. }
  304. /**
  305. * 根据树子节点查找所有父节点
  306. * @param {array} dataSource 树形结构数据源
  307. * @param {number} nodeId 子节点ID
  308. * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序
  309. */
  310. export function findParent(dataSource, node) {
  311. const parent = []; // 用于存储所有父节点ID的数组
  312. // 定义一个递归函数,用于遍历整棵树并查找子节点的所有父节点
  313. function traverse(child, node) {
  314. if (child.id === node.id) { // 如果当前节点的ID等于子节点的ID,则表示已经找到了子节点,可以开始向上查找父节点
  315. return true; // 返回true表示已经找到了子节点
  316. }
  317. if (child.children) { // 如果当前节点有子节点,则继续遍历子节点
  318. for (const childNode of child.children) {
  319. if (traverse(childNode, node)) { // 如果在子节点中找到了子节点的父节点,则将当前节点的ID添加到父节点ID数组中,并返回true表示已经找到了子节点
  320. parent.unshift(child);
  321. return true;
  322. }
  323. }
  324. }
  325. return false; // 如果当前节点不是子节点的父节点,则返回false
  326. }
  327. // 从根节点开始遍历整棵树,并调用递归函数查找子节点的所有父节点
  328. for (const child of dataSource) {
  329. if (traverse(child, node)) { // 如果在当前节点的子树中找到了子节点的父节点,则直接退出循环
  330. break;
  331. }
  332. }
  333. parent.push(node);
  334. return parent; // 返回所有父节点ID的数组
  335. }
  336. /**
  337. * 返回项目单位工程房间的层级关系
  338. * @param {array} data 树形结构数据源
  339. * @returns {array}
  340. */
  341. export function roomList(data) {
  342. let newArr = JSON.parse(JSON.stringify(data));
  343. let index = 1;
  344. newArr = newArr.map(item => {
  345. item['projectItemId'] = item['id'];
  346. item['id'] = index;
  347. item['projectItem'] = item;
  348. item['optionName'] = item['name'];
  349. index++;
  350. item['children'] = item.projectItemTargetList.map(target => {
  351. target['projectItemTargetId'] = target['id'];
  352. target['id'] = index;
  353. target['projectItem'] = item;
  354. target['optionName'] = target['name'];
  355. index++;
  356. target['children'] = target.projectItemTargetRoomList.map(room => {
  357. room['roomId'] = room['id'];
  358. room['id'] = index;
  359. room['projectItem'] = item;
  360. room['projectItemTarget'] = target;
  361. room['optionName'] = room['roomNumber'];
  362. index++;
  363. return room;
  364. })
  365. return target
  366. })
  367. return item;
  368. })
  369. return newArr;
  370. }
  371. /**
  372. * 返回项目单位工程房间选择的层级关系
  373. * @param {array} data 树形结构数据源
  374. * @returns {array}
  375. */
  376. export function roomCheckedList(data, roomIds) {
  377. let newArr = JSON.parse(JSON.stringify(data));
  378. let index = 1;
  379. newArr = newArr.map(item => {
  380. item['projectItemId'] = item['id'];
  381. item['id'] = index;
  382. item['projectItem'] = item;
  383. item['optionName'] = item['name'];
  384. index++;
  385. item['children'] = item.projectItemTargetList.map(target => {
  386. target['projectItemTargetId'] = target['id'];
  387. target['id'] = index;
  388. target['projectItem'] = item;
  389. target['optionName'] = target['name'];
  390. index++;
  391. target['children'] = target.projectItemTargetRoomList.map(room => {
  392. room['roomId'] = room['id'];
  393. room['id'] = index;
  394. room['projectItem'] = item;
  395. room['projectItemTarget'] = target;
  396. room['optionName'] = room['roomNumber'];
  397. index++;
  398. return room;
  399. }).filter(room => roomIds.filter(node => node == room.roomId).length > 0);
  400. return target
  401. }).filter(target => target.children.length > 0);
  402. return item;
  403. }).filter(target => target.children.length > 0);
  404. return newArr;
  405. }
  406. /**
  407. * 返回sheet去除data里null数据
  408. * @param {array} data 结构数据源
  409. * @returns {array}
  410. */
  411. export function sheetDataRemoveNull(data) {
  412. let newArr = JSON.parse(JSON.stringify(data));
  413. for (let i = 0; i < newArr.length; i++) {
  414. for (let j = 0; j < newArr[i].data.length; j++) {
  415. newArr[i].data[j] = newArr[i].data[j].filter(node => node);
  416. }
  417. }
  418. return newArr;
  419. }
  420. /**
  421. * 返回sheet添加data里null数据
  422. * @param {array} data 结构数据源
  423. * @returns {array}
  424. */
  425. export function sheetDataAddNull(data) {
  426. let newArr = JSON.parse(JSON.stringify(data));
  427. for (let i = 0; i < newArr.length; i++) {
  428. for (let j = 0; j < newArr[i].data.length; j++) {
  429. for (let k = 0; k < 64; k++) {
  430. if (!newArr[i].data[j][k]) newArr[i].data[j].push(null)
  431. }
  432. }
  433. }
  434. return newArr;
  435. }
  436. /*
  437. * 整理数据
  438. */
  439. export function constData(documentElement) {
  440. let obj = {};
  441. for (var i = 0; i < documentElement.length; i++) {
  442. let elem = documentElement[i];
  443. let id = elem.getAttribute('id'),
  444. name = elem.getAttribute('updatetype');
  445. if (!name || name == 'null' || elem.innerText == '申请盖章' || elem.innerText == '确认签名' || elem.innerText ==
  446. '使用注册章')
  447. continue;
  448. if (!obj[name]) obj[name] = {};
  449. if (elem.getElementsByTagName("img").length > 0 && name == 'seal') {
  450. if (!!elem.getElementsByTagName("img")[0].id) obj[name][id] = elem.getElementsByTagName("img")[0].id;
  451. continue;
  452. }
  453. if (elem.getElementsByTagName("img").length > 0 && name == 'sealperson') {
  454. if (!!elem.getElementsByTagName("img")[0].id) obj[name][id] = elem.getElementsByTagName("img")[0].id;
  455. continue;
  456. }
  457. if (elem.getElementsByTagName("img").length > 0 && name == 'sign') {
  458. if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName(
  459. "img")[0].getAttribute('src');
  460. continue;
  461. }
  462. if (elem.getElementsByTagName("img").length > 0 && name == 'signQR') {
  463. if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName(
  464. "img")[0].getAttribute('src');
  465. continue;
  466. }
  467. if (elem.getElementsByTagName("img").length > 0 && name == 'copyImage') {
  468. if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName(
  469. "img")[0].getAttribute('src');
  470. continue;
  471. }
  472. if (elem.innerText != '申请盖章' && elem.innerText != '确认签名' && elem.innerText != '使用注册章' && elem.innerText !=
  473. '上传图片') obj[name][id] = elem.innerText == null ? '' : elem.innerText;
  474. }
  475. return obj;
  476. }
  477. /*
  478. * 下载文件
  479. *
  480. */
  481. export function downloadFileDom(data, fileName) {
  482. let blob = new Blob([data], {
  483. type: 'application/octet-stream'
  484. }); // 转化为blob对象
  485. if (typeof window.navigator.msSaveBlob !== 'undefined') {
  486. window.navigator.msSaveBlob(blob, fileName);
  487. } else {
  488. var blobURL = window.URL.createObjectURL(blob); // 将blob对象转为一个URL
  489. var tempLink = document.createElement('a'); // 创建一个a标签
  490. tempLink.style.display = 'none';
  491. tempLink.href = blobURL;
  492. tempLink.setAttribute('download', fileName); // 给a标签添加下载属性
  493. if (typeof tempLink.download === 'undefined') {
  494. tempLink.setAttribute('target', '_blank');
  495. }
  496. document.body.appendChild(tempLink); // 将a标签添加到body当中
  497. tempLink.click(); // 启动下载
  498. document.body.removeChild(tempLink); // 下载完毕删除a标签
  499. window.URL.revokeObjectURL(blobURL);
  500. }
  501. }