目录
一、项目介绍
项目使用vite搭建基础框架,配置Router、store等,根据大多需求的情况下,实现系统的菜单权限,路由权限,登录鉴权,按钮权限等。同时封装了axios请求,router路由以及pinia状态管理等。
二、项目技术
使用vue3 setup语法糖配合typeScript+vite+router+pinia实现的管理系统摸板。我的以前文章也有简单的tsx封装的项目,借鉴使用,也踩了许多坑。
三、项目功能详细介绍
1、登录功能
目前登录没有完整,只是为了能够登录,后期使用需要做相应的修改。
2、菜单权限
菜单权限我的方法是:在设定router时,将无需权限和需要权限的路由分隔开,在meta中定义角色,通过判断角色动态显示菜单。
//处理权限
export const hasPermission = (route: any, role: any) => {
if (route.meta && route.meta.roles) {
return route.meta.roles.includes(role);
}
//默认不设置权限,所有角色可以访问
return true;
};
// 菜单权限处理
export const filterAsyncRouter = (routerMap: any, roles: any) => {
const accessedRouters = routerMap.filter((route: any) => {
// 判断用户是否有权限,默认有权限
if (hasPermission(route, roles)) {
if (route.children && route.children.length) {
// 这里使用了递归思想,
route.children = filterAsyncRouter(route.children, roles);
}
return true;
}
return false;
});
return accessedRouters;
};
3、路由权限
为什么做路由权限,其实公司不要求可以不做,多一事不如少一事,但是心里过意不去。路由权限往往配合菜单权限同时使用,因为菜单动态显示,菜单不显示时可以访问其路由,所有要做路由权限。实现思路:首先你要将角色的路由处理好,每个角色对应自己的菜单路由,然后利用addRoute动态添加路由。vue-router官网中有详细介绍。
addRoute#
添加一条新的路由记录作为现有路由的子路由。如果路由有一个 name
,并且已经有一个与之名字相同的路由,它会先删除之前的路由。
函数签名:
addRoute(parentName: string | symbol, route: RouteRecordRaw): () => void
参数
参数 | 类型 | 描述 |
---|---|---|
parentName | string | symbol | 父路由记录,route 应该被添加到的位置 |
route | RouteRecordRaw | 要添加的路由记录 |
我在实现此功能时遇到了很多的坑:
1.刚进入页面是一片空白
这是因为路由添加进去以后没有及时跟新,只需要重新进行路由拦截即可。这同时解决刷新的问题。
// 路由添加进去了没有及时更新 需要重新进去一次拦截
if (hasRoles) {
routes.forEach((item) => router.addRoute("Layout", item));
hasRoles = false;
next({ ...to, replace: true }); // 这里相当于push到一个页面 不在进入路由拦截
} else {
next(); // 如果不传参数就会重新执行路由拦截,重新进到这里
}
2.页面显示没有问题但是一直有警告
这是因为页面初始化时addRoute还没有添加到路由,但为什么页面可以显示,这是因为后边进行了路由拦截所以页面匹配到了路由所以可以显示。去掉警告的方法,就是在app初始化之前添加路由,也就是在main.ts中。
main.ts文件
const app = createApp(App);
refreshRoute().then(() => {
app.use(router);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.directive("permissions", btnPermission);
app.use(createPinia());
app.config.globalProperties.$message = ElMessage;
app.mount("#app");
});
refreshRoute.ts文件
export default () => {
return new Promise((resolve) => {
const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
permissionToken();
// 获取处理好的路由
let routes = userStore().routers;
routes.forEach((item) => router.addRoute("Layout", item));
resolve("success");
});
};
4、按钮权限
按钮权限实现是封装自定义指令,自定义指令不熟悉请查看文档。
import { Directive } from "vue";
export const btnPermission: Directive<HTMLInputElement> = (el, binding) => {
// 这里在mounted和update时都调用
// 获取自定义指令内容
const btnKey = binding.value;
if (btnKey) {
const key = checkKey(btnKey);
if (!key) {
el.remove();
}
}
};
const checkKey = (key: string) => {
// 获取后端返回的按钮权限组
const permissionBtnArr = JSON.parse(
sessionStorage.getItem("permissionBtnArr")!
);
// 如果传入的元素key不在权限组中
const permissionData = permissionBtnArr || [];
const index = permissionData.indexOf(key);
return index > -1;
};
详细代码请访问gitee: https://gitee.com/liu--zicheng/vue3-vite-template.git 大家多多支持,后期会不断更新功能。勿喷