feat: 动态路由逻辑更改,添加id和parendId用于生成路由树(结构为01-01-01),mock不再返回顶层路由,顶层layout路由改为直接静态导入
This commit is contained in:
parent
1f7c398c50
commit
b8e0497b1f
@ -1,4 +1,2 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
. "$(dirname -- "$0")/husky.sh"
|
. "${0%/*}/h"
|
||||||
|
|
||||||
npx --no-install commitlint --edit $1
|
|
||||||
@ -1,4 +1,2 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
. "$(dirname "$0")/husky.sh"
|
. "${0%/*}/h"
|
||||||
|
|
||||||
pnpm run lint:lint-staged
|
|
||||||
32
src/components.d.ts
vendored
32
src/components.d.ts
vendored
@ -5,22 +5,22 @@
|
|||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
declare module "vue" {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
BarcodeDraw: (typeof import("./components/barcode-draw/index.vue"))["default"];
|
BarcodeDraw: typeof import('./components/barcode-draw/index.vue')['default']
|
||||||
CodeView: (typeof import("./components/code-view/index.vue"))["default"];
|
CodeView: typeof import('./components/code-view/index.vue')['default']
|
||||||
ExternalLinkPage: (typeof import("./components/external-link-page/index.vue"))["default"];
|
ExternalLinkPage: typeof import('./components/external-link-page/index.vue')['default']
|
||||||
FillPage: (typeof import("./components/fill-page/index.vue"))["default"];
|
FillPage: typeof import('./components/fill-page/index.vue')['default']
|
||||||
InternalLinkPage: (typeof import("./components/internal-link-page/index.vue"))["default"];
|
InternalLinkPage: typeof import('./components/internal-link-page/index.vue')['default']
|
||||||
LangProvider: (typeof import("./components/lang-provider/index.vue"))["default"];
|
LangProvider: typeof import('./components/lang-provider/index.vue')['default']
|
||||||
MainTransition: (typeof import("./components/main-transition/index.vue"))["default"];
|
MainTransition: typeof import('./components/main-transition/index.vue')['default']
|
||||||
PinyinPro: (typeof import("./components/pinyin-pro/index.vue"))["default"];
|
PinyinPro: typeof import('./components/pinyin-pro/index.vue')['default']
|
||||||
QrcodeDraw: (typeof import("./components/qrcode-draw/index.vue"))["default"];
|
QrcodeDraw: typeof import('./components/qrcode-draw/index.vue')['default']
|
||||||
RouterLink: (typeof import("vue-router"))["RouterLink"];
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: (typeof import("vue-router"))["RouterView"];
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SelectIcon: (typeof import("./components/select-icon/index.vue"))["default"];
|
SelectIcon: typeof import('./components/select-icon/index.vue')['default']
|
||||||
SvgAndIcon: (typeof import("./components/svg-and-icon/index.vue"))["default"];
|
SvgAndIcon: typeof import('./components/svg-and-icon/index.vue')['default']
|
||||||
SvgIcon: (typeof import("./components/svg-icon/index.vue"))["default"];
|
SvgIcon: typeof import('./components/svg-icon/index.vue')['default']
|
||||||
VerifyCode: (typeof import("./components/verify-code/index.vue"))["default"];
|
VerifyCode: typeof import('./components/verify-code/index.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/config/index.ts
Normal file
4
src/config/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// 系统全局配置
|
||||||
|
|
||||||
|
// 首页地址(默认)
|
||||||
|
export const HOME_PATH: string = "/home";
|
||||||
@ -14,10 +14,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||||
|
import { useRoutesConfigStore } from "@/store/modules/route-config";
|
||||||
import { useDevicesSize } from "@/hooks/useDevicesSize";
|
import { useDevicesSize } from "@/hooks/useDevicesSize";
|
||||||
|
import { HOME_PATH } from "@/config/index";
|
||||||
const themeStore = useThemeConfig();
|
const themeStore = useThemeConfig();
|
||||||
const { isBreadcrumb, transitionPage } = storeToRefs(themeStore);
|
const { isBreadcrumb, transitionPage } = storeToRefs(themeStore);
|
||||||
|
const routesConfigStore = useRoutesConfigStore();
|
||||||
|
const { routeList } = storeToRefs(routesConfigStore);
|
||||||
const { isMobile } = useDevicesSize();
|
const { isMobile } = useDevicesSize();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -25,16 +28,17 @@ const router = useRouter();
|
|||||||
/**
|
/**
|
||||||
* 获取面包屑
|
* 获取面包屑
|
||||||
* 根据当前路由信息获取,route.matched可以获取当前路由的所有父级路由信息
|
* 根据当前路由信息获取,route.matched可以获取当前路由的所有父级路由信息
|
||||||
* 如果当前路由是顶层的重定向路由,则只返回当前路由信息(说明当前就是顶层)
|
* 如果当前路由是home路由,则只返回当前路由信息(说明当前就是顶层)
|
||||||
* 否则返回所有父级路由信息,顶层路由重写为首页
|
* 否则返回所有父级路由信息,顶层路由重写为首页
|
||||||
*/
|
*/
|
||||||
const breadcrumb = computed(() => {
|
const breadcrumb = computed(() => {
|
||||||
if (route.path === route.matched[0].redirect) {
|
// 如果是首页则直接返回当前路由信息
|
||||||
return [route];
|
if (route.path === HOME_PATH) return [route];
|
||||||
}
|
|
||||||
|
// 否则返回路径信息
|
||||||
return route.matched.map((item: any) => {
|
return route.matched.map((item: any) => {
|
||||||
if (item.name == "/") {
|
if (item.name == "layout") {
|
||||||
return item.children[0];
|
return routeList.value.find((item: any) => item.path == HOME_PATH);
|
||||||
} else {
|
} else {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
@ -55,7 +59,7 @@ const transition = computed(() => {
|
|||||||
// 面包屑跳转
|
// 面包屑跳转
|
||||||
const onBreadcrumb = (route: any) => {
|
const onBreadcrumb = (route: any) => {
|
||||||
let path = route.redirect || route.path;
|
let path = route.redirect || route.path;
|
||||||
router.replace((path as string) || "");
|
router.replace((path as string) || HOME_PATH);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,8 @@ import systemMenu from "../_data/system_menu";
|
|||||||
* 1、将模块设置为真实模块
|
* 1、将模块设置为真实模块
|
||||||
* 2、存储路由树,用于生成菜单
|
* 2、存储路由树,用于生成菜单
|
||||||
* 3、根据树生成一维路由数组
|
* 3、根据树生成一维路由数组
|
||||||
* 4、动态添加路由,设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
* 4、动态添加路由
|
||||||
* 5、动态添加路由
|
* 5、缓存一维路由
|
||||||
* 6、缓存一维路由
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// post请求body,get请求query
|
// post请求body,get请求query
|
||||||
@ -30,8 +29,7 @@ export default [
|
|||||||
// 这里模拟两个角色,admin、common
|
// 这里模拟两个角色,admin、common
|
||||||
let userRoles = token === "Admin-Token" ? ["admin"] : ["common"];
|
let userRoles = token === "Admin-Token" ? ["admin"] : ["common"];
|
||||||
const originTree: any = deepClone(systemMenu);
|
const originTree: any = deepClone(systemMenu);
|
||||||
originTree[0].children = treeSort(filterByRole(originTree[0].children, userRoles));
|
return resultSuccess(treeSort(filterByRole(originTree, userRoles)));
|
||||||
return resultSuccess(originTree);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
] as MockMethod[];
|
] as MockMethod[];
|
||||||
|
|||||||
@ -17,10 +17,10 @@ const router = createRouter({
|
|||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
/**
|
/**
|
||||||
* 设置静态路由,其它的路由通过addRoute动态添加
|
* 设置静态路由,其它的路由通过addRoute动态添加
|
||||||
* 1、staticRoutes登录页
|
* 1、staticRoutes登录页、layout页、默认页面('/')
|
||||||
* 2、notFoundAndNoPower 添加默认 404、401界面,防止提示 No match found for location with path 'xxx'
|
* 2、notFoundAndNoPower 添加默认 401、500界面,防止提示 No match found for location with path 'xxx'
|
||||||
* 2、后端控制路由中也需要添加 notFoundAndNoPower 404、401界面
|
* 2、后端控制路由中也需要添加 notFoundAndNoPower 401、500界面
|
||||||
* 静态添加 notFoundAndNoPower 404、401界面将全屏显示
|
* 静态添加 notFoundAndNoPower 401、500界面将全屏显示
|
||||||
* 如果要 notFoundAndNoPower 在layout容器展示,则需要移除静态添加并将其添加到缓存路由树
|
* 如果要 notFoundAndNoPower 在layout容器展示,则需要移除静态添加并将其添加到缓存路由树
|
||||||
*/
|
*/
|
||||||
routes: [...staticRoutes, ...notFoundAndNoPower]
|
routes: [...staticRoutes, ...notFoundAndNoPower]
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { useRoutesConfigStore } from "@/store/modules/route-config";
|
|||||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||||
import { deepClone, arrayFlattened } from "@/utils/index";
|
import { deepClone, arrayFlattened } from "@/utils/index";
|
||||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||||
import Layout from "@/layout/index.vue";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路由树转一维数组
|
* 路由树转一维数组
|
||||||
@ -67,19 +66,13 @@ export const moduleReplacement = (tree: any) => {
|
|||||||
/**
|
/**
|
||||||
* 模块匹配
|
* 模块匹配
|
||||||
* 1、导入 views 目录及其子目录下的所有 .vue 文件。
|
* 1、导入 views 目录及其子目录下的所有 .vue 文件。
|
||||||
* 2、匹配顶层layout,替换真实模块,layout为应用的基础结构
|
* 2、匹配views下的所有文件路径,将模块转换为按需引入的真实模块
|
||||||
* 3、匹配views下的所有文件路径,将模块转换为按需引入的真实模块
|
* 3、未匹配上,不做处理
|
||||||
* 4、未匹配上,不做处理
|
|
||||||
*/
|
*/
|
||||||
// 匹配views里面所有的.vue文件
|
// 匹配views里面所有的.vue文件
|
||||||
const modules = import.meta.glob("@/views/**/*.vue");
|
const modules = import.meta.glob("@/views/**/*.vue");
|
||||||
export const moduleMatch = (item: any) => {
|
export const moduleMatch = (item: any) => {
|
||||||
// 若是layout,则直接给予顶层layout
|
// 匹配每个views文件夹下的文件路径
|
||||||
if (item.component === "layout") {
|
|
||||||
// 布局组件是应用的基础结构,在应用启动时就需要被加载,因此不需要按需引入
|
|
||||||
return (item.component = Layout);
|
|
||||||
}
|
|
||||||
// 其它情况下,匹配每个views文件夹下的文件路径
|
|
||||||
for (const key in modules) {
|
for (const key in modules) {
|
||||||
const dir = key.split("views/")[1].replace(".vue", "");
|
const dir = key.split("views/")[1].replace(".vue", "");
|
||||||
// 若匹配上,则替换真实模块
|
// 若匹配上,则替换真实模块
|
||||||
|
|||||||
@ -1,29 +1,35 @@
|
|||||||
|
import { HOME_PATH } from "@/config/index";
|
||||||
|
import Layout from "@/layout/index.vue";
|
||||||
/**
|
/**
|
||||||
* 路由path路径与文件夹名称相同,找文件可以浏览器地址快速查找,方便定位文件
|
* 路由path路径与文件夹名称相同,找文件可以浏览器地址快速查找,方便定位文件
|
||||||
*
|
*
|
||||||
* 路由meta对象参数,我们通常将属性放到meta对象中
|
* 路由meta对象参数,我们通常将属性放到meta对象中
|
||||||
* meta: {
|
* meta: {
|
||||||
* title: 菜单栏以及 tabsView 栏、菜单搜索名称(国际化)
|
* title: 菜单栏以及 tabsView 栏、菜单搜索名称(国际化)
|
||||||
* hide: 是否隐藏此路由,不会显示在菜单树,可以访问
|
* hide: 是否隐藏此路由,不会显示在菜单树,可以访问
|
||||||
* disable: 是否停用,不会显示在菜单树,且不可访问
|
* disable: 是否停用,不会显示在菜单树,且不可访问
|
||||||
* keepAlive: 是否缓存组件状态
|
* keepAlive: 是否缓存组件状态
|
||||||
* affix: 是否固定在 tabsView 栏上
|
* affix: 是否固定在 tabsView 栏上
|
||||||
* link: 是否是超链接菜单,开启外链条件:1、 link:链接地址不为空 2、iframe: false
|
* link: 是否是超链接菜单,开启外链条件:1、 link:链接地址不为空 2、iframe: false
|
||||||
* iframe: 是否内嵌窗口,开启条件:1、iframe:true 2、link:链接地址不为空
|
* iframe: 是否内嵌窗口,开启条件:1、iframe:true 2、link:链接地址不为空
|
||||||
* roles: 当前路由权限表示,取角色管理。路由控制显示、隐藏。 超级管理员:admin;普通角色:common
|
* roles: 当前路由权限表示,取角色管理。路由控制显示、隐藏。 超级管理员:admin;普通角色:common
|
||||||
* icon: 菜单、tabsView 图标等
|
* icon: 菜单、tabsView 图标等
|
||||||
* svgIcon: svg图标
|
* svgIcon: svg图标
|
||||||
* sort: 排序
|
* sort: 菜单顺序
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 静态路由 (默认路由)
|
* 静态路由 (默认路由)
|
||||||
* 此路由不要动,用于做静态路由定向,如果要添加路由,请在 `dynamicRoutes数组` 中添加
|
* 此路由不要动,用于做静态路由定向,如果要添加路由,请在 `layout-children` 中添加
|
||||||
* @description 前端控制路由 直接改 dynamicRoutes 中的路由,后端控制则不需要,请求接口路由数据时,覆盖 dynamicRoutes 第一个顶层 children 的内容(全屏,不包括 lauyout 中的路由出口)
|
* @description 前端控制路由 直接改 mock/_data/system_menu 中的路由,后端控制则不需要
|
||||||
* @returns 返回路由菜单数据
|
* @returns 返回路由菜单数据
|
||||||
*/
|
*/
|
||||||
export const staticRoutes = [
|
export const staticRoutes = [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
redirect: HOME_PATH
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: "/login",
|
||||||
name: "login",
|
name: "login",
|
||||||
@ -31,10 +37,18 @@ export const staticRoutes = [
|
|||||||
meta: {
|
meta: {
|
||||||
title: "login"
|
title: "login"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/layout",
|
||||||
|
name: "layout",
|
||||||
|
redirect: HOME_PATH,
|
||||||
|
component: Layout, // 容器布局-顶层路由
|
||||||
|
// 二级路由-主要渲染页面
|
||||||
|
children: []
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 提示:写在这里的为全屏界面,不建议写在这里
|
* 提示:写在这里的为全屏界面,不建议写在这里非全屏界面,请写在 layout.children 路由数组中
|
||||||
* 非全屏界面,请写在 dynamicRoutes 路由数组中
|
*
|
||||||
*/
|
*/
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -86,9 +86,8 @@ export const routesConfigStore = () => {
|
|||||||
* 2、将模块设置为真实模块
|
* 2、将模块设置为真实模块
|
||||||
* 3、存储路由树,用于生成菜单
|
* 3、存储路由树,用于生成菜单
|
||||||
* 4、根据树生成一维路由数组
|
* 4、根据树生成一维路由数组
|
||||||
* 5、动态添加路由,设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
* 5、动态添加路由
|
||||||
* 6、动态添加路由
|
* 6、缓存一维路由
|
||||||
* 7、缓存一维路由
|
|
||||||
*/
|
*/
|
||||||
async function initSetRouter() {
|
async function initSetRouter() {
|
||||||
// 1、获取过滤角色权限后的树,后端做排序处理
|
// 1、获取过滤角色权限后的树,后端做排序处理
|
||||||
@ -96,15 +95,13 @@ export const routesConfigStore = () => {
|
|||||||
// 2、将模块设置为真实模块
|
// 2、将模块设置为真实模块
|
||||||
let tree = await moduleReplacement(data);
|
let tree = await moduleReplacement(data);
|
||||||
// 3、存储路由树,用于生成菜单
|
// 3、存储路由树,用于生成菜单
|
||||||
routeTree.value = tree[0].children;
|
routeTree.value = tree;
|
||||||
// 4、根据树生成一维路由数组
|
// 4、根据树生成一维路由数组
|
||||||
tree[0].children = linearArray(tree[0].children);
|
tree = linearArray(tree);
|
||||||
// 5、设置完整的路由,二维路由:顶层路由 + 二级的一维路由
|
// 5、动态添加路由
|
||||||
tree[0].redirect = tree[0].children[0].path;
|
tree.forEach((route: any) => router.addRoute("layout", route));
|
||||||
// 6、动态添加路由
|
// 6、缓存一维路由
|
||||||
tree.forEach((route: any) => router.addRoute(route));
|
routeList.value = tree;
|
||||||
// 7、缓存一维路由
|
|
||||||
routeList.value = tree[0].children;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -95,7 +95,7 @@ import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
|
|||||||
import dynamicRoutes from "@/mock/_data/system_menu";
|
import dynamicRoutes from "@/mock/_data/system_menu";
|
||||||
|
|
||||||
const tableData = computed(() => {
|
const tableData = computed(() => {
|
||||||
return dynamicRoutes[0].children;
|
return dynamicRoutes;
|
||||||
});
|
});
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
form: {
|
form: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user