'admin-21.01.26:处理各菜单导航a链接跳转、前端控制页面菜单权限等'

This commit is contained in:
lyt 2021-01-26 18:17:13 +08:00
parent fcdd6cace6
commit a66f93d59d
8 changed files with 128 additions and 41 deletions

View File

@ -9,13 +9,7 @@ export const dynamicRoutes = [
component: () => import('/@/views/layout/index.vue'), component: () => import('/@/views/layout/index.vue'),
redirect: '/home', redirect: '/home',
meta: { meta: {
title: '首页', isKeepAlive: true
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
icon: 'iconfont icon-shouye'
}, },
children: [{ children: [{
path: '/home', path: '/home',
@ -28,6 +22,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: true, isAffix: true,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-shouye' icon: 'iconfont icon-shouye'
} }
}, },
@ -43,6 +38,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-xitongshezhi' icon: 'iconfont icon-xitongshezhi'
}, },
children: [ children: [
@ -57,6 +53,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
}, },
@ -71,6 +68,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-icon-', icon: 'iconfont icon-icon-',
} }
} }
@ -88,6 +86,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-quanxian' icon: 'iconfont icon-quanxian'
}, },
children: [ children: [
@ -102,7 +101,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
}, },
children: [ children: [
{ {
@ -115,7 +115,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
} }
}, },
{ {
@ -128,7 +129,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
} }
} }
] ]
@ -143,7 +145,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
}, },
children: [ children: [
{ {
@ -156,7 +159,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
} }
}, },
{ {
@ -169,7 +173,8 @@ export const dynamicRoutes = [
isHide: false, isHide: false,
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false isIframe: false,
auth: ['admin', 'test']
} }
} }
] ]
@ -188,6 +193,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-xitongshezhi' icon: 'iconfont icon-xitongshezhi'
}, },
children: [ children: [
@ -203,6 +209,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
}, },
children: [ children: [
@ -217,6 +224,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
}, },
@ -232,6 +240,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
}, },
children: [ children: [
@ -246,6 +255,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
}, },
@ -260,6 +270,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
} }
@ -276,6 +287,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
} }
@ -292,6 +304,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan' icon: 'iconfont icon-caidan'
} }
} }
@ -309,6 +322,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-crew_feature' icon: 'iconfont icon-crew_feature'
}, },
children: [ children: [
@ -323,6 +337,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'el-icon-thumb' icon: 'el-icon-thumb'
} }
} }
@ -339,6 +354,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-fuzhiyemian' icon: 'iconfont icon-fuzhiyemian'
} }
}, },
@ -353,6 +369,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-zujian' icon: 'iconfont icon-zujian'
} }
}, },
@ -367,6 +384,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-ico_shuju' icon: 'iconfont icon-ico_shuju'
} }
}, },
@ -381,6 +399,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-gerenzhongxin' icon: 'iconfont icon-gerenzhongxin'
} }
}, },
@ -395,6 +414,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-gongju' icon: 'iconfont icon-gongju'
} }
}, },
@ -409,6 +429,7 @@ export const dynamicRoutes = [
isKeepAlive: false, isKeepAlive: false,
isAffix: false, isAffix: false,
isIframe: false, isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-caozuo-wailian' icon: 'iconfont icon-caozuo-wailian'
} }
}, },
@ -423,6 +444,7 @@ export const dynamicRoutes = [
isKeepAlive: true, isKeepAlive: true,
isAffix: true, isAffix: true,
isIframe: true, isIframe: true,
auth: ['admin'],
icon: 'iconfont icon-neiqianshujuchucun' icon: 'iconfont icon-neiqianshujuchucun'
} }
}] }]
@ -504,16 +526,62 @@ export function setCacheTagsViewRoutes() {
store.dispatch('setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children) store.dispatch('setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children)
} }
// 获取当前用户的权限去比对路由表,用于左侧菜单/横向菜单的显示
export function setFilterMenu() {
if (store.state.auths.length <= 0) store.dispatch('setAuths')
store.dispatch("setRoutes", setFilterMenuFun(dynamicRoutes[0].children, store.state.auths))
}
// 判断路由 auth 中是否包含当前登录用户权限字段
export function hasAuth(auths: any, route: any) {
if (route.meta && route.meta.auth) return auths.some((auth: any) => route.meta.auth.includes(auth))
else return true
}
// 递归过滤又权限的路由
export function setFilterMenuFun(routes: any, auth: any) {
const menu: any = []
routes.map((route: any) => {
const item = { ...route }
if (hasAuth(auth, item)) {
if (item.children) item.children = setFilterMenuFun(item.children, auth)
menu.push(item)
}
})
return menu
}
// 获取当前用户的权限去比对路由表,用于动态路由的添加
export function setFilterRoute() {
if (store.state.auths.length <= 0) store.dispatch('setAuths')
let filterRoute: any = []
formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children.map((route: any) => {
route.meta.auth.map((metaAuth: any) => {
store.state.auths.map((auth: any) => {
if (metaAuth === auth) filterRoute.push({ ...route })
})
})
})
return filterRoute
}
// 比对后的路由表,进行重新赋值
export function setFilterRouteEnd() {
let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))
filterRouteEnd[0].children = setFilterRoute()
return filterRouteEnd
}
// 添加动态路由 // 添加动态路由
export function setAddRoute() { export function setAddRoute() {
formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)).map((route: any) => { setFilterRouteEnd().map((route: any) => {
router.addRoute(route as RouteRecordRaw) router.addRoute(route as RouteRecordRaw)
}) })
} }
// 删除/重置路由 // 删除/重置路由
export function resetRoute() { export function resetRoute() {
formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes)).map((route: any) => { setFilterRouteEnd().map((route: any) => {
const { name } = route const { name } = route
router.hasRoute(name) && router.removeRoute(name) router.hasRoute(name) && router.removeRoute(name)
}) })
@ -521,8 +589,10 @@ export function resetRoute() {
// 初始化执行函数 // 初始化执行函数
setAddRoute() setAddRoute()
setFilterMenu()
setCacheTagsViewRoutes() setCacheTagsViewRoutes()
// router.afterEach((to, from) => { // router.afterEach((to, from) => {
// }) // })

View File

@ -44,7 +44,8 @@ export interface RootStateTypes {
}, },
routes: Array<object>, routes: Array<object>,
caches: Array<string>, caches: Array<string>,
tagsViewRoutes: Array<object> tagsViewRoutes: Array<object>,
auths: Array<string>
} }
export const key: InjectionKey<Store<RootStateTypes>> = Symbol() export const key: InjectionKey<Store<RootStateTypes>> = Symbol()
@ -54,7 +55,8 @@ export const store = createStore<RootStateTypes>({
themeConfig, themeConfig,
routes: [], routes: [],
caches: [], caches: [],
tagsViewRoutes: [] tagsViewRoutes: [],
auths: []
}, },
mutations: { mutations: {
getThemeConfig(state: any, data: object) { getThemeConfig(state: any, data: object) {
@ -68,6 +70,9 @@ export const store = createStore<RootStateTypes>({
}, },
getTagsViewRoutes(state: any, data: Array<string>) { getTagsViewRoutes(state: any, data: Array<string>) {
state.tagsViewRoutes = data state.tagsViewRoutes = data
},
getAuths(state: any, data: Array<string>) {
state.auths = data
} }
}, },
actions: { actions: {
@ -83,6 +88,13 @@ export const store = createStore<RootStateTypes>({
async setTagsViewRoutes({ commit }, data: Array<string>) { async setTagsViewRoutes({ commit }, data: Array<string>) {
commit('getTagsViewRoutes', data) commit('getTagsViewRoutes', data)
}, },
setAuths({ commit }, data: Array<string>) {
const defaultAuthList: Array<string> = ['admin', 'btn.add', 'btn.del', 'btn.edit']
let authList: Array<string> = []
if (data && data.length > 0) authList = data
else authList = defaultAuthList
commit('getAuths', authList)
}
} }
}) })

