feat: 递归菜单

This commit is contained in:
wang_fan_w 2024-04-13 22:09:14 +08:00
parent e882fb6055
commit 913d213737
13 changed files with 373 additions and 309 deletions

View File

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

View File

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

1
src/icons/common.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1713016089982" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="32457" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M108.8 454.4c-25.6 0-44.8-12.8-44.8-44.8V108.8c0-32 12.8-44.8 44.8-44.8h307.2c25.6 0 38.4 19.2 38.4 44.8v307.2c0 25.6-19.2 38.4-38.4 38.4H108.8z m499.2 0c-25.6 0-38.4-19.2-38.4-44.8V108.8c0-25.6 12.8-44.8 38.4-44.8h307.2c32 0 44.8 12.8 44.8 44.8v307.2c0 25.6-19.2 38.4-44.8 38.4H608zM108.8 960c-32 0-44.8-12.8-44.8-44.8V608c0-25.6 19.2-38.4 44.8-38.4h307.2c25.6 0 38.4 19.2 38.4 38.4v307.2c0 25.6-19.2 44.8-38.4 44.8H108.8z m499.2 0c-25.6 0-38.4-19.2-38.4-44.8V608c0-25.6 19.2-38.4 38.4-38.4h307.2c25.6 0 44.8 19.2 44.8 38.4v307.2c0 25.6-19.2 44.8-44.8 44.8H608z" p-id="32458" fill="#e5e6eb"></path></svg>

After

Width:  |  Height:  |  Size: 939 B

1
src/icons/form.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M0 0m349.090909 0l325.818182 0q349.090909 0 349.090909 349.090909l0 325.818182q0 349.090909-349.090909 349.090909l-325.818182 0q-349.090909 0-349.090909-349.090909l0-325.818182q0-349.090909 349.090909-349.090909Z" fill="#F7A647" /><path d="M663.272727 244.363636a46.545455 46.545455 0 0 1 46.545455 46.545455v84.026182L465.501091 619.264a64 64 0 0 0-2.024727 88.389818l2.024727 2.117818a64 64 0 0 0 88.389818 2.024728l2.117818-2.024728L709.818182 555.950545V733.090909a46.545455 46.545455 0 0 1-46.545455 46.545455H279.272727a46.545455 46.545455 0 0 1-46.545454-46.545455V290.909091a46.545455 46.545455 0 0 1 46.545454-46.545455h384z m108.101818 160.046546a29.090909 29.090909 0 0 1 0.93091 39.633454l-1.44291 1.512728-238.545454 232.727272a29.090909 29.090909 0 0 1-42.065455-40.145454l1.431273-1.512727 238.545455-232.727273a29.090909 29.090909 0 0 1 41.134545 0.512zM401.454545 581.818182H314.181818l-1.745454 0.058182A23.272727 23.272727 0 0 0 314.181818 628.363636h87.272727l1.745455-0.058181A23.272727 23.272727 0 0 0 401.454545 581.818182z m64-110.545455H314.181818l-1.745454 0.058182A23.272727 23.272727 0 0 0 314.181818 517.818182h151.272727l1.745455-0.058182A23.272727 23.272727 0 0 0 465.454545 471.272727z m58.181819-116.363636H314.181818l-1.745454 0.058182A23.272727 23.272727 0 0 0 314.181818 401.454545h209.454546l1.745454-0.058181A23.272727 23.272727 0 0 0 523.636364 354.909091z" fill="#FFFFFF" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

1
src/icons/home.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M1024 512c0 282.7776-229.2224 512-512 512S0 794.7776 0 512 229.2224 0 512 0s512 229.2224 512 512z" fill="#2962FF" /><path d="M493.5936 234.9056a39.3984 39.3984 0 0 1 36.608 0l1.9584 1.024 1.6384 1.536 243.7376 224.512a45.4144 45.4144 0 0 1 13.7344 49.024 36.8896 36.8896 0 0 1-35.6096 23.168H704V716.8a51.2 51.2 0 0 1-51.2 51.2h-76.8v-115.2a64 64 0 0 0-128 0v115.2h-76.8a51.2 51.2 0 0 1-51.2-51.2V534.1696h-54.2336a36.6336 36.6336 0 0 1-33.024-23.552 44.9536 44.9536 0 0 1 13.9136-48.896l244.992-225.792z" fill="#FFFFFF" /></svg>

After

Width:  |  Height:  |  Size: 796 B

