feat: 动态路由逻辑更改,添加id和parendId用于生成路由树(结构为01-01-01),mock不再返回顶层路由,顶层layout路由改为直接静态导入

This commit is contained in:
wangfan 2025-01-24 13:59:49 +08:00
parent 1f7c398c50
commit b8e0497b1f
12 changed files with 1133 additions and 1016 deletions

View File

@ -1,4 +1,2 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/husky.sh"
npx --no-install commitlint --edit $1
. "${0%/*}/h"

View File

@ -1,4 +1,2 @@
#!/usr/bin/env sh
. "$(dirname "$0")/husky.sh"
pnpm run lint:lint-staged
. "${0%/*}/h"

32
src/components.d.ts vendored
View File

@ -5,22 +5,22 @@
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module "vue" {
declare module 'vue' {
export interface GlobalComponents {
BarcodeDraw: (typeof import("./components/barcode-draw/index.vue"))["default"];
CodeView: (typeof import("./components/code-view/index.vue"))["default"];
ExternalLinkPage: (typeof import("./components/external-link-page/index.vue"))["default"];
FillPage: (typeof import("./components/fill-page/index.vue"))["default"];
InternalLinkPage: (typeof import("./components/internal-link-page/index.vue"))["default"];
LangProvider: (typeof import("./components/lang-provider/index.vue"))["default"];
MainTransition: (typeof import("./components/main-transition/index.vue"))["default"];
PinyinPro: (typeof import("./components/pinyin-pro/index.vue"))["default"];
QrcodeDraw: (typeof import("./components/qrcode-draw/index.vue"))["default"];
RouterLink: (typeof import("vue-router"))["RouterLink"];
RouterView: (typeof import("vue-router"))["RouterView"];
SelectIcon: (typeof import("./components/select-icon/index.vue"))["default"];
SvgAndIcon: (typeof import("./components/svg-and-icon/index.vue"))["default"];
SvgIcon: (typeof import("./components/svg-icon/index.vue"))["default"];
VerifyCode: (typeof import("./components/verify-code/index.vue"))["default"];
BarcodeDraw: typeof import('./components/barcode-draw/index.vue')['default']
CodeView: typeof import('./components/code-view/index.vue')['default']
ExternalLinkPage: typeof import('./components/external-link-page/index.vue')['default']
FillPage: typeof import('./components/fill-page/index.vue')['default']
InternalLinkPage: typeof import('./components/internal-link-page/index.vue')['default']
LangProvider: typeof import('./components/lang-provider/index.vue')['default']
MainTransition: typeof import('./components/main-transition/index.vue')['default']
PinyinPro: typeof import('./components/pinyin-pro/index.vue')['default']
QrcodeDraw: typeof import('./components/qrcode-draw/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SelectIcon: typeof import('./components/select-icon/index.vue')['default']
SvgAndIcon: typeof import('./components/svg-and-icon/index.vue')['default']
SvgIcon: typeof import('./components/svg-icon/index.vue')['default']
VerifyCode: typeof import('./components/verify-code/index.vue')['default']
}
}

4
src/config/index.ts Normal file
View File

@ -0,0 +1,4 @@
// 系统全局配置
// 首页地址(默认)
export const HOME_PATH: string = "/home";

View File

@ -14,10 +14,13 @@
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/modules/theme-config";
import { useRoutesConfigStore } from "@/store/modules/route-config";
import { useDevicesSize } from "@/hooks/useDevicesSize";
import { HOME_PATH } from "@/config/index";
const themeStore = useThemeConfig();
const { isBreadcrumb, transitionPage } = storeToRefs(themeStore);
const routesConfigStore = useRoutesConfigStore();
const { routeList } = storeToRefs(routesConfigStore);
const { isMobile } = useDevicesSize();
const route = useRoute();
const router = useRouter();
@ -25,16 +28,17 @@ const router = useRouter();
/**
* 获取面包屑
* 根据当前路由信息获取route.matched可以获取当前路由的所有父级路由信息
* 如果当前路由是顶层的重定向路由则只返回当前路由信息(说明当前就是顶层)
* 如果当前路由是home路由则只返回当前路由信息(说明当前就是顶层)
* 否则返回所有父级路由信息顶层路由重写为首页
*/
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) => {
if (item.name == "/") {
return item.children[0];
if (item.name == "layout") {
return routeList.value.find((item: any) => item.path == HOME_PATH);
} else {
return item;
}
@ -55,7 +59,7 @@ const transition = computed(() => {
//
const onBreadcrumb = (route: any) => {
let path = route.redirect || route.path;
router.replace((path as string) || "");
router.replace((path as string) || HOME_PATH);
};
</script>

View File

@ -27,22 +27,13 @@
/**
*
* layout为框架布局
* layout.children下的路由为menu菜单"一级路由"
* children则是当前菜单的二级菜单
*
* layout.children下的路由为menu菜单
*/
export default [
// layout-二级路由(主要渲染页面)
{
path: "/",
name: "/",
redirect: "/home",
component: "layout", // 容器布局-顶层路由
meta: {
keepAlive: true
},
// 二级路由-主要渲染页面
children: [
{
id: "01",
parentId: "0",
path: "/home",
name: "home",
component: "home/home",
@ -60,6 +51,8 @@ export default [
}
},
{
id: "02",
parentId: "0",
path: "/file",
name: "file",
redirect: "/file/document-library",
@ -77,6 +70,8 @@ export default [
},
children: [
{
id: "0201",
parentId: "02",
path: "/file/document-library",
name: "document-library",
component: "file/document-library/document-library",
@ -96,6 +91,8 @@ export default [
]
},
{
id: "03",
parentId: "0",
path: "/table",
name: "table",
redirect: "/table/common-table",
@ -113,6 +110,8 @@ export default [
},
children: [
{
id: "0301",
parentId: "03",
path: "/table/common-table",
name: "common-table",
component: "table/common-table/common-table",
@ -130,6 +129,8 @@ export default [
}
},
{
id: "0302",
parentId: "03",
path: "/table/custom-table",
name: "custom-table",
component: "table/custom-table/custom-table",
@ -149,6 +150,8 @@ export default [
]
},
{
id: "04",
parentId: "0",
path: "/form",
name: "form",
redirect: "/form/common-form",
@ -166,6 +169,8 @@ export default [
},
children: [
{
id: "0401",
parentId: "04",
path: "/form/common-form",
name: "common-form",
component: "form/common-form/common-form",
@ -183,6 +188,8 @@ export default [
}
},
{
id: "0402",
parentId: "04",
path: "/form/step-form",
name: "step-form",
component: "form/step-form/step-form",
@ -202,6 +209,8 @@ export default [
]
},
{
id: "05",
parentId: "0",
path: "/multilevel",
name: "multilevel",
redirect: "/multilevel/second-1",
@ -219,6 +228,8 @@ export default [
},
children: [
{
id: "0501",
parentId: "05",
path: "/multilevel/second-1",
name: "second-1",
component: "multilevel/second/second-1",
@ -236,6 +247,8 @@ export default [
}
},
{
id: "0502",
parentId: "05",
path: "/multilevel/second-2",
name: "second-2",
redirect: "/multilevel/third-1",
@ -253,6 +266,8 @@ export default [
},
children: [
{
id: "050201",
parentId: "0502",
path: "/multilevel/third-2",
name: "third-2",
component: "multilevel/third/third-2",
@ -270,6 +285,8 @@ export default [
}
},
{
id: "050202",
parentId: "0502",
path: "/multilevel/third-1",
name: "third-1",
component: "multilevel/third/third-1",
@ -287,6 +304,8 @@ export default [
}
},
{
id: "050203",
parentId: "0502",
path: "/multilevel/third-3",
name: "third-3",
component: "multilevel/third/third-3",
@ -303,6 +322,8 @@ export default [
}
},
{
id: "050204",
parentId: "0502",
path: "/multilevel/third-4",
name: "third-4",
component: "multilevel/third/third-4",
@ -319,6 +340,8 @@ export default [
}
},
{
id: "050205",
parentId: "0502",
path: "/multilevel/third-5",
name: "third-5",
component: "multilevel/third/third-5",
@ -335,6 +358,8 @@ export default [
}
},
{
id: "050206",
parentId: "0502",
path: "/multilevel/third-6",
name: "third-6",
component: "multilevel/third/third-6",
@ -351,6 +376,8 @@ export default [
}
},
{
id: "050207",
parentId: "0502",
path: "/multilevel/third-7",
name: "third-7",
component: "multilevel/third/third-7",
@ -367,6 +394,8 @@ export default [
}
},
{
id: "050208",
parentId: "0502",
path: "/multilevel/third-8",
name: "third-8",
component: "multilevel/third/third-8",
@ -383,6 +412,8 @@ export default [
}
},
{
id: "050209",
parentId: "0502",
path: "/multilevel/third-9",
name: "third-9",
component: "multilevel/third/third-9",
@ -403,6 +434,8 @@ export default [
]
},
{
id: "06",
parentId: "0",
path: "/component",
name: "component",
redirect: "/component/player",
@ -420,6 +453,8 @@ export default [
},
children: [
{
id: "0601",
parentId: "06",
path: "/component/player",
name: "player",
component: "component/player/player",
@ -437,6 +472,8 @@ export default [
}
},
{
id: "0602",
parentId: "06",
path: "/component/print",
name: "print",
component: "component/print/print",
@ -454,6 +491,8 @@ export default [
}
},
{
id: "0603",
parentId: "06",
path: "/component/draggable",
name: "draggable",
component: "component/draggable/draggable",
@ -471,6 +510,8 @@ export default [
}
},
{
id: "0604",
parentId: "06",
path: "/component/editor",
name: "editor",
component: "component/editor/editor",
@ -488,6 +529,8 @@ export default [
}
},
{
id: "0605",
parentId: "06",
path: "/component/newbie",
name: "newbie",
component: "component/newbie/newbie",
@ -505,6 +548,8 @@ export default [
}
},
{
id: "0606",
parentId: "06",
path: "/component/icon-selector",
name: "icon-selector",
component: "component/icon-selector/icon-selector",
@ -522,6 +567,8 @@ export default [
}
},
{
id: "0607",
parentId: "06",
path: "/component/user-center",
name: "user-center",
component: "component/user-center/user-center",
@ -539,6 +586,8 @@ export default [
}
},
{
id: "0608",
parentId: "06",
path: "/component/fingerprintjs2",
name: "fingerprintjs2",
component: "component/fingerprintjs2/fingerprintjs2",
@ -556,6 +605,8 @@ export default [
}
},
{
id: "0609",
parentId: "06",
path: "/component/barcode",
name: "barcode",
component: "component/barcode/barcode",
@ -573,6 +624,8 @@ export default [
}
},
{
id: "0610",
parentId: "06",
path: "/component/qrcode",
name: "qrcode",
component: "component/qrcode/qrcode",
@ -590,6 +643,8 @@ export default [
}
},
{
id: "0611",
parentId: "06",
path: "/component/pinyin",
name: "pinyin",
component: "component/pinyin/pinyin",
@ -609,6 +664,8 @@ export default [
]
},
{
id: "07",
parentId: "0",
path: "/directive",
name: "directive",
redirect: "/directive/anti-shake",
@ -626,6 +683,8 @@ export default [
},
children: [
{
id: "0701",
parentId: "07",
path: "/directive/anti-shake",
name: "anti-shake",
component: "directive/anti-shake/anti-shake",
@ -643,6 +702,8 @@ export default [
}
},
{
id: "0702",
parentId: "07",
path: "/directive/throttle",
name: "throttle",
component: "directive/throttle/throttle",
@ -660,6 +721,8 @@ export default [
}
},
{
id: "0703",
parentId: "07",
path: "/directive/test-directive",
name: "test-directive",
component: "directive/test-directive/test-directive",
@ -679,6 +742,8 @@ export default [
]
},
{
id: "08",
parentId: "0",
path: "/personal",
name: "personal",
redirect: "/personal/userinfo",
@ -696,6 +761,8 @@ export default [
},
children: [
{
id: "0801",
parentId: "08",
path: "/personal/userinfo",
name: "userinfo",
component: "personal/userinfo/userinfo",
@ -713,6 +780,8 @@ export default [
}
},
{
id: "0802",
parentId: "08",
path: "/personal/user-settings",
name: "user-settings",
component: "personal/user-settings/user-settings",
@ -732,6 +801,8 @@ export default [
]
},
{
id: "09",
parentId: "0",
path: "/system",
name: "system",
redirect: "/system/account",
@ -749,6 +820,8 @@ export default [
},
children: [
{
id: "0901",
parentId: "09",
path: "/system/account",
name: "account",
component: "system/account/account",
@ -766,6 +839,8 @@ export default [
}
},
{
id: "0902",
parentId: "09",
path: "/system/role",
name: "role",
component: "system/role/role",
@ -783,6 +858,8 @@ export default [
}
},
{
id: "0903",
parentId: "09",
path: "/system/menu",
name: "menu",
component: "system/menu/menu",
@ -800,6 +877,8 @@ export default [
}
},
{
id: "0904",
parentId: "09",
path: "/system/division",
name: "division",
component: "system/division/division",
@ -817,6 +896,8 @@ export default [
}
},
{
id: "0905",
parentId: "09",
path: "/system/dictionary",
name: "dictionary",
component: "system/dictionary/dictionary",
@ -834,6 +915,8 @@ export default [
}
},
{
id: "0906",
parentId: "09",
path: "/system/log",
name: "log",
component: "system/log/log",
@ -853,6 +936,8 @@ export default [
]
},
{
id: "10",
parentId: "0",
path: "/link",
name: "link",
redirect: "/link/internal",
@ -870,6 +955,8 @@ export default [
},
children: [
{
id: "1001",
parentId: "10",
path: "/link/internal",
name: "internal",
redirect: "/link/internal/uigradients",
@ -887,6 +974,8 @@ export default [
},
children: [
{
id: "100101",
parentId: "1001",
path: "/link/internal/uigradients",
name: "uigradients",
component: "link/internal/internal",
@ -904,6 +993,8 @@ export default [
}
},
{
id: "100102",
parentId: "1001",
path: "/link/internal/color-taking-tool",
name: "color-taking-tool",
component: "link/internal/internal",
@ -921,6 +1012,8 @@ export default [
}
},
{
id: "100103",
parentId: "1001",
path: "/link/internal/grid-generator",
name: "grid-generator",
component: "link/internal/internal",
@ -940,6 +1033,8 @@ export default [
]
},
{
id: "1002",
parentId: "10",
path: "/link/external",
name: "external",
redirect: "/link/external/link-vue",
@ -957,6 +1052,8 @@ export default [
},
children: [
{
id: "100201",
parentId: "1002",
path: "/link/external/SnowAdmin-Docs",
name: "SnowAdmin-Docs",
component: "link/external/external",
@ -974,6 +1071,8 @@ export default [
}
},
{
id: "100202",
parentId: "1002",
path: "/link/external/vue",
name: "vue",
component: "link/external/external",
@ -991,6 +1090,8 @@ export default [
}
},
{
id: "100203",
parentId: "1002",
path: "/link/external/vite",
name: "vite",
component: "link/external/external",
@ -1008,6 +1109,8 @@ export default [
}
},
{
id: "100204",
parentId: "1002",
path: "/link/external/github",
name: "github",
component: "link/external/external",
@ -1025,6 +1128,8 @@ export default [
}
},
{
id: "100205",
parentId: "1002",
path: "/link/external/juejin",
name: "juejin",
component: "link/external/external",
@ -1046,6 +1151,8 @@ export default [
]
},
{
id: "11",
parentId: "0",
path: "/disable-menu",
name: "disable-menu",
component: "disable-menu/disable-menu",
@ -1063,6 +1170,8 @@ export default [
}
},
{
id: "12",
parentId: "0",
path: "/hide-menu",
name: "hide-menu",
component: "hide-menu/hide-menu",
@ -1080,6 +1189,8 @@ export default [
}
},
{
id: "13",
parentId: "0",
path: "/i18n",
name: "i18n",
component: "i18n/i18n",
@ -1097,6 +1208,8 @@ export default [
}
},
{
id: "14",
parentId: "0",
path: "/about",
name: "about",
component: "about/about",
@ -1113,6 +1226,4 @@ export default [
sort: 14
}
}
]
}
];

View File

@ -14,9 +14,8 @@ import systemMenu from "../_data/system_menu";
* 1
* 2
* 3
* 4 +
* 5
* 6
* 4
* 5
*/
// post请求body,get请求query
@ -30,8 +29,7 @@ export default [
// 这里模拟两个角色admin、common
let userRoles = token === "Admin-Token" ? ["admin"] : ["common"];
const originTree: any = deepClone(systemMenu);
originTree[0].children = treeSort(filterByRole(originTree[0].children, userRoles));
return resultSuccess(originTree);
return resultSuccess(treeSort(filterByRole(originTree, userRoles)));
}
}
] as MockMethod[];

View File

@ -17,10 +17,10 @@ const router = createRouter({
history: createWebHashHistory(),
/**
* addRoute动态添加
* 1staticRoutes登录页
* 2notFoundAndNoPower 404401 No match found for location with path 'xxx'
* 2 notFoundAndNoPower 404401
* notFoundAndNoPower 404401
* 1staticRoutes登录页layout页('/')
* 2notFoundAndNoPower 401500 No match found for location with path 'xxx'
* 2 notFoundAndNoPower 401500
* notFoundAndNoPower 401500
* notFoundAndNoPower layout容器展示
*/
routes: [...staticRoutes, ...notFoundAndNoPower]

View File

@ -4,7 +4,6 @@ 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 Layout from "@/layout/index.vue";
/**
*
@ -67,19 +66,13 @@ export const moduleReplacement = (tree: any) => {
/**
*
* 1 views .vue
* 2layoutlayout为应用的基础结构
* 3views下的所有文件路径
* 4
* 2views下的所有文件路径
* 3
*/
// 匹配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文件夹下的文件路径
// 匹配每个views文件夹下的文件路径
for (const key in modules) {
const dir = key.split("views/")[1].replace(".vue", "");
// 若匹配上,则替换真实模块

View File

@ -1,3 +1,5 @@
import { HOME_PATH } from "@/config/index";
import Layout from "@/layout/index.vue";
/**
* path路径与文件夹名称相同便
*
@ -13,17 +15,21 @@
* roles: 当前路由权限表示 admincommon
* icon: 菜单tabsView
* svgIcon: svg图标
* sort:
* sort: 菜单顺
* }
*/
/**
*
* `dynamicRoutes数组`
* @description dynamicRoutes dynamicRoutes children lauyout
* `layout-children`
* @description mock/_data/system_menu
* @returns
*/
export const staticRoutes = [
{
path: "/",
redirect: HOME_PATH
},
{
path: "/login",
name: "login",
@ -31,10 +37,18 @@ export const staticRoutes = [
meta: {
title: "login"
}
},
{
path: "/layout",
name: "layout",
redirect: HOME_PATH,
component: Layout, // 容器布局-顶层路由
// 二级路由-主要渲染页面
children: []
}
/**
*
* dynamicRoutes
* layout.children
*
*/
];

View File

@ -86,9 +86,8 @@ export const routesConfigStore = () => {
* 2
* 3
* 4
* 5 +
* 6
* 7
* 5
* 6
*/
async function initSetRouter() {
// 1、获取过滤角色权限后的树后端做排序处理
@ -96,15 +95,13 @@ export const routesConfigStore = () => {
// 2、将模块设置为真实模块
let tree = await moduleReplacement(data);
// 3、存储路由树用于生成菜单
routeTree.value = tree[0].children;
routeTree.value = tree;
// 4、根据树生成一维路由数组
tree[0].children = linearArray(tree[0].children);
// 5、设置完整的路由二维路由顶层路由 + 二级的一维路由
tree[0].redirect = tree[0].children[0].path;
// 6、动态添加路由
tree.forEach((route: any) => router.addRoute(route));
// 7、缓存一维路由
routeList.value = tree[0].children;
tree = linearArray(tree);
// 5、动态添加路由
tree.forEach((route: any) => router.addRoute("layout", route));
// 6、缓存一维路由
routeList.value = tree;
}
return {

View File

@ -95,7 +95,7 @@ import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
import dynamicRoutes from "@/mock/_data/system_menu";
const tableData = computed(() => {
return dynamicRoutes[0].children;
return dynamicRoutes;
});
const formData = reactive({
form: {