/** * 解析参数 * @param {string} url * @returns {Object} */ export function getQueryObject(url) { url = url == null ? window.location.href : url const search = url.substring(url.lastIndexOf('?') + 1) const obj = {} const reg = /([^?&=]+)=([^?&=]*)/g search.replace(reg, (rs, $1, $2) => { const name = decodeURIComponent($1) let val = decodeURIComponent($2) val = String(val) obj[name] = val return rs }) return obj } /** * 返回字符串的大小byte * @param {string} input value * @returns {number} output value */ export function byteLength(str) { // returns the byte length of an utf8 string let s = str.length for (var i = str.length - 1; i >= 0; i--) { const code = str.charCodeAt(i) if (code > 0x7f && code <= 0x7ff) s++ else if (code > 0x7ff && code <= 0xffff) s += 2 if (code >= 0xDC00 && code <= 0xDFFF) i-- } return s } /** * @param {Array} actual * @returns {Array} */ export function cleanArray(actual) { const newArray = [] for (let i = 0; i < actual.length; i++) { if (actual[i]) { newArray.push(actual[i]) } } return newArray } /** * 将json换成get传参 * @param {Object} json * @returns {Array} */ export function param(json) { if (!json) return '' return cleanArray( Object.keys(json).map(key => { if (json[key] === undefined) return '' return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) }) ).join('&') } /** * 将url参数提取出来 * @param {string} url * @returns {Object} */ export function param2Obj(url) { const search = url.split('?')[1] if (!search) { return {} } return JSON.parse( '{"' + decodeURIComponent(search) .replace(/"/g, '\\"') .replace(/&/g, '","') .replace(/=/g, '":"') .replace(/\+/g, ' ') + '"}' ) } /** * @param {string} val * @returns {string} */ export function html2Text(val) { const div = document.createElement('div') div.innerHTML = val return div.textContent || div.innerText } /** * 对象去重合并 * @param {Object} target * @param {(Object|Array)} source * @returns {Object} */ export function objectMerge(target, source) { if (typeof target !== 'object') { target = {} } if (Array.isArray(source)) { return source.slice() } Object.keys(source).forEach(property => { const sourceProperty = source[property] if (typeof sourceProperty === 'object') { target[property] = objectMerge(target[property], sourceProperty) } else { target[property] = sourceProperty } }) return target } /** * 移除和添加className * @param {HTMLElement} element * @param {string} className */ export function toggleClass(element, className) { if (!element || !className) { return } let classString = element.className const nameIndex = classString.indexOf(className) if (nameIndex === -1) { classString += ' ' + className } else { classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length) } element.className = classString } /** * @param {string} type * @returns {Date} */ export function getTime(type) { if (type === 'start') { return new Date().getTime() - 3600 * 1000 * 24 * 90 } else { return new Date(new Date().toDateString()) } } /** * 防抖 * @param {Function} func * @param {number} wait * @param {boolean} immediate * @return {*} */ export function debounce(func, wait, immediate) { let timeout, args, context, timestamp, result const later = function() { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function(...args) { context = this timestamp = +new Date() const callNow = immediate && !timeout // 如果延时不存在,重新设定延时 if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } } /** * This is just a simple version of deep copy * Has a lot of edge cases bug * If you want to use a perfect deep copy, use lodash's _.cloneDeep * 深拷贝 * @param {Object} source * @returns {Object} */ export function deepClone(source) { if (!source && typeof source !== 'object') { throw new Error('error arguments', 'deepClone') } const targetObj = source.constructor === Array ? [] : {} Object.keys(source).forEach(keys => { if (source[keys] && typeof source[keys] === 'object') { targetObj[keys] = deepClone(source[keys]) } else { targetObj[keys] = source[keys] } }) return targetObj } /** * 去重 * @param {Array} arr * @returns {Array} */ export function uniqueArr(arr) { return Array.from(new Set(arr)) } /** * 创建唯一随机数 * @returns {string} */ export function createUniqueString() { const timestamp = +new Date() + '' const randomNum = parseInt((1 + Math.random()) * 65536) + '' return (+(randomNum + timestamp)).toString(32) } /** * Check if an element has a class * 判断是否含有该className * @param {HTMLElement} elm * @param {string} cls * @returns {boolean} */ export function hasClass(ele, cls) { return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) } /** * Add class to element * 添加className * @param {HTMLElement} elm * @param {string} cls */ export function addClass(ele, cls) { if (!hasClass(ele, cls)) ele.className += ' ' + cls } /** * Remove class from element * 移除classNmae * @param {HTMLElement} elm * @param {string} cls */ export function removeClass(ele, cls) { if (hasClass(ele, cls)) { const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') ele.className = ele.className.replace(reg, ' ') } } /** * 根据树子节点ID查找所有父节点ID * @param {array} dataSource 树形结构数据源 * @param {number} nodeId 子节点ID * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序 */ export function findParentIds(dataSource, nodeId) { const parentIds = []; // 用于存储所有父节点ID的数组 // 定义一个递归函数,用于遍历整棵树并查找子节点的所有父节点 function traverse(node, nodeId) { if (node.id === nodeId) { // 如果当前节点的ID等于子节点的ID,则表示已经找到了子节点,可以开始向上查找父节点 return true; // 返回true表示已经找到了子节点 } if (node.children) { // 如果当前节点有子节点,则继续遍历子节点 for (const childNode of node.children) { if (traverse(childNode, nodeId)) { // 如果在子节点中找到了子节点的父节点,则将当前节点的ID添加到父节点ID数组中,并返回true表示已经找到了子节点 parentIds.unshift(node.id); return true; } } } return false; // 如果当前节点不是子节点的父节点,则返回false } // 从根节点开始遍历整棵树,并调用递归函数查找子节点的所有父节点 for (const node of dataSource) { if (traverse(node, nodeId)) { // 如果在当前节点的子树中找到了子节点的父节点,则直接退出循环 break; } } parentIds.push(nodeId); return parentIds; // 返回所有父节点ID的数组 } /** * 获取所有子集 * @param {array} dataSource 树形结构数据源 * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序 */ export function steamroller(dataSource) { let newArr = [] let flat = function(item) { for (var i = 0; i < item.length; i++) { if (Array.isArray(item[i].children)) { flat(item[i].children) } else { newArr.push(item[i]) } } } flat(dataSource); return newArr } /** * 根据树子节点查找所有父节点 * @param {array} dataSource 树形结构数据源 * @param {number} nodeId 子节点ID * @returns {array} 包含所有父节点ID的数组,按照从根节点到直接父节点的顺序排序 */ export function findParent(dataSource, node) { const parent = []; // 用于存储所有父节点ID的数组 // 定义一个递归函数,用于遍历整棵树并查找子节点的所有父节点 function traverse(child, node) { if (child.id === node.id) { // 如果当前节点的ID等于子节点的ID,则表示已经找到了子节点,可以开始向上查找父节点 return true; // 返回true表示已经找到了子节点 } if (child.children) { // 如果当前节点有子节点,则继续遍历子节点 for (const childNode of child.children) { if (traverse(childNode, node)) { // 如果在子节点中找到了子节点的父节点,则将当前节点的ID添加到父节点ID数组中,并返回true表示已经找到了子节点 parent.unshift(child); return true; } } } return false; // 如果当前节点不是子节点的父节点,则返回false } // 从根节点开始遍历整棵树,并调用递归函数查找子节点的所有父节点 for (const child of dataSource) { if (traverse(child, node)) { // 如果在当前节点的子树中找到了子节点的父节点,则直接退出循环 break; } } parent.push(node); return parent; // 返回所有父节点ID的数组 } /** * 返回项目单位工程房间的层级关系 * @param {array} data 树形结构数据源 * @returns {array} */ export function roomList(data) { let newArr = JSON.parse(JSON.stringify(data)); let index = 1; newArr = newArr.map(item => { item['projectItemId'] = item['id']; item['id'] = index; item['projectItem'] = item; item['optionName'] = item['name']; index++; item['children'] = item.projectItemTargetList.map(target => { target['projectItemTargetId'] = target['id']; target['id'] = index; target['projectItem'] = item; target['optionName'] = target['name']; index++; target['children'] = target.projectItemTargetRoomList.map(room => { room['roomId'] = room['id']; room['id'] = index; room['projectItem'] = item; room['projectItemTarget'] = target; room['optionName'] = room['roomNumber']; index++; return room; }) return target }) return item; }) return newArr; } /** * 返回项目单位工程房间选择的层级关系 * @param {array} data 树形结构数据源 * @returns {array} */ export function roomCheckedList(data, roomIds) { let newArr = JSON.parse(JSON.stringify(data)); let index = 1; newArr = newArr.map(item => { item['projectItemId'] = item['id']; item['id'] = index; item['projectItem'] = item; item['optionName'] = item['name']; index++; item['children'] = item.projectItemTargetList.map(target => { target['projectItemTargetId'] = target['id']; target['id'] = index; target['projectItem'] = item; target['optionName'] = target['name']; index++; target['children'] = target.projectItemTargetRoomList.map(room => { room['roomId'] = room['id']; room['id'] = index; room['projectItem'] = item; room['projectItemTarget'] = target; room['optionName'] = room['roomNumber']; index++; return room; }).filter(room => roomIds.filter(node => node == room.roomId).length > 0); return target }).filter(target => target.children.length > 0); return item; }).filter(target => target.children.length > 0); return newArr; } /** * 返回sheet去除data里null数据 * @param {array} data 结构数据源 * @returns {array} */ export function sheetDataRemoveNull(data) { let newArr = JSON.parse(JSON.stringify(data)); for (let i = 0; i < newArr.length; i++) { for (let j = 0; j < newArr[i].data.length; j++) { newArr[i].data[j] = newArr[i].data[j].filter(node => node); } } return newArr; } /** * 返回sheet添加data里null数据 * @param {array} data 结构数据源 * @returns {array} */ export function sheetDataAddNull(data) { let newArr = JSON.parse(JSON.stringify(data)); for (let i = 0; i < newArr.length; i++) { for (let j = 0; j < newArr[i].data.length; j++) { for (let k = 0; k < 64; k++) { if (!newArr[i].data[j][k]) newArr[i].data[j].push(null) } } } return newArr; } /* * 整理数据 */ export function constData(documentElement) { let obj = {}; for (var i = 0; i < documentElement.length; i++) { let elem = documentElement[i]; let id = elem.getAttribute('id'), name = elem.getAttribute('updatetype'); if (!name || name == 'null' || elem.innerText == '申请盖章' || elem.innerText == '确认签名' || elem.innerText == '使用注册章') continue; if (!obj[name]) obj[name] = {}; if (elem.getElementsByTagName("img").length > 0 && name == 'seal') { if (!!elem.getElementsByTagName("img")[0].id) obj[name][id] = elem.getElementsByTagName("img")[0].id; continue; } if (elem.getElementsByTagName("img").length > 0 && name == 'sealperson') { if (!!elem.getElementsByTagName("img")[0].id) obj[name][id] = elem.getElementsByTagName("img")[0].id; continue; } if (elem.getElementsByTagName("img").length > 0 && name == 'sign') { if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName( "img")[0].getAttribute('src'); continue; } if (elem.getElementsByTagName("img").length > 0 && name == 'signQR') { if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName( "img")[0].getAttribute('src'); continue; } if (elem.getElementsByTagName("img").length > 0 && name == 'copyImage') { if (!!elem.getElementsByTagName("img")[0].getAttribute('src')) obj[name][id] = elem.getElementsByTagName( "img")[0].getAttribute('src'); continue; } if (elem.innerText != '申请盖章' && elem.innerText != '确认签名' && elem.innerText != '使用注册章' && elem.innerText != '上传图片') obj[name][id] = elem.innerText == null ? '' : elem.innerText; } return obj; } /* * 下载文件 * */ export function downloadFileDom(data, fileName) { let blob = new Blob([data], { type: 'application/octet-stream' }); // 转化为blob对象 if (typeof window.navigator.msSaveBlob !== 'undefined') { window.navigator.msSaveBlob(blob, fileName); } else { var blobURL = window.URL.createObjectURL(blob); // 将blob对象转为一个URL var tempLink = document.createElement('a'); // 创建一个a标签 tempLink.style.display = 'none'; tempLink.href = blobURL; tempLink.setAttribute('download', fileName); // 给a标签添加下载属性 if (typeof tempLink.download === 'undefined') { tempLink.setAttribute('target', '_blank'); } document.body.appendChild(tempLink); // 将a标签添加到body当中 tempLink.click(); // 启动下载 document.body.removeChild(tempLink); // 下载完毕删除a标签 window.URL.revokeObjectURL(blobURL); } }