1
src/icons/set.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M0 0m349.090909 0l325.818182 0q349.090909 0 349.090909 349.090909l0 325.818182q0 349.090909-349.090909 349.090909l-325.818182 0q-349.090909 0-349.090909-349.090909l0-325.818182q0-349.090909 349.090909-349.090909Z" fill="#62A8FC" /><path d="M704.570182 266.554182l-90.216727 90.88 75.892363 77.533091 90.391273-91.054546c20.957091 51.688727 10.973091 113.384727-30.161455 155.403637-45.300364 46.277818-113.757091 53.480727-166.946909 22.830545l-38.458182 42.914909-28.066909 31.325091-183.970909 205.312a42.286545 42.286545 0 0 1-60.706909 0l-15.185454-15.511273a44.532364 44.532364 0 0 1 0-62.033454l209.559272-179.293091-139.182545-142.545455-43.938909-0.023272-50.850909-83.549091 40.96-41.902546 83.642182 52.282182 0.581818 43.985455 140.776727 144.384 40.96-35.048728c-40.029091-55.773091-35.863273-134.295273 13.498182-184.715636a137.402182 137.402182 0 0 1 151.424-31.173818zM651.636364 570.181818c64.267636 0 116.363636 52.096 116.363636 116.363637s-52.096 116.363636-116.363636 116.363636-116.363636-52.096-116.363637-116.363636 52.096-116.363636 116.363637-116.363637zM277.178182 746.007273c-8.378182 8.576-8.378182 22.458182 0 31.034182 8.378182 8.564364 21.969455 8.564364 30.370909 0 8.378182-8.564364 8.378182-22.458182 0-31.022546a21.154909 21.154909 0 0 0-30.370909 0z m364.765091-122.496a14.545455 14.545455 0 0 0-14.475637 13.067636l-0.069818 1.477818v74.053818l0.058182 1.396364a14.545455 14.545455 0 0 0 12.986182 13.067636l1.501091 0.081455h61.707636l1.396364-0.069818a14.545455 14.545455 0 0 0 13.067636-12.986182l0.081455-1.489455-0.069819-1.396363a14.545455 14.545455 0 0 0-12.986181-13.079273l-1.489455-0.069818h-47.173818v-59.508364l-0.058182-1.396363a14.545455 14.545455 0 0 0-14.475636-13.149091z" fill="#FFFFFF" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

1
src/icons/switch.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M0 0m349.090909 0l325.818182 0q349.090909 0 349.090909 349.090909l0 325.818182q0 349.090909-349.090909 349.090909l-325.818182 0q-349.090909 0-349.090909-349.090909l0-325.818182q0-349.090909 349.090909-349.090909Z" fill="#3271FD" /><path d="M718.661818 232.727273a22.341818 22.341818 0 0 1 22.283637 20.677818l0.058181 1.664 0.011637 328.145454a61.463273 61.463273 0 0 1 0 114.501819l-0.011637 71.214545a22.341818 22.341818 0 0 1-44.625454 1.664l-0.058182-1.664v-71.214545a61.463273 61.463273 0 0 1 0-114.501819v-328.145454c0-12.334545 10.007273-22.341818 22.341818-22.341818z m-424.494545 0a22.341818 22.341818 0 0 1 22.283636 20.677818l0.058182 1.664v328.145454a61.463273 61.463273 0 0 1 0 114.501819v71.214545a22.341818 22.341818 0 0 1-44.625455 1.664l-0.058181-1.664-0.011637-71.214545a61.463273 61.463273 0 0 1 0-114.501819l0.011637-328.145454c0-12.334545 10.007273-22.341818 22.341818-22.341818z m212.247272 0a22.341818 22.341818 0 0 1 22.283637 20.677818l0.058182 1.664v81.221818a83.816727 83.816727 0 0 1 0 161.512727v271.127273a22.341818 22.341818 0 0 1-44.625455 1.664l-0.058182-1.664v-271.127273a83.816727 83.816727 0 0 1 0-161.512727v-81.221818c0-12.334545 10.007273-22.341818 22.341818-22.341818z" fill="#FFFFFF" /></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -5,29 +5,19 @@
<span class="logo_title" v-if="!collapsed">dc admin</span>
</div>
<a-layout-sider :collapsed="collapsed" breakpoint="xl" class="layout_side" :width="220">
<a-scrollbar style="height: 100%; overflow: auto" outer-class="scrollbar">
<a-menu show-collapse-button breakpoint="xl" @collapse="onCollapse">
<a-menu-item key="0_0_0" data-obj="1">Menu 1</a-menu-item>
<a-sub-menu :key="item" v-for="item in 20">
<template #icon><icon-apps></icon-apps></template>
<template #title>Navigation 1</template>
<a-menu-item key="0_0">Menu 1</a-menu-item>
<a-menu-item key="0_1">Menu 2</a-menu-item>
<a-menu-item key="0_2" disabled>Menu 3</a-menu-item>
</a-sub-menu>
</a-menu>
</a-scrollbar>
<a-scrollbar style="height: 100%; overflow: auto" outer-class="scrollbar"><Menu /></a-scrollbar>
</a-layout-sider>
</div>
</template>
<script setup lang="ts">
import Logo from "@/assets/img/logo.jpg";
import Menu from "@/layout/components/Menu/index.vue";
import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/theme-config";
const collapsed = ref<boolean>(false);
const onCollapse = (type: boolean) => {
collapsed.value = type;
};
const themeStore = useThemeConfig();
const { collapsed } = storeToRefs(themeStore);
</script>
<style lang="scss" scoped>