View File

@ -19,7 +19,6 @@ import {
onUnmounted, onUnmounted,
} from "vue"; } from "vue";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import { dynamicRoutes } from "/@/router/index.ts";
import Logo from "/@/views/layout/logo/index.vue"; import Logo from "/@/views/layout/logo/index.vue";
import Vertical from "/@/views/layout/navMenu/vertical.vue"; import Vertical from "/@/views/layout/navMenu/vertical.vue";
export default { export default {
@ -34,7 +33,6 @@ export default {
// // // //
const setFilterRoutes = () => { const setFilterRoutes = () => {
if (store.state.themeConfig.layout === "columns") return false; if (store.state.themeConfig.layout === "columns") return false;
store.dispatch("setRoutes", dynamicRoutes[0].children);
state.menuList = filterRoutesFun(store.state.routes); state.menuList = filterRoutesFun(store.state.routes);
}; };
// //

View File

@ -5,21 +5,19 @@
<li v-for="(v,k) in columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v,k)" <li v-for="(v,k) in columnsAsideList" :key="k" @click="onColumnsAsideMenuClick(v,k)"
:ref="el => { if (el) columnsAsideOffsetTopRefs[k] = el }" :class="{'layout-columns-active':liIndex === k}" :ref="el => { if (el) columnsAsideOffsetTopRefs[k] = el }" :class="{'layout-columns-active':liIndex === k}"
:title="v.meta.title"> :title="v.meta.title">
<div class="layout-columns-aside-li-box"> <div class="layout-columns-aside-li-box" v-if="!v.meta.isLink || v.meta.isLink && v.meta.isIframe">
<template v-if="!v.meta.isLink"> <i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}}
</div>
</div>
<div class="layout-columns-aside-li-box" v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i> <i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12"> <div class="layout-columns-aside-li-box-title font12">
{{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}} {{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}}
</div> </div>
</template> </a>
<template v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i>
<div class="layout-columns-aside-li-box-title font12">
{{v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0,4) : v.meta.title}}
</div>
</a>
</template>
</div> </div>
</li> </li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div> <div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
@ -40,7 +38,6 @@ import {
} from "vue"; } from "vue";
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router"; import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import { dynamicRoutes } from "/@/router/index.ts";
export default { export default {
name: "layoutColumnsAside", name: "layoutColumnsAside",
setup() { setup() {
@ -88,7 +85,6 @@ export default {
}; };
// // // //
const setFilterRoutes = () => { const setFilterRoutes = () => {
store.dispatch("setRoutes", dynamicRoutes[0].children);
state.columnsAsideList = filterRoutesFun(store.state.routes); state.columnsAsideList = filterRoutesFun(store.state.routes);
const resData = setSendChildren(route.path); const resData = setSendChildren(route.path);
onColumnsAsideDown(resData.item[0], resData.item[0].k); onColumnsAsideDown(resData.item[0], resData.item[0].k);

View File

@ -18,7 +18,6 @@ import {
} from "vue"; } from "vue";
import { useRoute, onBeforeRouteUpdate } from "vue-router"; import { useRoute, onBeforeRouteUpdate } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import { dynamicRoutes } from "/@/router/index.ts";
import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue"; import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue";
import User from "/@/views/layout/navBars/breadcrumb/user.vue"; import User from "/@/views/layout/navBars/breadcrumb/user.vue";
import Logo from "/@/views/layout/logo/index.vue"; import Logo from "/@/views/layout/logo/index.vue";
@ -55,7 +54,6 @@ export default {
// // // //
const setFilterRoutes = () => { const setFilterRoutes = () => {
let { layout, isClassicSplitMenu } = store.state.themeConfig; let { layout, isClassicSplitMenu } = store.state.themeConfig;
store.dispatch("setRoutes", dynamicRoutes[0].children);
if (layout === "classic" && isClassicSplitMenu) { if (layout === "classic" && isClassicSplitMenu) {
state.menuList = delClassicChildren( state.menuList = delClassicChildren(
filterRoutesFun(store.state.routes) filterRoutesFun(store.state.routes)

View File

@ -11,10 +11,16 @@
<SubItem :chil="val.children" /> <SubItem :chil="val.children" />
</el-submenu> </el-submenu>
<el-menu-item :index="val.path" :key="val.path" v-else> <el-menu-item :index="val.path" :key="val.path" v-else>
<i :class="val.meta.icon ? val.meta.icon : ''"></i> <template #title v-if="!val.meta.isLink || val.meta.isLink && val.meta.isIframe">
<template #title <i :class="val.meta.icon ? val.meta.icon : ''"></i>
v-if="!val.meta.isLink || val.meta.isLink && val.meta.isIframe">{{ val.meta.title }}</template> {{ val.meta.title }}
<template #title v-else><a :href="val.meta.isLink" target="_blank">{{ val.meta.title }}</a></template> </template>
<template #title v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ val.meta.title }}
</a>
</template>
</el-menu-item> </el-menu-item>
</template> </template>
</el-menu> </el-menu>
@ -111,6 +117,9 @@ export default defineComponent({
::v-deep(.el-scrollbar__bar.is-vertical) { ::v-deep(.el-scrollbar__bar.is-vertical) {
display: none; display: none;
} }
::v-deep(a) {
width: 100%;
}
.el-menu.el-menu--horizontal { .el-menu.el-menu--horizontal {
display: flex; display: flex;
height: 100%; height: 100%;

View File

@ -8,11 +8,16 @@
<sub-item :chil="val.children" /> <sub-item :chil="val.children" />
</el-submenu> </el-submenu>
<el-menu-item :index="val.path" :key="val.path" v-else> <el-menu-item :index="val.path" :key="val.path" v-else>
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<template v-if="!val.meta.isLink || val.meta.isLink && val.meta.isIframe"> <template v-if="!val.meta.isLink || val.meta.isLink && val.meta.isIframe">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ val.meta.title }}</span> <span>{{ val.meta.title }}</span>
</template> </template>
<template v-else><a :href="val.meta.isLink" target="_blank">{{ val.meta.title }}</a></template> <template v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ val.meta.title }}
</a>
</template>
</el-menu-item> </el-menu-item>
</template> </template>
</template> </template>

View File

@ -25,7 +25,6 @@ import {
import { import {
useRoute, useRoute,
useRouter, useRouter,
RouteRecordRaw,
onBeforeRouteUpdate, onBeforeRouteUpdate,
} from "vue-router"; } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";