import { cloneDeep, throttle, debounce } from 'lodash' /* eslint-disable */ const Utils = {} /** 参数说明: * 根据长度截取先使用字符串,超长部分追加… * str 对象字符串 * len 目标字节长度 * 返回值: 处理结果字符串 */ Utils.cutString = (str, len) => { if (str.length * 2 <= len) { return str } let strlen = 0 let s = '' for (let i = 0; i < str.length; i++) { // eslint-disable-line s += str.charAt(i) if (str.charCodeAt(i) > 128) { strlen += 2 if (strlen >= len) { return `${s.substring(0, s.length - 1)}...` } } else { strlen += 1 if (strlen >= len) { return `${s.substring(0, s.length - 2)}...` } } } return s } /** * 简单数组的交集 * @param {Array} a * @param {Array} b */ Utils.getIntersect = (a, b) => { if (a.constructor === Array && b.constructor === Array) { const set1 = new Set(a) const set2 = new Set(b) return Array.from(new Set([...set1].filter(x => set2.has(x)))) } return null } /** * 防抖函数 * @param {*} func 函数体 * @param {*} wait 延时 */ Utils.debounce = (func, wait = 50) => debounce(func, wait) /** * 节流函数 * @param {*} func 函数体 * @param {*} wait 延时 */ Utils.throttle = (func, wait = 50) => throttle(func, wait) /** * 返回 n 位的随机字符串 * @param {Number} n */ Utils.getRandomStr = (n = 6) => { let str = '' const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' for (let i = 0; i < n; i += 1) { str += chars.charAt(Math.floor(Math.random() * 62)) } return str } function getTypeOf(obj) { const { toString } = Object.prototype const 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', '[object Symbol]': 'symbol', } return map[toString.call(obj)] } function groupByOrder(source) { // 有order的放这里 const map = {} // 没有order放这里 const noOrderList = [] source.forEach(s => { const { order } = s if (typeof order !== 'number') { noOrderList.push(s) return } const list = map[order] if (list) { list.push(s) } else { map[order] = [s] } }) return { orderMap: map, noOrderList, } } /** * 根据数组的 order 字段排序 * @param {Array} source */ Utils.sortByOrder = (source = []) => { if (!Array.isArray(source)) { const message = 'sortByOrder 传入参数不符合要求, 应为数组' console.error(message) throw new Error(message) } if (!source.length) { return source } // 1.根据order对数据进行分组 const { orderMap, noOrderList } = groupByOrder(source) // 2.获取已存在的order const orders = Object.keys(orderMap).map(o => Number(o)) // 对order进行排序 orders.sort((a, b) => a - b) // 小于0的order const ltZeroOrders = orders.filter(o => o < 0) // 大于等于0的order const gteZeroOrders = orders.filter(o => o >= 0) const finallyArr = [] const gteZeroItemList = gteZeroOrders.map(o => orderMap[o]).flat() finallyArr.push(...gteZeroItemList) finallyArr.push(...noOrderList) // 如果没有小于0的order,则直接拼接 if (!ltZeroOrders.length) { return finallyArr } // 将小于0的order的item插入到数组中 ltZeroOrders.reverse().forEach(o => { let index = finallyArr.length + o + 1 if (index < 0) { index = 0 } const arr = orderMap[o] finallyArr.splice(index, 0, ...arr) }) return finallyArr } /** * 深度遍历,深拷贝 * @param {*} data */ Utils.deepClone = data => cloneDeep(data) /** * 中划线转驼峰 */ Utils.came = str => { return `${str}`.replace(/-\D/g, match => match.charAt(1).toUpperCase()) } /** * 判断权限 */ Utils.hasPermission = (permissions, route, user) => { // eslint-disable-line if (user?.admin) { return true } if (route.permission) { return permissions.some(permission => route.permission.indexOf(permission) > -1) } return true } let cached /** * 获取窗口滚动条大小, From: https://github.com/react-component/util/blob/master/src/getScrollBarSize.js * @param {boolean} fresh 强制重新计算 * @returns {number} */ export function getScrollBarSize(fresh) { if (fresh || cached === undefined) { const inner = document.createElement('div') inner.style.width = '100%' inner.style.height = '200px' const outer = document.createElement('div') const outerStyle = outer.style outerStyle.position = 'absolute' outerStyle.top = 0 outerStyle.left = 0 outerStyle.pointerEvents = 'none' outerStyle.visibility = 'hidden' outerStyle.width = '200px' outerStyle.height = '150px' outerStyle.overflow = 'hidden' outer.appendChild(inner) document.body.appendChild(outer) const widthContained = inner.offsetWidth outer.style.overflow = 'scroll' let widthScroll = inner.offsetWidth if (widthContained === widthScroll) { widthScroll = outer.clientWidth } document.body.removeChild(outer) cached = widthContained - widthScroll } return cached } export default Utils