feat(modules/permission.ts): 动态路由完成

This commit is contained in:
有来技术 2021-11-30 23:56:53 +08:00
parent 1d21c6b098
commit 2e787ec921
6 changed files with 108 additions and 35 deletions

View File

@ -29,7 +29,10 @@ export default defineComponent({
setup(props) {
const router = useRouter()
const push = () => {
router.push(props.to)
console.log(props.to)
router.push(props.to).catch((err) => {
console.log(err)
})
}
return {
push,

View File

@ -1,41 +1,49 @@
<template>
<div>
<div v-if="!item.meta ||!item.meta.hidden">
<!-- 非嵌套路由 -->
<template>
<div v-if="!item.meta || !item.meta.hidden" >
<template
v-if="!item.children||item.children.length==0">
<app-link v-if="item.meta" :to="resolvePath(item.path)">
<el-menu-item :index="resolvePath(item.path)" :class="{'submenu-title-noDropdown':!isNest}">
<svg-icon v-if="item.meta && item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.meta && item.meta.title">{{ item.meta.title }}</span>
v-if="!alwaysShowRootMenu && theOnlyOneChild && !theOnlyOneChild.children"
>
<AppLink
v-if="theOnlyOneChild.meta"
:to="resolvePath(theOnlyOneChild.path)"
>
<el-menu-item
:index="resolvePath(theOnlyOneChild.path)"
:class="{'submenu-title-noDropdown': isFirstLevel}"
>
<svg-icon v-if="theOnlyOneChild.meta&&theOnlyOneChild.meta.icon" :icon-class="theOnlyOneChild.meta.icon"></svg-icon>
<span v-if="theOnlyOneChild.meta && theOnlyOneChild.meta.title">{{ theOnlyOneChild.meta.title }}</span>
</el-menu-item>
</app-link>
</AppLink>
</template>
<!-- 嵌套路由 -->
<el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<el-sub-menu
v-else
:index="resolvePath(item.path)"
>
<!-- popper-append-to-body -->
<template #title>
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>
<span v-if="item.meta && item.meta.title">{{ item.meta.title }}</span>
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
<template v-if="item.children">
<sidebar-item
v-for="child in item.children"
:key="child.path"
:item="child"
:is-collapse="isCollapse"
:is-first-level="false"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</template>
</el-sub-menu>
</div>
</div>
</template>
</template>
<script lang="ts">
import path from 'path-browserify'
import {defineComponent, PropType} from "vue";
import {defineComponent, PropType, reactive,computed } from "vue";
import {RouteRecordRaw} from 'vue-router'
import {isExternal} from '@utils/validate'
import AppLink from './Link.vue'
@ -43,23 +51,67 @@ import SvgIcon from '@/components/SvgIcon/index.vue';
export default defineComponent({
name: 'SidebarItem',
components: {SvgIcon, AppLink},
props: {
item: {
type: Object as PropType<RouteRecordRaw>,
required: true
},
isNest: {
isCollapse: {
type: Boolean,
default: false
required: false
},
isFirstLevel: {
type: Boolean,
required: true
},
basePath: {
type: String,
default: ''
required: true
}
},
components: {
AppLink,
SvgIcon
},
setup(props) {
const alwaysShowRootMenu = computed(() => {
if (props.item.meta && props.item.meta.alwaysShow) {
return true
} else {
return false
}
})
const showingChildNumber = computed(() => {
if (props.item.children) {
const showingChildren = props.item.children.filter((item) => {
if (item.meta && item.meta.hidden) {
return false
} else {
return true
}
})
return showingChildren.length
}
return 0
})
const theOnlyOneChild = computed(() => {
if (showingChildNumber.value > 1) {
return null
}
if (props.item.children) {
for (const child of props.item.children) {
if (!child.meta || !child.meta.hidden) {
return child
}
}
}
// If there is no children, return itself with path removed,
// because this.basePath already conatins item's path information
return { ...props.item, path: '' }
})
const resolvePath = (routePath: string) => {
if (isExternal(routePath)) {
return routePath
@ -67,11 +119,13 @@ export default defineComponent({
if (isExternal(props.basePath)) {
return props.basePath
}
console.log(props.basePath,routePath)
return path.resolve(props.basePath, routePath)
}
return {
alwaysShowRootMenu,
showingChildNumber,
theOnlyOneChild,
resolvePath
}
}

View File

@ -21,6 +21,7 @@
:item="route"
:key="route.path"
:base-path="route.path"
:is-collapse="isCollapse"
/>
</el-menu>
</el-scrollbar>

View File

@ -34,7 +34,6 @@ export const constantRoutes: Array<RouteRecordRaw> = [
path: '/',
component: Layout,
redirect: '/dashboard',
meta:{hidden:true},
children: [
{
path: 'dashboard',

View File

@ -2,8 +2,10 @@ import {Module} from "vuex";
import {PermissionState, RootStateTypes} from "@store/interface";
import {RouteRecordRaw} from 'vue-router'
import {constantRoutes} from '@/router'
import {getRouteList} from "@api/system/menu";
import {getRouteList} from "@/api/system/menu";
const modules = import.meta.glob("../../views/**/**.vue");
import Layout from '@/layout/index.vue'
const hasPermission = (roles: string[], route: RouteRecordRaw) => {
// 超级管理员放行
@ -26,10 +28,21 @@ export const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]) =>
routes.forEach(route => {
const tmp = {...route}
if (hasPermission(roles, tmp)) {
if (tmp.component == 'Layout') {
tmp.component = Layout
} else {
const component = modules[`../../views/${tmp.component}.vue`] as any;
if (component) {
tmp.component = modules[`../../views/${tmp.component}.vue`];
} else {
tmp.component = modules[`../../views/error-page/404.vue`];
}
}
res.push(tmp)
if (tmp.children) {
tmp.children = filterAsyncRoutes(tmp.children, roles)
}
res.push(tmp)
}
})
return res

View File

@ -1,5 +1,8 @@
<template>
<div>
123
</div>
</template>
<script>