router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
// 引入 useStore
import { useStore } from '../store/index.js'
const routes = [
{
path: '/',
redirect: '/order'
},
{
path: '/login',
name: 'login',
component: () => import(/* webpackChunkName: "about" */ '../views/login.vue')
},
]
// 动态路由,根据用户权限动态添加
const asyncRoutes = [
{
path: '/order',
name: 'order',
component: () => import(/* webpackChunkName: "about" */ '../views/navindex/order.vue'),
redirect: '/order/awayorder',
meta: {
id:1,
title: '订单管理',
icon1:'order.png',
icon2:'order2.png',
},
children: [
{
path: 'awayorder',
name: 'awayorder',
component: () => import(/* webpackChunkName: "about" */ '../views/awayorder.vue'),
meta: {
id:2,
title: '收单管理',
},
},
{
path: 'sendorder',
name: 'sendorder',
component: () => import(/* webpackChunkName: "about" */ '../views/sendorder.vue'),
meta: {
id:3,
title: '派单管理',
},
},
]
},
{
path: '/system',
name: 'system',
component: () => import(/* webpackChunkName: "about" */ '../views/navindex/system.vue'),
redirect: '/system/staffm',
meta: {
id:4,
title: '系统管理',
icon1:'set.png',
icon2:'set2.png',
},
children: [
{
path: 'staffm',
name: 'staffm',
component: () => import(/* webpackChunkName: "about" */ '../views/staffm.vue'),
meta: {
id:5,
title: '人员管理',
},
},
{
path: 'rolesm',
name: 'rolesm',
component: () => import(/* webpackChunkName: "about" */ '../views/rolesm.vue'),
meta: {
id:6,
title: '角色管理',
},
},
]
},
//无子集页面
{
path: '/test',
name: 'test',
component: () => import(/* webpackChunkName: "about" */ '../views/test.vue'),
meta: {
id:20,
title: '测试',
icon1:'set.png',
icon2:'set2.png',
},
},
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 根据权限id,过滤要添加的路由的函数
function filterAsyncRoutes(routes, permissions) {
const filteredRoutes = [];
routes.forEach(route => {
const newRoute = { ...route };
//添加路由的条件,根据需求调整
if (permissions.includes(route.meta?.id)) {
if (route.children) {
newRoute.children = filterAsyncRoutes(route.children, permissions);
}
filteredRoutes.push(newRoute);
} else if (route.children) {
const filteredChildren = filterAsyncRoutes(route.children, permissions);
if (filteredChildren.length > 0) {
newRoute.children = filteredChildren;
filteredRoutes.push(newRoute);
}
}
});
return filteredRoutes;
}
// 添加动态路由的函数
function addDynamicRoutes(permissions) {
// 清除旧的动态路由
asyncRoutes.forEach(route => {
router.removeRoute(route.name);
});
const filteredRoutes = filterAsyncRoutes(asyncRoutes, permissions);
filteredRoutes.forEach(route => {
router.addRoute(route);
});
// 因为watch无法监听都动态添加的路由,所以用pinia进行存储,让导航能使用到
const store = useStore();
store.addnowroute(filteredRoutes);
console.log('filteredRoutes========')
console.log(filteredRoutes)
}
// 处理页面刷新
router.beforeEach((to, from, next) => {
//刷新重新加载路由
if (to.path === '/login') {
localStorage.removeItem('user');
next();
return;
}
if(JSON.parse(localStorage.getItem('user'))){
const permissions = JSON.parse(localStorage.getItem('user')).permission;
if (permissions && router.getRoutes().length === routes.length) {
addDynamicRoutes(permissions);
next({ ...to, replace: true });
} else {
next();
}
}else{
next('/login');
}
});
//导出方法,在登录后获取权限,进行动态路由添加
export { addDynamicRoutes };
export default router;
pinia
import { defineStore } from 'pinia'
export const useStore = defineStore('storeId',{
state: ()=>{
return {
nowroute:[]
}
},
getters: {
},
actions: {
addnowroute(arr){
this.nowroute = arr
},
},
// 开启数据缓存
// persist:{
// enabled:true,
// strategies:[
// {
// key:'my_user',//储存的key
// storage:localStorage,//储存方式
// paths:['num']//储存数据,不要此项则储存所有数据
// }
// ]
// }
})
login.vue
<template>
<div class="home">
<button @click="loginbtn">登录</button>
</div>
</template>
<script setup>
import {login} from '@/assets/js/common.js'
import { inject ,onMounted,ref, reactive} from "vue";
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Delete, Edit, Search, Share, Upload, Plus, Close } from '@element-plus/icons-vue'
import {useStore} from '../store'
import { storeToRefs } from 'pinia';
// 重点!!!!!!!!!!
import { addDynamicRoutes } from '@/router/index'; // 引入封装的方法
//路由跳转
const router = useRouter()
//获取数据
const route = useRoute()
onMounted(() => {
console.log('onMounted')
})
const loginbtn = ()=>{
login({name: '三国演义',password: '111111'}).then((response)=>{
console.log(response)
// 模拟登录成功后获取权限数组
const permissions = [ 2, 5,20];
localStorage.setItem('permissions', JSON.stringify(permissions));
// 添加动态路由
addDynamicRoutes(permissions);
//这里根据需求判断跳转页面
router.push('/')
})
}
</script>
app.vue
<el-menu
style="background-color: #eff1f6;margin-top: 30px;"
:default-active="nowpath"
router
@select="handleSelect"
>
<div class="t_nav_list_box" v-for="(item,index) in navlist.data" :key="index">
<!-- 有子集的导航 -->
<el-sub-menu v-if="item.children" :index="item.path" >
<template #title>
<img class="t_nav_icon" v-if="isStringIncluded(nowpath,item.path)" :src="getIconPath(item.meta.icon1)" alt="">
<img class="t_nav_icon" v-else :src="getIconPath(item.meta.icon2)" alt="">
<span style="margin-left: 5px;" :class="{'t_nav_color':isStringIncluded(nowpath,item.path)}">{{ item.meta.title }}</span>
</template>
<el-menu-item v-for="(item2,index2) in item.children" :key="index2" :index="item.path+'/'+item2.path">{{ item2.meta.title }}</el-menu-item>
</el-sub-menu>
<!-- 无子集的导航 -->
<el-menu-item v-else :index="item.path" >
<img class="t_nav_icon" v-if="isStringIncluded(nowpath,item.path)" :src="getIconPath(item.meta.icon1)" alt="">
<img class="t_nav_icon" v-else :src="getIconPath(item.meta.icon2)" alt="">
<span style="margin-left: 5px;">{{ item.meta.title }}</span>
</el-menu-item>
</div>
</el-menu>
// 引入 useStore
import { useStore } from '@/store';
import { storeToRefs } from 'pinia';
const store = useStore();
let {nowroute} = storeToRefs(store)
//菜单列表
const navlist = reactive({
data:[]
})
//当前路由
const nowpath = ref('/order')
/js判断当前父级路由是否是当前选中的子集路由,改变图标颜色和子集颜色
const isStringIncluded = (str, target)=> {
return str.includes(target);
}
// 计算属性,生成选中状态的图标路径
const getIconPath = (path) => {
return require(`../src/assets/img/${path}`)
}
//监听当前路由
onMounted(() => {
//从pinia拿到当前动态添加的路由,赋值给导航栏
navlist.data = nowroute;
})
//监听当前路由
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
//获取所有路由
// var allroute = proxy.$router.options.routes
nowpath.value = newValue
}, { immediate: true, deep: true })