feat: mock路由数据,整体路由逻辑调整,包括:生成、加载、跳转
This commit is contained in:
parent
1c27fab1b2
commit
32fd8caa50
@ -4,7 +4,6 @@ import { Message } from "@arco-design/web-vue";
|
||||
|
||||
// 是否开启本地mock
|
||||
const MOCK_FLAG = import.meta.env.VITE_APP_OPEN_MOCK === "true";
|
||||
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
baseURL: MOCK_FLAG ? "" : "/api"
|
||||
@ -14,9 +13,13 @@ service.interceptors.request.use(
|
||||
function (config: any) {
|
||||
// 发送请求之前做什么
|
||||
// 获取token鉴权
|
||||
if (localStorage.getItem("AdminToken")) {
|
||||
let userInfo: any = {};
|
||||
if (localStorage.getItem("user-info")) {
|
||||
userInfo = JSON.parse(localStorage.getItem("user-info") as string);
|
||||
}
|
||||
if (userInfo?.AdminToken) {
|
||||
// 有token,在请求头中携带token
|
||||
config.headers.Authorization = localStorage.getItem("AdminToken");
|
||||
config.headers.Authorization = userInfo.AdminToken;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
|
||||
9
src/api/modules/system/index.ts
Normal file
9
src/api/modules/system/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import axios from "@/api";
|
||||
|
||||
// 获取菜单数据
|
||||
export const getMenuListAPI = () => {
|
||||
return axios({
|
||||
url: "/mock/menu/list",
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
@ -9,12 +9,10 @@ export const loginAPI = (data: any) => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 获取用户信息
|
||||
export const getUserInfoAPI = () => {
|
||||
return axios({
|
||||
url: "/mock/user/info",
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
return axios({
|
||||
url: "/mock/user/info",
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import pinia from "@/store/index";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
/**
|
||||
* 路由处理hooks,内置多种路由处理场景
|
||||
* @returns 路由方法
|
||||
@ -12,7 +12,7 @@ export const useRoutingMethod = () => {
|
||||
* @returns 查找到的路由,undefined则表示未找到
|
||||
*/
|
||||
const findLinearArray = (key: string) => {
|
||||
const routerStore = useRoutesListStore(pinia);
|
||||
const routerStore = useRoutesConfigStore(pinia);
|
||||
const { routeList } = storeToRefs(routerStore);
|
||||
return routeList.value.find((item: Menu.MenuOptions) => item.name == key);
|
||||
};
|
||||
@ -23,7 +23,7 @@ export const useRoutingMethod = () => {
|
||||
* @returns 查找到的路由,undefined则表示未找到
|
||||
*/
|
||||
const findTagsList = (key: string) => {
|
||||
const routerStore = useRoutesListStore(pinia);
|
||||
const routerStore = useRoutesConfigStore(pinia);
|
||||
const { tabsList } = storeToRefs(routerStore);
|
||||
return tabsList.value.find((item: Menu.MenuOptions) => item.name == key);
|
||||
};
|
||||
|
||||
@ -12,10 +12,10 @@ import Logo from "@/layout/components/Logo/index.vue";
|
||||
import Menu from "@/layout/components/Menu/index.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
const themeStore = useThemeConfig();
|
||||
const { collapsed, asideDark } = storeToRefs(themeStore);
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const { routeTree } = storeToRefs(routerStore);
|
||||
</script>
|
||||
|
||||
|
||||
@ -62,11 +62,11 @@
|
||||
<script setup lang="ts">
|
||||
import PickColors from "vue-pick-colors";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { currentlyRoute } from "@/router/route-output";
|
||||
const themeStore = useThemeConfig();
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const {
|
||||
collapsed,
|
||||
isAccordion,
|
||||
|
||||
@ -17,10 +17,10 @@
|
||||
import Tabs from "@/layout/components/Tabs/index.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
const themeStore = useThemeConfig();
|
||||
let { refreshPage, isTabs, watermark, watermarkStyle, watermarkRotate, watermarkGap } = storeToRefs(themeStore);
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const { cacheRoutes } = storeToRefs(routerStore);
|
||||
|
||||
// 水印配置
|
||||
|
||||
@ -18,10 +18,10 @@
|
||||
import MenuItem from "@/layout/components/Menu/menu-item.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
const router = useRouter();
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const { currentRoute } = storeToRefs(routerStore);
|
||||
const themeStore = useThemeConfig();
|
||||
const { collapsed, isAccordion, layoutType, asideDark } = storeToRefs(themeStore);
|
||||
|
||||
@ -56,11 +56,11 @@
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from "vue-router";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
const router = useRouter();
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const { tabsList, currentRoute } = storeToRefs(routerStore);
|
||||
|
||||
// 点击标签页,如果标签页存在,则跳转
|
||||
|
||||
@ -47,13 +47,13 @@ import Footer from "@/layout/components/Footer/index.vue";
|
||||
import MenuItem from "@/layout/components/Menu/menu-item.vue";
|
||||
import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useMenuMethod } from "@/hooks/useMenuMethod";
|
||||
defineOptions({ name: "LayoutHead" });
|
||||
const router = useRouter();
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const themeStore = useThemeConfig();
|
||||
const { routeTree, currentRoute } = storeToRefs(routerStore);
|
||||
const { isFooter, language } = storeToRefs(themeStore);
|
||||
|
||||
@ -49,7 +49,7 @@ import Footer from "@/layout/components/Footer/index.vue";
|
||||
import Menu from "@/layout/components/Menu/index.vue";
|
||||
import HeaderRight from "@/layout/components/Header/components/header-right/index.vue";
|
||||
import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
@ -57,7 +57,7 @@ import { useMenuMethod } from "@/hooks/useMenuMethod";
|
||||
defineOptions({ name: "LayoutMixing" });
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const routerStore = useRoutesListStore();
|
||||
const routerStore = useRoutesConfigStore();
|
||||
const themeStore = useThemeConfig();
|
||||
const { isFooter, collapsed, asideDark, language } = storeToRefs(themeStore);
|
||||
const { routeTree } = storeToRefs(routerStore);
|
||||
|
||||
1088
src/mock/_data/system_menu.ts
Normal file
1088
src/mock/_data/system_menu.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,8 @@ import { createProdMockServer } from "vite-plugin-mock/es/createProdMockServer";
|
||||
|
||||
import testModule from "./test/index";
|
||||
import userModule from "./user/index";
|
||||
// import tableModule from './person/index'
|
||||
// import systemModule from './system/index'
|
||||
// import fileModule from './file/index'
|
||||
// import cateModule from './cate/index'
|
||||
// import areaModule from './area/index'
|
||||
import systemModule from "./system/index";
|
||||
|
||||
export function setupProdMockServer() {
|
||||
createProdMockServer([...testModule, ...userModule]);
|
||||
createProdMockServer([...testModule, ...userModule, ...systemModule]);
|
||||
}
|
||||
|
||||
3
src/mock/system/index.ts
Normal file
3
src/mock/system/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import menu from "./menu";
|
||||
|
||||
export default [...menu];
|
||||
95
src/mock/system/menu.ts
Normal file
95
src/mock/system/menu.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import type { MockMethod } from "vite-plugin-mock";
|
||||
import { resultSuccess, resultError } from "../_utils";
|
||||
import systemMenu from "../_data/system_menu";
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* 后端TODO
|
||||
* 1、根据token判断角色
|
||||
* 2、根据角色过滤权限树
|
||||
* 3、路由树排序
|
||||
* 4、返回路由树
|
||||
*
|
||||
* 前端TODO
|
||||
* 1、将模块设置为真实模块
|
||||
* 2、存储路由树,用于生成菜单
|
||||
* 3、根据树生成一维路由数组
|
||||
* 4、动态添加路由,设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
||||
* 5、动态添加路由
|
||||
* 6、缓存一维路由
|
||||
*/
|
||||
|
||||
// post请求body,get请求query
|
||||
export default [
|
||||
{
|
||||
url: "/mock/menu/list",
|
||||
method: "get",
|
||||
timeout: 300,
|
||||
response: ({ headers }: any) => {
|
||||
let token = headers.authorization;
|
||||
// 这里模拟两个角色,admin、common
|
||||
let userRoles = token === "Admin-Token" ? ["admin"] : ["common"];
|
||||
systemMenu[0].children = treeSort(filterByRole(systemMenu[0].children, userRoles));
|
||||
return resultSuccess(systemMenu);
|
||||
}
|
||||
}
|
||||
] as MockMethod[];
|
||||
|
||||
/**
|
||||
* 路由树递归排序
|
||||
* 1、先给当前层排序
|
||||
* 2、若当前层有children则递归排序
|
||||
* @param {array} tree 根据角色权限过滤后的路由树
|
||||
* @returns 返回排序之后的树
|
||||
*/
|
||||
export const treeSort = (tree: Menu.MenuOptions[]) => {
|
||||
if (!tree || tree.length == 0) return [];
|
||||
tree.sort((a: Menu.MenuOptions, b: Menu.MenuOptions) => {
|
||||
// a和b都是undefined则相等
|
||||
if (a.meta.sort != 0 && !a.meta.sort && b.meta.sort != 0 && !b.meta.sort) {
|
||||
return 0;
|
||||
}
|
||||
// a是undefined则a被排在b之后
|
||||
if (a.meta.sort != 0 && !a.meta.sort) return 1;
|
||||
// b是undefined则b被排在a之后
|
||||
if (b.meta.sort != 0 && !b.meta.sort) return -1;
|
||||
return a.meta.sort - b.meta.sort;
|
||||
});
|
||||
|
||||
// 深层递归
|
||||
return tree.map((item: any) => {
|
||||
if (item?.children?.length > 0) {
|
||||
item.children = treeSort(item.children);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 过滤路由树,返回有权限的树
|
||||
* 1、先过滤停用的菜单,该菜单是不可访问的,直接去掉
|
||||
* 2、根据角色权限过滤原始路由树
|
||||
* @param {array} tree 根据角色权限过滤原始路由树
|
||||
* @returns 返回有权限的树
|
||||
*/
|
||||
export const filterByRole = (tree: any, userRoles: Array<string>) => {
|
||||
return tree.filter((item: any) => {
|
||||
// 过滤角色权限
|
||||
if (item?.meta?.roles) {
|
||||
if (!roleBase(item.meta.roles, userRoles)) return false;
|
||||
}
|
||||
// 过滤是否禁用
|
||||
if (item?.meta?.disable) return false;
|
||||
if (item.children) item.children = filterByRole(item.children, userRoles);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 校验该角色是否有路由权限
|
||||
* @param {array} roles 路由的角色权限
|
||||
* @returns 是否有权限 true是 false否
|
||||
*/
|
||||
export const roleBase = (roles: Array<string>, userRoles: Array<string>) => {
|
||||
return userRoles.some((item: string) => roles.includes(item));
|
||||
};
|
||||
@ -10,8 +10,10 @@ export default [
|
||||
response: ({ body }) => {
|
||||
let { username, password } = body;
|
||||
if (username === "admin" && password === "123456") {
|
||||
// 请求成功返回token
|
||||
return resultSuccess({ token: "Your-Token" });
|
||||
return resultSuccess({ token: "Admin-Token" });
|
||||
}
|
||||
if(username === "common" && password === "123456"){
|
||||
return resultSuccess({ token: "Common-Token" });
|
||||
}
|
||||
return resultError(null, "账号或者密码错误", 500);
|
||||
}
|
||||
|
||||
@ -2,11 +2,12 @@ import NProgress from "@/config/nprogress";
|
||||
import pinia from "@/store/index";
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import { staticRoutes, notFoundAndNoPower } from "@/router/route.ts";
|
||||
import { initSetRouter, currentlyRoute } from "@/router/route-output";
|
||||
import { currentlyRoute } from "@/router/route-output";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { loadingPage } from "@/utils/loading-page";
|
||||
|
||||
/**
|
||||
* 创建vue的路由示例
|
||||
@ -55,7 +56,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
currentlyRoute(to.name as string);
|
||||
} else {
|
||||
// 4、去非登录页,有token,校验是否动态添加过路由,添加过则放行,未添加则执行路由初始化
|
||||
const routeStore = useRoutesListStore(pinia);
|
||||
const routeStore = useRoutesConfigStore(pinia);
|
||||
const { routeTree } = storeToRefs(routeStore);
|
||||
|
||||
// 获取外链路由的处理函数
|
||||
@ -66,7 +67,8 @@ router.beforeEach(async (to, from, next) => {
|
||||
// 如果缓存的路由是0,则说明未动态添加路由,先添加再跳转
|
||||
// 解决刷新页面404的问题
|
||||
if (routeTree.value.length == 0) {
|
||||
await initSetRouter();
|
||||
loadingPage.start();
|
||||
await routeStore.initSetRouter();
|
||||
// 处理外链跳转
|
||||
openExternalLinks(to);
|
||||
// 处理完重新跳转
|
||||
|
||||
@ -1,51 +1,10 @@
|
||||
import pinia from "@/store/index";
|
||||
import router from "@/router/index.ts";
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
import { dynamicRoutes } from "@/router/route";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { deepClone, arrayFlattened } from "@/utils/index";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { loadingPage } from "@/utils/loading-page";
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* 1、过滤有权限的路由树并存入store,用于菜单生成
|
||||
* 2、根据路由树生成一维数组
|
||||
* 3、设置完整的路由,顶层路由 + 一维路由数组,addRoute动态添加路由,KeepAlive支持二级路由缓存
|
||||
*/
|
||||
export async function initSetRouter() {
|
||||
// 初始化路由,渲染loading
|
||||
loadingPage.start();
|
||||
const store = useRoutesListStore(pinia);
|
||||
// 根据角色权限过滤树并将其排序
|
||||
const originTree: RouteRecordRaw[] = deepClone(dynamicRoutes);
|
||||
let filteredTree = treeSort(filterByRole(originTree[0].children));
|
||||
await store.setRouteTree(filteredTree);
|
||||
// 根据树生成一维路由数组
|
||||
const flattenedArray = linearArray(filteredTree);
|
||||
// 设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
||||
const addBeforeTree = originTree.map(item => {
|
||||
if (flattenedArray.length > 0) item.redirect = flattenedArray[0].path;
|
||||
item.children = flattenedArray;
|
||||
return item;
|
||||
});
|
||||
// 动态添加路由
|
||||
addBeforeTree.forEach((route: RouteRecordRaw) => router.addRoute(route));
|
||||
// 设置一维路由
|
||||
setRouting(flattenedArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置有访问权限的一维路由数组
|
||||
* @param {array} flattenedArray 一维路由数组
|
||||
*/
|
||||
export function setRouting(flattenedArray: any) {
|
||||
const store = useRoutesListStore(pinia);
|
||||
store.setRouteList(flattenedArray); // 缓存一维路由
|
||||
}
|
||||
import Layout from "@/layout/index.vue";
|
||||
|
||||
/**
|
||||
* 路由树转一维数组
|
||||
@ -57,67 +16,6 @@ export function linearArray(tree: any) {
|
||||
return arrayFlattened(nodes, "children");
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤路由树,返回有权限的树
|
||||
* 1、先过滤停用的菜单,该菜单是不可访问的,直接去掉
|
||||
* 2、根据角色权限过滤原始路由树
|
||||
* @param {array} tree 根据角色权限过滤原始路由树
|
||||
* @returns 返回有权限的树
|
||||
*/
|
||||
export const filterByRole = (tree: any) => {
|
||||
return tree.filter((item: any) => {
|
||||
// 过滤角色权限
|
||||
if (item?.meta?.roles) {
|
||||
if (!roleBase(item.meta.roles)) return false;
|
||||
}
|
||||
// 过滤是否禁用
|
||||
if (item?.meta?.disable) return false;
|
||||
if (item.children) item.children = filterByRole(item.children);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 路由树递归排序
|
||||
* 1、先给当前层排序
|
||||
* 2、若当前层有children则递归排序
|
||||
* @param {array} tree 根据角色权限过滤后的路由树
|
||||
* @returns 返回排序之后的树
|
||||
*/
|
||||
export const treeSort = (tree: Menu.MenuOptions[]) => {
|
||||
if (!tree || tree.length == 0) return [];
|
||||
tree.sort((a: Menu.MenuOptions, b: Menu.MenuOptions) => {
|
||||
// a和b都是undefined则相等
|
||||
if (a.meta.sort != 0 && !a.meta.sort && b.meta.sort != 0 && !b.meta.sort) {
|
||||
return 0;
|
||||
}
|
||||
// a是undefined则a被排在b之后
|
||||
if (a.meta.sort != 0 && !a.meta.sort) return 1;
|
||||
// b是undefined则b被排在a之后
|
||||
if (b.meta.sort != 0 && !b.meta.sort) return -1;
|
||||
return a.meta.sort - b.meta.sort;
|
||||
});
|
||||
|
||||
// 深层递归
|
||||
return tree.map((item: any) => {
|
||||
if (item?.children?.length > 0) {
|
||||
item.children = treeSort(item.children);
|
||||
}
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 校验该角色是否有路由权限
|
||||
* @param {array} roles 路由的角色权限
|
||||
* @returns 是否有权限 true是 false否
|
||||
*/
|
||||
export const roleBase = (roles: Array<string>) => {
|
||||
const store = useUserInfoStore(pinia);
|
||||
const { account } = storeToRefs(store);
|
||||
return account.value.roles.some((item: string) => roles.includes(item));
|
||||
};
|
||||
|
||||
/**
|
||||
* 统一处理所有的路由跳转:当前路由高亮、tabs栏数据
|
||||
* 处理项目内跳转,存入当前跳转路由和tabs标签栏数据
|
||||
@ -127,7 +25,7 @@ export const roleBase = (roles: Array<string>) => {
|
||||
export const currentlyRoute = (name: string) => {
|
||||
const themeStore = useThemeConfig();
|
||||
const { isTabs } = storeToRefs(themeStore);
|
||||
const store = useRoutesListStore(pinia);
|
||||
const store = useRoutesConfigStore(pinia);
|
||||
const { tabsList, routeList } = storeToRefs(store);
|
||||
// tabs无数据则默认添加首页
|
||||
if (tabsList.value.length == 0 && routeList.value.length != 0) {
|
||||
@ -149,3 +47,46 @@ export const currentlyRoute = (name: string) => {
|
||||
if (!find.meta.keepAlive || !isTabs.value) return;
|
||||
store.setRouteNames(find.name); // 缓存路由name
|
||||
};
|
||||
|
||||
/**
|
||||
* 模块替换,深层递归,对所有的路由中符合条件的模块进行转换
|
||||
* @param {array} tree 过滤角色权限后的树
|
||||
*/
|
||||
export const moduleReplacement = (tree: any) => {
|
||||
if (tree?.length == 0) return [];
|
||||
tree.map((item: any) => {
|
||||
// 模块匹配以及转换
|
||||
moduleMatch(item);
|
||||
if (item?.children?.length > 0) {
|
||||
item.children = moduleReplacement(item.children);
|
||||
}
|
||||
});
|
||||
return tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* 模块匹配
|
||||
* 1、导入 views 目录及其子目录下的所有 .vue 文件。
|
||||
* 2、匹配顶层layout,替换真实模块,layout为应用的基础结构
|
||||
* 3、匹配views下的所有文件路径,将模块转换为按需引入的真实模块
|
||||
* 4、未匹配上,不做处理
|
||||
*/
|
||||
// 匹配views里面所有的.vue文件
|
||||
const modules = import.meta.glob("@/views/**/*.vue");
|
||||
export const moduleMatch = (item: any) => {
|
||||
// 若是layout,则直接给予顶层layout
|
||||
if (item.component === "layout") {
|
||||
// 布局组件是应用的基础结构,在应用启动时就需要被加载,因此不需要按需引入
|
||||
return (item.component = Layout);
|
||||
}
|
||||
// 其它情况下,匹配每个views文件夹下的文件路径
|
||||
for (const key in modules) {
|
||||
const dir = key.split("views/")[1].replace(".vue", "");
|
||||
// 若匹配上,则替换真实模块
|
||||
if (item.component === dir) {
|
||||
// 按需引入modules
|
||||
// 将模块的导入操作和实际使用操作解耦,使得我们可以在需要的时候才执行导入操作
|
||||
item.component = () => modules[key]();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
import router from "@/router/index.ts";
|
||||
import { RouteRecordRaw } from "vue-router";
|
||||
import { getMenuListAPI } from "@/api/modules/system/index";
|
||||
import { moduleReplacement, linearArray } from "@/router/route-output";
|
||||
/**
|
||||
* 路由列表
|
||||
* @methods setRouteTree 设置路由树
|
||||
* @methods setRoutesList 设置路由一维数据
|
||||
* @methods setRouteNames 设置路由名称集合
|
||||
* @methods setTabs 添加tabs标签页
|
||||
* @methods setCurrentRoute 设置系统内的当前路由
|
||||
* @methods removeTabsList 删除tabs页的指定路由
|
||||
* @methods removeRouteName 删除缓存路由名,用于取消页面缓存,单个删除
|
||||
* @methods removeRouteNames 删除缓存路由名,用于取消页面缓存,批量删除
|
||||
* @methods initSetRouter 路由初始化
|
||||
*/
|
||||
export const useRoutesListStore = defineStore("route-list", {
|
||||
export const useRoutesConfigStore = defineStore("route-config", {
|
||||
state: (): any => ({
|
||||
routeTree: [], // 有访问权限的路由树
|
||||
routeList: [], // 有访问权限的一维路由数组
|
||||
@ -18,20 +22,6 @@ export const useRoutesListStore = defineStore("route-list", {
|
||||
currentRoute: {} // 当前路由
|
||||
}),
|
||||
actions: {
|
||||
/**
|
||||
* 设置有访问权限的路由树
|
||||
* @param {Array} data 一维路由数组
|
||||
*/
|
||||
async setRouteTree(data: Menu.MenuOptions) {
|
||||
this.routeTree = data;
|
||||
},
|
||||
/**
|
||||
* 设置有访问权限的一维路由数组
|
||||
* @param {Array} data 一维路由数组
|
||||
*/
|
||||
setRouteList(data: any) {
|
||||
this.routeList = data;
|
||||
},
|
||||
/**
|
||||
* 设置可缓存路由的路由名
|
||||
* @param {string} name 路由名
|
||||
@ -65,6 +55,7 @@ export const useRoutesListStore = defineStore("route-list", {
|
||||
*/
|
||||
removeTabsList(key: string) {
|
||||
const index = this.tabsList.findIndex((item: Menu.MenuOptions) => item.name === key);
|
||||
if (this.tabsList[index].meta.affix) return;
|
||||
if (index === -1) return;
|
||||
this.tabsList.splice(index, 1);
|
||||
},
|
||||
@ -83,6 +74,32 @@ export const useRoutesListStore = defineStore("route-list", {
|
||||
*/
|
||||
removeRouteNames(list: Array<string>) {
|
||||
this.cacheRoutes = this.cacheRoutes.filter((item: string) => !list.includes(item));
|
||||
},
|
||||
/**
|
||||
* 路由初始化
|
||||
* 1、将模块设置为真实模块
|
||||
* 2、存储路由树,用于生成菜单
|
||||
* 3、根据树生成一维路由数组
|
||||
* 4、动态添加路由,设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
||||
* 5、动态添加路由
|
||||
* 6、缓存一维路由
|
||||
*/
|
||||
async initSetRouter() {
|
||||
// 1、获取过滤角色权限后的树,后端做排序处理
|
||||
let { data } = await getMenuListAPI();
|
||||
// 2、将模块设置为真实模块
|
||||
let tree = moduleReplacement(data);
|
||||
// 3、存储路由树,用于生成菜单
|
||||
this.routeTree = tree[0].children;
|
||||
// 4、根据树生成一维路由数组
|
||||
tree[0].children = linearArray(tree[0].children);
|
||||
// 5、设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
||||
tree[0].redirect = tree[0].children[0].path;
|
||||
// 6、动态添加路由
|
||||
tree.forEach((route: RouteRecordRaw) => router.addRoute(route));
|
||||
console.log("最终路由", tree);
|
||||
// 7、缓存一维路由
|
||||
this.routeList = tree[0].children;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -42,7 +42,6 @@ import { Message } from "@arco-design/web-vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import { loginAPI, getUserInfoAPI } from "@/api/modules/user/index";
|
||||
|
||||
const router = useRouter();
|
||||
const form = ref({
|
||||
username: "admin",
|
||||
@ -86,7 +85,7 @@ const onSubmit = async ({ errors }: any) => {
|
||||
if (errors) return;
|
||||
let res = await loginAPI(form.value);
|
||||
let stores = useUserInfoStore();
|
||||
stores.setToken(res.data.token);
|
||||
await stores.setToken(res.data.token);
|
||||
let account = await getUserInfoAPI();
|
||||
stores.setAccount(account.data); // 存储用户信息
|
||||
Message.success("登录成功");
|
||||
|
||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@ -17,3 +17,4 @@ declare module "nprogress";
|
||||
declare module "@wangeditor/editor-for-vue";
|
||||
declare module "@/directives/modules/custom";
|
||||
declare module "mockjs";
|
||||
declare module "@/store/modules/route-config";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user