View File

@ -2,9 +2,10 @@
<a-layout-header class="header">
<div class="header_crumb">
<div class="menu_fold">
<a-button size="mini" type="text" class="menu_fold_icon">
<a-button size="mini" type="text" class="menu_fold_icon" @click="onCollapsed">
<template #icon>
<icon-menu-fold :size="18" />
<icon-menu-fold :size="18" v-if="!collapsed" />
<icon-menu-unfold :size="18" v-if="collapsed" />
</template>
</a-button>
</div>
@ -114,11 +115,19 @@
<script setup lang="ts">
import Notice from "@/layout/components/Header/components/Notice/index.vue";
import myImage from "@/assets/img/my-image.jpg";
import pinia from "@/store/index";
import { Modal } from "@arco-design/web-vue";
import { useRouter } from "vue-router";
import pinia from "@/store/index";
import { storeToRefs } from "pinia";
import { useUserInfoStore } from "@/store/user-info";
import { useThemeConfig } from "@/store/theme-config";
const router = useRouter();
const themeStore = useThemeConfig();
const { collapsed } = storeToRefs(themeStore);
const onCollapsed = () => {
themeStore.setCollapsed(!collapsed.value);
};
const logOut = () => {
Modal.warning({

View File

@ -1,7 +1,21 @@
<template>
<div></div>
<a-menu breakpoint="xl" :collapsed="collapsed">
<MenuItem :route-tree="routeTree" />
</a-menu>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import MenuItem from "@/layout/components/Menu/menu-item.vue";
import { storeToRefs } from "pinia";
import { useRoutesListStore } from "@/store/route-list";
import { useThemeConfig } from "@/store/theme-config";
const routerStore = useRoutesListStore();
const { routeTree } = storeToRefs(routerStore);
const themeStore = useThemeConfig();
const { collapsed } = storeToRefs(themeStore);
console.log("路由树", routeTree.value);
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,26 @@
<template>
<template v-for="item in props.routeTree" :key="item.name">
<a-sub-menu v-if="item.children && item.children.length > 0" :key="item.name">
<template #icon><SvgIcon :name="item.meta.icon" :size="25" /></template>
<template #title>{{ item.meta.title }}</template>
<MenuItem :route-tree="item.children" />
</a-sub-menu>
<a-menu-item v-else :key="item.name">
<template #icon><SvgIcon :name="item.meta.icon" :size="25" /></template>
<div>{{ item.meta.title }}</div>
</a-menu-item>
</template>
</template>
<script setup lang="ts">
defineOptions({ name: "MenuItem" });
// defineProps
const props = defineProps({
routeTree: {
type: Array,
default: () => []
}
});
</script>
<style lang="scss" scoped></style>

View File

@ -5,10 +5,6 @@
</template>
<script setup lang="ts">
import { useRoute } from "vue-router";
const route = useRoute();
console.log("页面查看路由", route);
// -
const layouts = {
defaults: defineAsyncComponent(() => import("@/layout/LayoutDefaults/index.vue")),

19
src/store/theme-config.ts Normal file
View File

@ -0,0 +1,19 @@
import { defineStore } from "pinia";
/**
*
* @methods setCollapsed
*/
export const useThemeConfig = defineStore("themeConfig", {
state: (): any => ({
collapsed: false // 是否折叠菜单
}),
actions: {
async setCollapsed(data: boolean) {
this.collapsed = data;
}
},
persist: {
enabled: true
}
});