页面设计
权限管理设计
布局设置
accessEnum.ts
const ACCESS_ENUM = {
NOT_LOGIN: "notLogin",
USER: "user",
ADMIN: "admin",
};
export default ACCESS_ENUM;
checkAccess.ts
这个用于检查权限,参数是传递过来跳转路由需要的权限
然后这里面获取登录用户的权限,两个对比
例如这个需要权限
{
path: "/image",
name: "图片展示",
meta: {
hidenInMenu: true,
},
component: ImageView,
},
有的跳转不需要权限
{
path: "/",
name: "首页",
component: HomeView,
},
用这个获取需要的权限
//存在就获取,不存在就是undefined
const needAccess = (to.meta?.access as string) ?? ACCESS_ENUM.NOT_LOGIN;
const needAccess:这是声明一个常量变量 needAccess。
to.meta?.access:这是 Vue Router 中路由导航守卫的一个特性。to 是即将跳转到的目标路由对象,meta 是路由元信息对象,?. 是可选链操作符,用于判断 to.meta 是否存在,如果存在,则继续访问 access 属性。
as string:这是 TypeScript 的类型断言,将 to.meta?.access 强制转换为字符串类型。这里假设 access 属性是一个字符串,但由于可选链操作符的使用,它可能为空。
?? ACCESS_ENUM.NOT_LOGIN:这是空值合并运算符 (nullish coalescing operator),用于判断 to.meta?.access as string 是否为 null 或 undefined,如果是,则返回 ACCESS_ENUM.NOT_LOGIN。空值合并运算符用于提供默认值,即如果 to.meta?.access 为空,则将 needAccess 赋值为 ACCESS_ENUM.NOT_LOGIN。
总的来说,这行代码的含义是:如果目标路由对象 to 的元信息中存在 access 属性,则将其转换为字符串并赋值给 needAccess 变量;如果不存在或为空,则将 needAccess 赋值为 ACCESS_ENUM.NOT_LOGIN。
/*
* 检查权限(判断当前登录用户是否具有某个权限)
* logingUSER 当前登录用户
* needAccess 需要有的权限
* boolean 有无权限
* */
import ACCESS_ENUM from "@/access/accessEnum";
/**
* 检查权限(判断当前登录用户是否具有某个权限)
* @param loginUser 当前登录用户
* @param needAccess 需要有的权限
* @return boolean 有无权限
*/
const checkAccess = (loginUser: any, needAccess = ACCESS_ENUM.NOT_LOGIN) => {
// 获取当前登录用户具有的权限(如果没有 loginUser,则表示未登录),和这个路由跳转权限对比
const loginUserAccess = loginUser?.userRole ?? ACCESS_ENUM.NOT_LOGIN;
//这个权限是不需要登录的,直接返回
if (needAccess === ACCESS_ENUM.NOT_LOGIN) {
return true;
}
// 如果用户登录才能访问,这个是登录了,需要用户权限,但是登录的用户没有用户权限
if (needAccess === ACCESS_ENUM.USER) {
// 如果用户没登录,那么表示无权限,查看登录用户是否已经登录了
//这个是登录用户的权限,需要的权限是user,但是登录用户的权限显示ACCESS_ENUM.NOT_LOGIN,返回跳转到无权限页面
if (loginUserAccess === ACCESS_ENUM.NOT_LOGIN) {
return false;
}
}
// 如果需要管理员权限
if (needAccess === ACCESS_ENUM.ADMIN) {
// 如果不为管理员,表示无权限
//需要管理员权限
if (loginUserAccess !== ACCESS_ENUM.ADMIN) {
return false;
}
}
return true;
};
export default checkAccess;
indes.ts
这个是路由守卫,跳转路由触发,然后检查权限
import store from "@/store";
import ACCESS_ENUM from "@/access/accessEnum";
import checkAccess from "@/access/checkAccess";
import router from "@/router";
router.beforeEach(async (to, from, next) => {
// alert("xxxx13" + "45");
console.log("登录用户信息", store.state.user.loginUser);
console.log(to.matched);
const loginUser = store.state.user.loginUser;
if (!loginUser || !loginUser.userRole) {
//用来触发action方法
await store.dispatch("user/getLoginUser");
}
//不需要登录就是ACCESS_ENUM.NOT_LOGIN,这个从meta取的
const needAccess = (to.meta?.access as string) ?? ACCESS_ENUM.NOT_LOGIN;
//要跳转的页面必须登录,需要判断权限
if (needAccess !== ACCESS_ENUM.NOT_LOGIN) {
//如果没有登录,跳转到登录页面
//如果没有登录!loginUser就是ture
if (!loginUser) {
next(`/user/login?redirect=${to.fullPath}`);
return;
}
//如果已经登录了,但是权限不足,那么跳转到无权限界面
if (!checkAccess(loginUser, needAccess)) {
next("/noAuth");
return;
}
//仅管理员可见,判断当前用户是否有权限
// if (to.meta?.access === "canAdmin") {
// if (store.state.user.loginUser?.role === "admin") {
// next("/noAuth");
// return;
// }
// }
}
//不需要登录直接跳转
next();
console.log(to);
});
设计全局对象
index.ts
import { createStore } from "vuex";
import user from "./user";
export default createStore({
mutations: {},
actions: {},
modules: {
user,
},
});
user.ts
import { StoreOptions } from "vuex";
import { UserControllerService } from "../../generated";
import ACCESS_ENUM from "@/access/accessEnum";
export default {
namespaced: true,
state: () => ({
//存储用户信息,这里是存储一个对象信息
loginUser: {
userName: "未登录",
role: "notLogin",
},
}),
actions: {
// getLoginUser({ commit, state }, payload) {
// commit("updateUser", { userName: "鱼皮" });
// },
//payload的作用
async getLoginUser({ commit, state }, payload) {
const res = await UserControllerService.getLoginUserUsingGet();
// console.log("xxxxxxxxxxxxxxxxxxxx");
console.log(res);
if (res.code === 0) {
commit("updateUser", res.data);
} else {
commit("updateUser", {
...state.loginUser,
userRole: ACCESS_ENUM.NOT_LOGIN,
});
}
},
},
mutations: {
updateUser(state, payload) {
console.log("payload");
console.log(payload);
state.loginUser = payload;
},
},
} as StoreOptions<any>;
路由
index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import { routes } from "@/router/routes";
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;
routes.ts
import { RouteRecordRaw } from "vue-router";
import HomeView from "@/views/HomeView.vue";
import NoAuth from "@/views/NoAuth.vue";
import AdminView from "@/views/AdminView.vue";
import ImageView from "@/views/ImageView.vue";
import UserLoginView from "@/views/user/UserLoginView.vue";
import UserRegisterView from "@/views/user/UserRegisterView.vue";
import AboutView from "@/views/AboutView.vue";
import UserLayout from "@/layouts/UserLayout.vue";
export const routes: Array<RouteRecordRaw> = [
{
path: "/user",
name: "用户",
component: UserLayout,
children: [
{
path: "login",
name: "用户登录",
component: UserLoginView,
},
{
path: "register",
name: "用户注册",
component: UserRegisterView,
},
],
},
{
path: "/",
name: "首页",
component: HomeView,
},
{
path: "/noAuth",
name: "无权限",
component: NoAuth,
},
{
path: "/image",
name: "图片展示",
meta: {
hidenInMenu: true,
},
component: ImageView,
},
{
path: "/admin",
name: "管理员可见",
component: AdminView,
meta: {
access: "canAdmin",
},
},
{
path: "/about",
name: "about",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
meta: {
hidenInMenu: true,
},
component: AboutView,
// component: () =>
// import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
},
];