UNPKG

yinghe-lowcode-zln

Version:

基于vue、ant-design-vue,datagrid的低代码平台

311 lines (293 loc) 8.29 kB
import * as loginService from '@/api/material/login' import { asyncRouterMap } from '@/config/router.config' // 布局页面路由生成器 const layoutRouterDirectory = {} const generatorLayoutRouter = context => { const routerComponents = {} const dirKeyRegex = /^.*\/([^/]+)\.vue$/ const replaceKeyRegex = /^.*(\/[^/]+)\.vue$/ context.keys().forEach(item => { const dir = item.replace(dirKeyRegex, '$1') const key = item.replace(replaceKeyRegex, '$1') if (!layoutRouterDirectory[dir]) { layoutRouterDirectory[dir] = key } routerComponents[key] = context(item).default }) return routerComponents } // 业务页面路由生成器 const viewsRouterDirectory = [] const generatorViewsRouter = context => { const routerComponents = {} const dirKeyRegex = /^\.{0,2}(\/[^/]+)\/(([^/]+\/?)+)\.vue$/ const replaceKeyRegex = /^\.{0,2}(\/([^/]+\/?)+)\.vue$/ const replaceValueRegex = /^\.{0,2}\/(([^/]+\/?)+)\.vue$/ context.keys().forEach(item => { const dir = item.replace(dirKeyRegex, '$1') const key = item.replace(replaceKeyRegex, '$1') const path = item.replace(replaceValueRegex, '$1') if (!viewsRouterDirectory.includes(dir)) { viewsRouterDirectory.push(dir) } routerComponents[key] = () => import(`@/views/${path}`) }) return routerComponents } // 前端路由汇总表 const constantRouterComponents = { // 布局基础页面 ...generatorLayoutRouter( // 过滤layouts下以_开头的文件夹的资源 require.context('@/layouts', false, /^((\.{0,2}\/(?!_\w*\/?))[^/]+)+\.vue$/i) ), // 业务相关页面 ...generatorViewsRouter( // 过滤views下非modules目录或者以_开头的文件夹的资源 require.context('@/views', true, /^((\.{0,2}\/(?!modules\/|_\w*\/?))[^/]+)+\.vue$/i) ) } // 前端未找到页面路由 const notFoundRouter = [ { path: '/404', name: '404', // component: () => import(`@/views/page/404`), meta: { title: '404', componentName: '404', hiddenHeaderContent: true, noCache: false }, hidden: true }, { path: '*', name: '*', redirect: '/404', hidden: true } ] // 默认外部链接路由 const externalRouter = { key: 'External', name: 'External', path: '/external', // component: () => import(`@/layouts/PageView`), redirect: '/external/link', meta: { title: '外部链接', componentName: 'External', hiddenHeaderContent: true, noCache: false }, children: [ { key: 'ExternalLink', name: 'ExternalLink', path: '/external/link', // component: () => import(`@/layouts/PageFrame`), meta: { title: '外部链接', match: 'external', external: 'www.baidu.com', componentName: 'ExternalLink', hiddenHeaderContent: true, noCache: false } } ], hidden: true } // 根级菜单 const rootRouter = { key: 'Basic', name: 'Basic', path: '/', component: 'BasicLayout', redirect: '/index', meta: { title: '首页' }, children: [] } /** * 转换树形结构 * @param list 源数组 * @param tree 树 * @param parentId 父ID */ const listToTree = (list, tree, parentId) => { list.forEach(item => { // 判断是否为父级菜单 if (item.parentId === parentId) { // 创建 route const route = { ...item, key: item.key || item.name, children: [] } // 迭代 list,找到符合的子菜单 listToTree(list, route.children, item.id) // 删掉不存在 children 属性 if (route.children.length <= 0) { delete route.children } // push route tree.push(route) } }) } /** * 动态生成菜单 * @param token * @returns {Promise<Router>} */ export const generatorDynamicRouter = token => { return new Promise((resolve, reject) => { loginService .getCurrentUserNav(token) .then(res => { if (res.code !== '0000') { reject(res) return } let children = [] const { result = [] } = res // 后端数据, 根级树数组,根级 PID listToTree(result, children, '1593523388247740416') children = asyncRouterMap.concat(children) const routers = generator([{ ...rootRouter, children }]) // 添加静态路由 routers[0].children.unshift(externalRouter) routers.push(...notFoundRouter) resolve(routers) }) .catch(err => { reject(err) }) }) } /** * 动态生成路由路径 * * @param parent * @param item * @returns {路由路径} */ export const generatorDynamicPath = (parent = {}, item = {}) => { // 正则 const format = '/$1' const regex = /^\/*([^/].*)/ // 路由路径 const keyPath = item.key || '' const itemPath = item.path || '' const parentPath = parent.path || '' const isNotIframeView = item.component !== 'PageFrame' return ( !(isNotIframeView && itemPath) ? (parentPath + '/' + keyPath).replace(regex, format) : itemPath ) } /** * 动态加载路由对应页面的组件 * * @param parent * @param item * @returns { 组件 } */ export const loadDynamicComponent = (parent = {}, item = {}) => { // 组件路径 const itemPath = item.path || '' const parentPath = parent.path || '' const componentPath = item.component || '' const isNotIframeView = item.component !== 'PageFrame' let currentPath = ( !(isNotIframeView && itemPath) ?'/' + componentPath : itemPath ).replace(/^\/*([^/].*)/, '/$1') if (itemPath === '/index') { currentPath = '/' + componentPath } // layout组件 for (const directoryPath in layoutRouterDirectory) { if (componentPath === directoryPath) { return constantRouterComponents[layoutRouterDirectory[directoryPath]] } } // views组件 for (const directoryPath of viewsRouterDirectory) { if (constantRouterComponents[directoryPath + currentPath]) { return constantRouterComponents[directoryPath + currentPath] } } // 默认组件 return () => import(`@/views/${currentPath.slice(1)}`) } /** * 格式化树形结构数据 生成 vue-router 层级路由表 * * @param routerMap * @param parent * @returns {*} */ export const generator = (routerMap, parent = {}) => { return routerMap.map(item => { const { title, show, noCache, hideChildren, hiddenHeaderContent, target, icon, pageId } = item.meta || {} const isNotIframeView = item.component !== 'PageFrame' const match = isNotIframeView ? 'path' : 'external' const currentRouter = { // 路由path path: generatorDynamicPath(parent, item), // 路由名称 name: item.name || item.key || '', // 路由组件 component: loadDynamicComponent(parent, item), // 路由meta meta: { icon: icon, show: show, keepAlive: true, match: match, title: title, target: target, pageId: item.pageId, noCache: false, external: !isNotIframeView && item.path || '', componentName: item.component || item.name || item.key || '', hiddenHeaderContent: hiddenHeaderContent !== undefined ? hiddenHeaderContent !== false : (parent.meta || {}).hiddenHeaderContent !== false, permission: [item.name || item.key || ''] } } // 是否设置了隐藏菜单 if (show === false) { currentRouter.hidden = true } // 是否设置了隐藏子菜单 if (hideChildren) { currentRouter.hideChildrenInMenu = true } // PageFrame 使用别名 if (!isNotIframeView) { currentRouter.alias = currentRouter.path + '/*' } // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠 if (!currentRouter.path.startsWith('http')) { currentRouter.path = currentRouter.path.replace('//', '/') } // 重定向 if (item.redirect) { currentRouter.redirect = item.redirect } // 是否有子菜单,并递归处理 if (item.children && item.children.length > 0) { currentRouter.children = generator(item.children, currentRouter) } return currentRouter }) }