import { h, unref } from 'vue'; import type { App, Plugin } from 'vue'; import { ElIcon, ElTag } from 'element-plus'; import { PageEnum } from '@/enums/pageEnum'; import { isObject, isString, isNumber } from './is/index'; import { cloneDeep } from 'lodash-es'; import { TargetContext } from '/#/index'; /** * render 图标 * */ export function renderIcon(icon) { return () => h(ElIcon, null, { default: () => h(icon) }); } /** * render 图片 * */ export function renderImg(imgSrc: string) { return () => h('img', { src: imgSrc, class: 'my-icon' }); } /** * render new Tag * */ const newTagColors = { color: '#f90', textColor: '#fff', borderColor: '#f90' }; export function renderNew(type = 'warning', text = 'New', color: object = newTagColors) { return () => h( ElTag as any, { type, round: true, size: 'small', color, }, { default: () => text }, ); } /** * 递归组装菜单格式 */ export function generatorMenu(routerMap: Array) { return filterRouter(routerMap).map((item) => { const isRoot = isRootRouter(item); const info = isRoot ? item.children[0] : item; const currentMenu = { ...info, ...info.meta, title: info.meta?.title, key: info.name, icon: isRoot ? item.meta?.icon : info.meta?.icon, }; // 是否有子菜单,并递归处理 if (info.children && info.children.length > 0) { // Recursion currentMenu.children = generatorMenu(info.children); } return currentMenu; }); } /** * 混合菜单 * */ export function generatorMenuMix(routerMap: Array, routerName: string, location: string) { const cloneRouterMap = cloneDeep(routerMap); const newRouter = filterRouter(cloneRouterMap); if (location === 'header') { const firstRouter: any[] = []; newRouter.forEach((item) => { const isRoot = isRootRouter(item); const info = isRoot ? item.children[0] : item; info.children = undefined; const currentMenu = { ...info, ...info.meta, title: info.meta?.title, key: info.name, }; firstRouter.push(currentMenu); }); console.log(firstRouter); return firstRouter; } else { const currentRouters = newRouter.filter((item) => item.name === routerName); const childrenRouter = currentRouters.length ? currentRouters[0].children || [] : []; return getChildrenRouter(childrenRouter); } } /** * 递归组装子菜单 * */ export function getChildrenRouter(routerMap: Array) { return filterRouter(routerMap).map((item) => { const isRoot = isRootRouter(item); const info = isRoot ? item.children[0] : item; const currentMenu = { ...info, ...info.meta, title: info.meta?.title, key: info.name, }; // 是否有子菜单,并递归处理 if (info.children && info.children.length > 0) { // Recursion currentMenu.children = getChildrenRouter(info.children); } return currentMenu; }); } /** * 判断根路由 Router * */ export function isRootRouter(item) { return item.meta?.alwaysShow === true && item.children?.length === 1; } /** * 排除Router * */ export function filterRouter(routerMap: Array) { return routerMap.filter((item) => { return ( (item.meta?.hidden || false) != true && !['/:path(.*)*', '/', PageEnum.REDIRECT, PageEnum.BASE_LOGIN].includes(item.path) ); }); } export const withInstall = (component: T, alias?: string) => { const comp = component as any; comp.install = (app: App) => { app.component(comp.name || comp.displayName, component); if (alias) { app.config.globalProperties[alias] = component; } }; return component as T & Plugin; }; /** * 找到对应的节点 * */ let result = null; export function getTreeItem(data: any[], key?: string | number, keyField = 'key'): any { data.map((item) => { if (item[keyField] === key) { result = item; } else { if (item.children && item.children.length) { getTreeItem(item.children, key, keyField); } } }); return result; } /** * 找到所有节点 * */ const treeAll: any[] = []; export function getTreeAll(data: any[]): any[] { data.map((item) => { treeAll.push(item.key); if (item.children && item.children.length) { getTreeAll(item.children); } }); return treeAll; } // dynamic use hook props export function getDynamicProps(props: T): Partial { const ret: Recordable = {}; Object.keys(props).map((key) => { ret[key] = unref((props as Recordable)[key]); }); return ret as Partial; } export function deepMerge(src: any = {}, target: any = {}): T { let key: string; for (key in target) { src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]); } return src; } /** * Sums the passed percentage to the R, G or B of a HEX color * @param {string} color The color to change * @param {number} amount The amount to change the color by * @returns {string} The processed part of the color */ function addLight(color: string, amount: number) { const cc = parseInt(color, 16) + amount; const c = cc > 255 ? 255 : cc; return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`; } /** * Lightens a 6 char HEX color according to the passed percentage * @param {string} color The color to change * @param {number} amount The amount to change the color by * @returns {string} The processed color represented as HEX */ export function lighten(color: string, amount: number) { color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color; amount = Math.trunc((255 * amount) / 100); return `#${addLight(color.substring(0, 2), amount)}${addLight( color.substring(2, 4), amount, )}${addLight(color.substring(4, 6), amount)}`; } export function openWindow( url: string, opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }, ) { const { target = '__blank', noopener = true, noreferrer = true } = opt || {}; const feature: string[] = []; noopener && feature.push('noopener=yes'); noreferrer && feature.push('noreferrer=yes'); window.open(url, target, feature.join(',')); } /** * 处理css单位 * */ export function cssUnit(value: string | number, unit = 'px') { return isNumber(value) || (isString(value) && value.indexOf(unit as string) === -1) ? `${value}${unit}` : value; } /** * 判断是否 url * */ export function isUrl(url: string) { return /^(http|https):\/\//g.test(url); } /* * 模拟a下载一个文件 * @params res 结果集 * @params filename 文件名 */ export const downloadFile = (res, filename?) => { const blob = new Blob([res.data]); let fileName = filename || res.headers['content-disposition'].split('filename=').pop(); fileName = decodeURIComponent(fileName); if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE window.navigator.msSaveOrOpenBlob(blob, fileName); } else { const objectUrl = (window.URL || window.webkitURL).createObjectURL(blob); const downFile = document.createElement('a'); downFile.style.display = 'none'; downFile.href = objectUrl; downFile.download = fileName; // 下载后文件名 document.body.appendChild(downFile); downFile.click(); document.body.removeChild(downFile); // 下载完成移除元素 window.URL.revokeObjectURL(objectUrl); // 释放掉blob对象。 } }; /** * 将rgb或rgba颜色转化为[hex,透明度?] */ export const colorRGB2Hex = (color: string): string[] => { if (!color) return ['', '']; const pattern = /\((\d+),\s*(\d+),\s*(\d+),\s*(\d+(\.\d+)?)\)$/; const array = color.match(pattern); const r = Number(array![1]); const g = Number(array![2]); const b = Number(array![3]); const hex = '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); return [hex, Number(array![4]) * 100 + '%']; };