啊,我们经常做权限控制,控制菜单,控制按钮功能等,但是在一些特殊情况下不能够由后端来做权限控制,那就只能前端来做啦。
🤔初步思路
后端来控制权限,是在新增用户的时候来给用户添加不同的菜单或者按钮级别的权限,这些其实也是和前端约定好的数据,保存在数据库里面,那么前端在自己代码保存一份权限文件,通过对不同用户需求进行打包,不就能够生成对应的系统了吗?
🎍环境变量
- 新建env文件
假如有两个用户权限为A
和B
,那我们就新建两个env
文件,分别为.env.A
和.env.B
,分别在其中写入VITE_MODE=A
和VITE_MODE=B
。
- 设置命令
在package.json
中设置命令,A:vite --mode A
,B:vite --mode B
- 运行命令
运行yarn A
或者yarn B
。
- 获取环境变量
import.meta.env.MODE
即可获取env
文件中的MODE
参数,也就是环境变量。
🖥️配置文件
- 新建
premissionConfig
文件
// 引入路由菜单文件
import { routerMap } from "@/routers/routerMap";
export interface MenuList {
name: string;
icon: string;
to: string;
value: string;
id: string;
}
interface Center {
actionList: string[];
menuList: MenuList[];
}
interface Station extends Center {}
interface PremissionConfig {
center: Center;
station: Station;
}
export const premissionConfig: PremissionConfig = {
center: {
actionList: ["get"],
// 假设有以下几个菜单
menuList: [
{name: "A",to: routerMap.A,id: "A"},
{name: "B",to: routerMap.B,id: "B"},
{name: "C",to: routerMap.C,id: "C"},
],
},
station: {
actionList: ["post", "delete", "put", "download"],
menuList: [
{name: "A",to: routerMap.A,id: "A"},
{name: "B",to: routerMap.B,id: "B"},
{name: "C",to: routerMap.C,id: "C"},
{name: "D",to: routerMap.D,id: "D"},
],
},
};
- 自定义指令,主要是用于控制不同权限的按钮
import { premissionConfig } from "@/utils/premissionConfig";
let usersPermissions: string[] = [];
usersPermissions = premissionConfig[import.meta.env.MODE].actionList;
const permission = {
mounted(el: any, binding: any, vnode: any) {
const { value } = binding;
const exit = usersPermissions.some((v) => {
return v.indexOf(value) !== -1;
});
if (!exit) {
el.parentNode && el.parentNode.removeChild(el);
}
},
};
const directivesList: any = {
permission, // 挂载
};
const directives = {
install: function (app: any) {
Object.keys(directivesList).forEach((key) => {
app.directive(key, directivesList[key]); // 注册
});
},
};
export default directives;
- 注册指令
import { createApp } from "vue";
import App from "./App.vue";
import directives from "@/directives/permission";
const app = createApp(App);
app.use(Directives)
❓如何使用
- 菜单
import { premissionConfig, MenuList } from "@/utils/premissionConfig";
const menuList: Ref<MenuList[]> = ref([]);
menuList.value = premissionConfig[import.meta.env.MODE].menuList;
- 按钮或功能模块(使用v-permission不显示该按钮或功能)
<el-button icon="DeleteFilled" @click="xxx" v-permission="['delete']">删除</el-button>
🏢使用场景
- 特定情况下,用户权限的服务器不在统一地方,需要分开运行。
- 同一套代码,针对不同客户交付不同功能,减少重复性新开项目。