import { isObject } from '@vueuse/core' import { get } from '@/plugins/axios' import md5 from 'spark-md5' export const isEmpty = (val: unknown) => { return !(!!val ? typeof val === 'object' ? Array.isArray(val) ? !!val.length : !!Object.keys(val).length : true : false) } /** 转换为千分位 * showDecimal: 是否显示小数位 */ export const transformNumber = ( num: number | string | null | undefined, showDecimal = true, placeholder: string ): string => { const numStr = num + '' if (placeholder && (num === null || num === undefined || num === '')) { return placeholder } // 默认值为- if (num === null || num === undefined || num === '') { return '-' } if (['0', '0.00', '0.', '0.0'].includes(numStr)) { return showDecimal ? '0.00' : '0' } num = Number.parseFloat(num + '') const reg = /(\d)(?=(\d{3})+\.)/g // 避免出现-0.00的情况 const finalNum = Number.parseFloat(num.toFixed(2)) + 0 if (showDecimal) { return finalNum.toFixed(2).replace(reg, '$1,') } else { // 取整 return finalNum.toFixed(0) } } /** 根据字符串读取对象属性值,比如:obj['a.b.c'] */ export const getProp = function (obj: Object, value: string) { if (value.indexOf('.') === -1) return obj[value] || null const keys = value.split('.') let tmp = obj for (let i = 0; i < keys.length; i++) { const key = keys[i] if (isObject(tmp[key])) { tmp = tmp[key] } else { return tmp[key] } } return null } /** 将map转换为list */ export const mapToList = function (map: any): Array { const list = [] for (const [key, value] of Object.entries(map)) { if (key === 'toString') continue const name = map.toString(value) list.push({value, name, label: name}) } return list } /** 获取问号?参数 */ export const getQueryString = function (url: string, params: string): string { const res = new RegExp('(?:&|/?)' + params + '=([^&$]+)').exec(url) return res ? res[1] : '' } /** 获取url参数 */ export const getURLParam = function (key: string, href = window.location.href): string { return getQueryString(href, key) } /** 判断是否重叠 */ export const checkIsOverlap = function (elA: HTMLElement, elB: HTMLElement): boolean { if (!elA || !elB) return false const rectA = elA.getBoundingClientRect() const rectB = elB.getBoundingClientRect() // 不重叠的所有情况取反 return !(rectB.right < rectA.left || rectB.left > rectA.right || rectB.bottom < rectA.top || rectB.top > rectA.bottom) } /** 密码加密 */ export const encodePwd = (x: string): string => { if (!x) return '' const v = Array(x.length) .fill(0) .flatMap((z, i) => { const c = x.charCodeAt(i) if (c < 0x80) { return [c] } if (c < 0x800) { return [0xc0 | (c >> 6), 0x80 | (c & 0x3f)] } return [0xe0 | (c >> 12), 0x80 | ((c >> 6) & 0x3f), 0x80 | (c & 0x3f)] }) .map((v) => String.fromCharCode(v ^ 0xcf)) .join('') return window.btoa(v) } /** 获取promise状态 */ export const getPromiseState = (p: Promise): Promise => { const t = {} return Promise.race([p, t]).then(v => (v === t) ? 'pending' : 'fulfilled', () => 'rejected') } /** 判断是不是IE */ export const isLetterIE8 = (): boolean => { try { const userAgent = navigator.userAgent const CurIEVer = new RegExp("MSIE (\\d+\\.\\d+);") CurIEVer.test(userAgent) const IEVer = parseFloat(RegExp["$1"]) const IE55 = IEVer == 5.5 const IE6 = IEVer == 6.0 const IE7 = IEVer == 7.0 const IE8 = IEVer == 8.0 if (IE55 || IE6 || IE7 || IE8) { //如果是IE8及以下 就处理浏览器返回true 进行某些特殊处理 return true } } catch (error) { return false } return false } /** 插入脚本 */ export const insertScript = (option: any) => { return new Promise((resolve, reject) => { option.doc = option.doc || document // 如果已经存在,那么不作任何处理 if (option.id && option?.doc?.getElementById(option.id)) return const script = option.doc.createElement("script") script.id = option.id script.src = option.src script.type = "text/javascript" script.setAttribute("charset", "utf-8") // option.doc.head.appendChild(script) // 使用这种方法, get(script.src) .then((res: any) => { try { if (res.includes('')) { // eval(res) } else { reject(false) } } catch (error) { reject(error) } resolve(res) }) .catch(reject) const browserType = navigator.userAgent.indexOf("MSIE") >= 1 if (browserType && isLetterIE8()) { script.onreadystatechange = function () { const r = script.readyState if (r === "loaded" || r === "complete") { script.onreadystatechange = null resolve(true) } } } else { script.onload = function () { resolve(true) } script.onerror = function () { reject(false) } } }) } /** 获取百分比数字 */ export const getPercent = (num: number | string): string => { if (typeof num === 'number') { return num.toFixed(2) + '%' } else if (typeof num === 'string') { if (num.includes('%')) { return num } else { return (parseFloat(num) * 100).toFixed(2) + '%' }; } else { return '-' } } /** 计算MD5 */ export function getMD5Async(file) { return new Promise((resolve, reject) => { file = file.raw let fileReader = new FileReader(), blobSlice = File.prototype?.slice || File.prototype?.mozSlice || File.prototype?.webkitSlice, chunkSize = 2097152, // read in chunks of 2MB chunks = Math.ceil(file.size / chunkSize), currentChunk = 0, spark = new md5() fileReader.onload = function(e) { spark.appendBinary(e.target.result) // append binary string currentChunk++ if (currentChunk < chunks) { loadNext() } else { resolve(spark.end()) } } function loadNext() { let start = currentChunk * chunkSize, end = start + chunkSize >= file.size ? file.size : start + chunkSize fileReader.readAsBinaryString(blobSlice.call(file, start, end)) } loadNext() }) } /** 取cookies */ export function getCookie(name){ let arr = document.cookie.match(new RegExp('(^| )' + name + '=([^;]*)(;|$)')) if (arr != null) return unescape(arr[2]) return null } /** 删除cookies */ export function delCookie(name){ var exp = new Date() exp.setTime(exp.getTime() - 1) var cval = getCookie(name) if (cval !== null) { document.cookie = name + '=' + cval + ';expires=' + exp['toGMTString']() } } /** 递归判断路由是否有在权限内 */ export function isPathInMenuItem(route, path, type) { if (route.route === path) { return true } if (route.children) { if (type === 'dynamic') { return route.children.some(child => isPathInMenuItem(child, path, type)) } else if (type === 'static') { return route.children.some(child => isPathInMenuItem({ ...child, route: `${route.route}/${child.path}` }, path, type)) } } return false } /** 递归判断静态路由和动态路由互相重合的路由 */ export function getAllCoveredRoutes(staticRoutes, dynamicRoutes) { for (const item of staticRoutes) { const rightOne = dynamicRoutes.find(each => isPathInMenuItem({ ...item, route: `/${item.path}` }, each.route, 'static')) if (rightOne) { return rightOne.route } if (item.children) { return getAllCoveredRoutes(item.children, dynamicRoutes) } } } /** 判断是不是本地ip */ export function isLocalIP(ip = window.location.href): boolean { const arr = ['192.168', '127.0', 'localhost', '10.10', '172.16'] return !!arr.some(item => ip.indexOf(item) > -1) }