import { validatenull } from './validate'; import sha256 from 'crypto-js/sha256'; import Base64 from 'crypto-js/enc-base64'; import store from '@/store/index'; //表单序列化 export const serialize = data => { let list = []; Object.keys(data).forEach(ele => { list.push(`${ele}=${data[ele]}`); }); return list.join('&'); }; export const getObjType = obj => { var toString = Object.prototype.toString; var map = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regExp', '[object Undefined]': 'undefined', '[object Null]': 'null', '[object Object]': 'object', }; if (obj instanceof Element) { return 'element'; } return map[toString.call(obj)]; }; /** * 对象深拷贝 */ export const deepClone = data => { var type = getObjType(data); var obj; if (type === 'array') { obj = []; } else if (type === 'object') { obj = {}; } else { //不再具有下一层次 return data; } if (type === 'array') { for (var i = 0, len = data.length; i < len; i++) { obj.push(deepClone(data[i])); } } else if (type === 'object') { for (var key in data) { obj[key] = deepClone(data[key]); } } return obj; }; /** * 设置灰度模式 */ export const toggleGrayMode = status => { if (status) { document.body.className = document.body.className + ' grayMode'; } else { document.body.className = document.body.className.replace(' grayMode', ''); } }; /** * 设置主题 */ export const setTheme = name => { document.body.className = name; }; /** * 加密处理 */ export const encryption = params => { let { data = {}, type, param, key } = params; let result = JSON.parse(JSON.stringify(data)); if (type == 'Base64') { param.forEach(ele => { result[ele] = Base64.stringify(result[ele]); }); } else if (type == 'Aes') { param.forEach(ele => { result[ele] = sha256(result[ele], key); }); } return result; }; /** * 浏览器判断是否全屏 */ export const fullscreenToggel = () => { if (fullscreenEnable()) { exitFullScreen(); } else { reqFullScreen(); } }; /** * esc监听全屏 */ export const listenfullscreen = callback => { function listen() { callback(); } document.addEventListener('fullscreenchange', function () { listen(); }); document.addEventListener('mozfullscreenchange', function () { listen(); }); document.addEventListener('webkitfullscreenchange', function () { listen(); }); document.addEventListener('msfullscreenchange', function () { listen(); }); }; /** * 浏览器判断是否全屏 */ export const fullscreenEnable = () => { var isFullscreen = document.isFullScreen || document.mozIsFullScreen || document.webkitIsFullScreen; return isFullscreen; }; /** * 浏览器全屏 */ export const reqFullScreen = () => { if (document.documentElement.requestFullScreen) { document.documentElement.requestFullScreen(); } else if (document.documentElement.webkitRequestFullScreen) { document.documentElement.webkitRequestFullScreen(); } else if (document.documentElement.mozRequestFullScreen) { document.documentElement.mozRequestFullScreen(); } }; /** * 浏览器退出全屏 */ export const exitFullScreen = () => { if (document.documentElement.requestFullScreen) { document.exitFullScreen(); } else if (document.documentElement.webkitRequestFullScreen) { document.webkitCancelFullScreen(); } else if (document.documentElement.mozRequestFullScreen) { document.mozCancelFullScreen(); } }; /** * 递归寻找子类的父类 */ export const findParent = (menu, id) => { for (let i = 0; i < menu.length; i++) { if (menu[i].children.length != 0) { for (let j = 0; j < menu[i].children.length; j++) { if (menu[i].children[j].id == id) { return menu[i]; } else { if (menu[i].children[j].children.length != 0) { return findParent(menu[i].children[j].children, id); } } } } } }; /** * 判断2个对象属性和值是否相等 */ /** * 动态插入css */ export const loadStyle = url => { const link = document.createElement('link'); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = url; const head = document.getElementsByTagName('head')[0]; head.appendChild(link); }; /** * 判断路由是否相等 */ export const diff = (obj1, obj2) => { delete obj1.close; var o1 = obj1 instanceof Object; var o2 = obj2 instanceof Object; if (!o1 || !o2) { /* 判断不是对象 */ return obj1 === obj2; } if (Object.keys(obj1).length !== Object.keys(obj2).length) { return false; //Object.keys() 返回一个由对象的自身可枚举属性(key值)组成的数组,例如:数组返回下表:let arr = ["a", "b", "c"];console.log(Object.keys(arr))->0,1,2; } for (var attr in obj1) { var t1 = obj1[attr] instanceof Object; var t2 = obj2[attr] instanceof Object; if (t1 && t2) { return diff(obj1[attr], obj2[attr]); } else if (obj1[attr] !== obj2[attr]) { return false; } } return true; }; /** * 根据字典的value显示label */ export const findByvalue = (dic, value) => { let result = ''; if (validatenull(dic)) return value; if (typeof value == 'string' || typeof value == 'number' || typeof value == 'boolean') { let index = 0; index = findArray(dic, value); if (index != -1) { result = dic[index].label; } else { result = value; } } else if (value instanceof Array) { result = []; let index = 0; value.forEach(ele => { index = findArray(dic, ele); if (index != -1) { result.push(dic[index].label); } else { result.push(value); } }); result = result.toString(); } return result; }; /** * 根据字典的value查找对应的index */ export const findArray = (dic, value) => { for (let i = 0; i < dic.length; i++) { if (dic[i].value == value) { return i; } } return -1; }; /** * 生成随机len位数字 */ export const randomLenNum = (len, date) => { let random = ''; random = Math.ceil(Math.random() * 100000000000000) .toString() .substr(0, len ? len : 4); if (date) random = random + Date.now(); return random; }; /** * 打开小窗口 */ export const openWindow = (url, title, w, h) => { // Fixes dual-screen position Most browsers Firefox const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left; const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top; const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width; const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height; const left = width / 2 - w / 2 + dualScreenLeft; const top = height / 2 - h / 2 + dualScreenTop; const newWindow = window.open( url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left ); // Puts focus on the newWindow if (window.focus) { newWindow.focus(); } }; export const getScreen = isCollapse => { if (document.body.clientWidth <= 768) { return !isCollapse; } else { return isCollapse; } }; export const getHtmls = (arrs, htmldemo) => { let html = ''; arrs.map(item => { let strhtml = JSON.parse(JSON.stringify(htmldemo)); for (let key in item) { let str = '\\$\\{' + key + '\\}'; let reg = new RegExp(str, 'g'); strhtml = strhtml.replace(reg, item[key]); } html += strhtml; }); return html; }; /** * 获取顶部地址栏地址 */ export const getTopUrl = () => { return window.location.href.split('/#/')[0]; }; /** 移除标题栏指定地址 * @param {string} value 要移除的地址 */ export function AddressClosed(url) { console.log(url, store); const index = store.getters.tagList.findIndex(item => item.path == url); if (index != -1) { store.getters.tagList.splice(index, 1); } } /** * 获取url参数 * @param name 参数名 */ export const getQueryString = name => { let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i'); let r = window.location.search.substr(1).match(reg); if (r != null) return unescape(decodeURI(r[2])); return null; }; /** * 下载文件 * @param {String} path - 文件地址 * @param {String} name - 文件名,eg: test.png */ export const downloadFileBlob = (path, name) => { const xhr = new XMLHttpRequest(); xhr.open('get', path); xhr.responseType = 'blob'; xhr.send(); xhr.onload = function () { if (this.status === 200 || this.status === 304) { // 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob if ('msSaveOrOpenBlob' in navigator) { navigator.msSaveOrOpenBlob(this.response, name); return; } const url = URL.createObjectURL(this.response); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; }; /** * 下载文件 * @param {String} path - 文件地址 * @param {String} name - 文件名,eg: test.png */ export const downloadFileBase64 = (path, name) => { const xhr = new XMLHttpRequest(); xhr.open('get', path); xhr.responseType = 'blob'; xhr.send(); xhr.onload = function () { if (this.status === 200 || this.status === 304) { const fileReader = new FileReader(); fileReader.readAsDataURL(this.response); fileReader.onload = function () { const a = document.createElement('a'); a.style.display = 'none'; a.href = this.result; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); }; } }; }; /** * 下载excel * @param {blob} fileArrayBuffer 文件流 * @param {String} filename 文件名称 */ export const downloadXls = (fileArrayBuffer, filename) => { let data = new Blob([fileArrayBuffer], { type: 'application/vnd.ms-excel,charset=utf-8' }); if (typeof window.chrome !== 'undefined') { // Chrome var link = document.createElement('a'); link.href = window.URL.createObjectURL(data); link.download = filename; link.click(); } else if (typeof window.navigator.msSaveBlob !== 'undefined') { // IE var blob = new Blob([data], { type: 'application/force-download' }); window.navigator.msSaveBlob(blob, filename); } else { // Firefox var file = new File([data], filename, { type: 'application/force-download' }); window.open(URL.createObjectURL(file)); } }; /** 获取视口高度 */ export const getWinHeight = () => { // 使用window.innerHeight作为首选获取窗口高度的方法 if (typeof window.innerHeight === 'number') { return window.innerHeight; } // 如果window.innerHeight不可用,尝试使用标准模式下的documentElement属性 if (document.documentElement && document.documentElement.clientHeight) { return document.documentElement.clientHeight; } // 最后作为备选方案,尝试使用怪异模式下的document.body属性 if (document.body && document.body.clientHeight) { return document.body.clientHeight; } // 如果以上方法均不可行,则返回0 return 0; }; /** * 设置元素节点高度 * @param {node} node 元素 type: element || array * @param {string} height 高度 (非必填) type: string */ export const setNodeHeight = (_node, _height = '') => { console.log('getWinHeight() :>> ', getWinHeight()); const _defaultHeight = getWinHeight(); // 判断是否传入的是数组 const _type = Object.prototype.toString.call(_node); console.log('_type :>> ', _type); // 传入数组时 if (_type === '[object NodeList]') { console.log('333 :>> ', 333); _node.forEach(val => { const _itemType = Object.prototype.toString.call(val); if (_itemType === '[object HTMLDivElement]') { val.style.transition = 'all 0.3s ease-out'; if (_height) val.style.height = _height; else { const timer = setTimeout(() => { val.style.height = _defaultHeight - val.getBoundingClientRect().top - 65 + 'px'; clearTimeout(timer); }, 10); } } }); } // 传入单一节点时 else if (_type === '[object HTMLDivElement]') { _node.style.transition = 'all 0.3s ease-out'; if (_height) _node.style.height = _height; else { const timer = setTimeout(() => { _node.style.height = _defaultHeight - _node.getBoundingClientRect().top - 65 + 'px'; clearTimeout(timer); }, 10); } console.log('_node :>> ', _defaultHeight - _node.getBoundingClientRect().top - 65 + 'px'); } }; /** * 下拉框搜索公共函数processRowProperty(index, row, details); * @param {string} index index参数 * @param {object} row row (表头参数) * @param {object} details details (搜索参数) */ // const updateDetailQuery = (index, propName, obj) => { // 更新或删除查询参数 if (index) { obj[propName] = index; } else { delete obj[propName]; } }; export const processRowProperty = (index, row, details) => { const nameRegex = /(\w+)NameS$/; // 捕获以'NameS'结尾的属性名 const match = row.prop.match(nameRegex); // 如果属性以'NameS'结尾,则更新相应的查询参数 if (match) { const basePropName = match[1]; // 获取不包含'Name'的属性名 updateDetailQuery(index, basePropName, details.query); } else { updateDetailQuery(index, row.prop, details.query); } // 如果提供的index为假值,从query中删除原始属性 if (!index) { delete details.query[row.prop]; } }; /** * 数字运算(主要用于小数点精度问题) * [see](https://juejin.im/post/6844904066418491406#heading-12) * @param {number} a 前面的值 * @param {"+"|"-"|"*"|"/"} type 计算方式 * @param {number} b 后面的值 * @example * ```js * // 可链式调用 * const res = computeNumber(1.3, "-", 1.2).next("+", 1.5).next("*", 2.3).next("/", 0.2).result; * console.log(res); * ``` */ export function computeNumber(a, type, b) { /** * 获取数字小数点的长度 * @param {number} n 数字 */ function getDecimalLength(n) { const decimal = n.toString().split('.')[1]; return decimal ? decimal.length : 0; } /** * 修正小数点 * @description 防止出现 `33.33333*100000 = 3333332.9999999995` && `33.33*10 = 333.29999999999995` 这类情况做的处理 * @param {number} n */ const amend = (n, precision = 15) => parseFloat(Number(n).toPrecision(precision)); const power = Math.pow(10, Math.max(getDecimalLength(a), getDecimalLength(b))); let result = 0; a = amend(a * power); b = amend(b * power); switch (type) { case '+': result = (a + b) / power; break; case '-': result = (a - b) / power; break; case '*': result = (a * b) / (power * power); break; case '/': result = a / b; break; } result = amend(result); return { /** 计算结果 */ result, /** * 继续计算 * @param {"+"|"-"|"*"|"/"} nextType 继续计算方式 * @param {number} nextValue 继续计算的值 */ next(nextType, nextValue) { return computeNumber(result, nextType, nextValue); }, }; } /** 判断是否为数字 * @param {any} value 传入值, 判断该值是否为数字 */ export const isNumer = value => { // if (typeof value !== 'number' || typeof value !== 'string') return false; const _value = Number(value); if (_value !== _value) return false; return true; }; /** 防抖函数 */ export function debounce(func, delay) { let timer; return (function () { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function () { // func.apply(context, args); func(); clearTimeout(timer); }, delay); })(); } /** 去除零宽字符 */ export const removeZeroWidth = str => { return str.replace(/[\u200B-\u200D\uFEFF]/g, ''); };