Merge branch 'master' into main

This commit is contained in:
wang_fan_w 2024-08-24 22:09:24 +08:00
commit 7908a823a5
14 changed files with 176 additions and 97 deletions

View File

@ -0,0 +1,28 @@
/**
* hooks
* @returns
*/
export const useMneuMethod = () => {
/**
*
* @param {Menu.MenuOptions} item item
* @returns childrentruefalse
*/
const menuShow = (item: Menu.MenuOptions) => {
if (item.children && item.children?.length > 0 && !item.meta.hide) return true;
return false;
};
/**
*
* @param {Menu.MenuOptions} item item
* @returns truefalse
*/
const aMenuShow = (item: Menu.MenuOptions) => {
if (!item.meta.hide) return true;
return false;
};
return {
menuShow,
aMenuShow
};
};

View File

@ -64,6 +64,10 @@ const onTab = (key: number) => {
}
}
}
.margin-left-text {
margin-left: $margin-text;
}
// tabsbug
:deep(.arco-tabs-content .arco-tabs-content-list) {
display: unset;

View File

@ -257,4 +257,8 @@ const logOut = () => {
transform: rotate(180deg) !important;
}
}
.margin-left-text {
margin-left: $margin-text;
}
</style>

View File

@ -19,6 +19,7 @@
<script setup lang="ts">
import MenuItem from "@/layout/components/Menu/menu-item.vue";
import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
import { useMneuMethod } from "@/hooks/useMneuMethod";
defineOptions({ name: "MenuItem", inheritAttrs: false });
interface Props {
@ -30,16 +31,7 @@ const props = withDefaults(defineProps<Props>(), {
routeTree: () => []
});
//
const menuShow = (item: Menu.MenuOptions) => {
if (item.children && item.children?.length > 0 && !item.meta.hide) return true;
return false;
};
//
const aMenuShow = (item: Menu.MenuOptions) => {
if (!item.meta.hide) return true;
return false;
};
const { menuShow, aMenuShow } = useMneuMethod();
</script>
<style lang="scss" scoped></style>

View File

@ -90,10 +90,10 @@ const refresh = () => {
const themeStore = useThemeConfig();
themeStore.setRefreshPage(false);
currentRoute.value.meta.keepAlive && routerStore.removeRouteName(currentRoute.value.name);
setTimeout(() => {
nextTick(() => {
themeStore.setRefreshPage(true);
currentRoute.value.meta.keepAlive && routerStore.setRouteNames(currentRoute.value.name);
}, 0);
});
};
//

View File

@ -5,17 +5,23 @@
<div class="header-logo">
<Logo />
</div>
<a-menu mode="horizontal" :selected-keys="[currentRoute.name]" @menu-item-click="onMenuItem">
<div class="layout-head-menu">
<a-menu
v-if="drawing"
mode="horizontal"
:selected-keys="[currentRoute.name]"
@menu-item-click="onMenuItem"
:popup-max-height="600"
>
<template v-for="item in routeTree" :key="item.name">
<a-sub-menu v-if="item.children && item.children.length > 0" :key="item.name">
<a-sub-menu v-if="menuShow(item)" :key="item.name" :popup-max-height="600">
<template #icon v-if="item.meta.svgIcon || item.meta.icon">
<MenuItemIcon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template>
<template #title>{{ $t(`language.${item.meta.title}`) }}</template>
<MenuItem :route-tree="item.children" />
</a-sub-menu>
<a-menu-item v-else :key="item?.name">
<a-menu-item v-else-if="aMenuShow(item)" :key="item?.name">
<template #icon v-if="item.meta.svgIcon || item.meta.icon">
<MenuItemIcon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template>
@ -23,6 +29,8 @@
</a-menu-item>
</template>
</a-menu>
</div>
<HeaderRight />
</a-layout-header>
<Main />
@ -43,12 +51,21 @@ import { storeToRefs } from "pinia";
import { useRoutesListStore } from "@/store/modules/route-list";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
import { useThemeConfig } from "@/store/modules/theme-config";
import { useMneuMethod } from "@/hooks/useMneuMethod";
defineOptions({ name: "LayoutHead" });
const router = useRouter();
const routerStore = useRoutesListStore();
const themeStore = useThemeConfig();
const { routeTree, currentRoute } = storeToRefs(routerStore);
const { isFooter } = storeToRefs(themeStore);
const { isFooter, language } = storeToRefs(themeStore);
const { menuShow, aMenuShow } = useMneuMethod();
const drawing = ref<boolean>(true);
watch(language, () => {
drawing.value = false;
nextTick(() => (drawing.value = true));
});
/**
* @description 菜单点击事件
@ -79,15 +96,20 @@ const onMenuItem = (key: string) => {
.header {
padding: 0 $padding;
height: 60px;
width: 100%;
box-sizing: border-box;
border-bottom: $border-1 solid $color-border-2;
display: flex;
justify-content: space-between;
align-items: center;
overflow: hidden;
.header-logo {
max-width: 180px;
}
.layout-head-menu {
flex: 1;
display: flex;
overflow: hidden;
}
}
:deep(.arco-menu-pop) {

View File

@ -16,15 +16,24 @@
</template>
</a-button>
</div>
<a-menu mode="horizontal" :selected-keys="[aciveRoute]" @menu-item-click="onMenuItem">
<a-menu-item v-for="item in routeTree" :key="item.name">
<div class="layout-head-menu">
<a-menu
v-if="drawing"
mode="horizontal"
:selected-keys="[aciveRoute]"
@menu-item-click="onMenuItem"
:popup-max-height="600"
>
<template v-for="item in routeTree" :key="item.name">
<a-menu-item v-if="aMenuShow(item)" :key="item.name" :popup-max-height="600">
<template #icon v-if="item.meta.svgIcon || item.meta.icon">
<MenuItemIcon :svg-icon="item.meta.svgIcon" :icon="item.meta.icon" />
</template>
<span>{{ $t(`language.${item.meta.title}`) }}</span>
</a-menu-item>
</template>
</a-menu>
</div>
<HeaderRight />
</a-layout-header>
<Main />
@ -45,21 +54,27 @@ import { useRoutesListStore } from "@/store/modules/route-list";
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
import { storeToRefs } from "pinia";
import { useThemeConfig } from "@/store/modules/theme-config";
import { useMneuMethod } from "@/hooks/useMneuMethod";
defineOptions({ name: "LayoutMixing" });
const route = useRoute();
const router = useRouter();
const routerStore = useRoutesListStore();
const themeStore = useThemeConfig();
const { isFooter, collapsed, asideDark } = storeToRefs(themeStore);
const { isFooter, collapsed, asideDark, language } = storeToRefs(themeStore);
const { routeTree } = storeToRefs(routerStore);
const { aMenuShow } = useMneuMethod();
const drawing = ref<boolean>(true);
watch(language, () => {
drawing.value = false;
nextTick(() => (drawing.value = true));
});
//
const onCollapsed = () => {
themeStore.setCollapsed(!collapsed.value);
};
console.log("路由信息", route);
//
//
//
@ -181,6 +196,11 @@ const getAsideMenu = (key: string) => {
}
}
}
.layout-head-menu {
flex: 1;
display: flex;
overflow: hidden;
}
}
:deep(.arco-menu-pop) {

View File

@ -20,21 +20,20 @@ export async function initSetRouter() {
// 初始化路由渲染loading
loadingPage.start();
const store = useRoutesListStore(pinia);
// 根据角色权限过滤树
// 根据角色权限过滤树并将其排序
const originTree: RouteRecordRaw[] = deepClone(dynamicRoutes);
let filteredTree = filterByRole(originTree[0].children);
let filteredTree = treeSort(filterByRole(originTree[0].children));
await store.setRouteTree(filteredTree);
// 根据树生成一维路由数组
const flattenedArray = linearArray(filteredTree);
// 设置完整的路由,二维路由顶层路由 + 二级的一维路由
const twoStoryTree = originTree.map(item => {
// 设置完整的路由,二维路由顶层路由 + 二级的一维路由
const addBeforeTree = originTree.map(item => {
if (flattenedArray.length > 0) item.redirect = flattenedArray[0].path;
item.children = flattenedArray;
return item;
});
// 动态添加路由
twoStoryTree.forEach((route: any) => router.addRoute(route));
addBeforeTree.forEach((route: RouteRecordRaw) => router.addRoute(route));
// 设置一维路由
setRouting(flattenedArray);
}
@ -78,6 +77,37 @@ export const filterByRole = (tree: any) => {
});
};
/**
*
* 1
* 2children则递归排序
* @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;
});
// 深层递归
let sortAfter = tree.map((item: any) => {
if (item?.children?.length > 0) {
item.children = treeSort(item.children);
}
return item;
});
return sortAfter;
};
/**
*
* @param {array} roles

View File

@ -90,7 +90,6 @@ export const dynamicRoutes: RouteRecordRaw[] = [
}
]
},
{
path: "/table-management",
name: "table-management",
@ -534,7 +533,7 @@ export const dynamicRoutes: RouteRecordRaw[] = [
{
path: "/system-management",
name: "system-management",
redirect: "/system-management/account management",
redirect: "/system-management/account-management",
meta: {
title: "system-management",
hide: false,

View File

@ -1,4 +1,6 @@
/* global style scss */
// 有背景色的页面
.snow-page {
// margin padding 边距一致是为了保持视觉上的内外统一
margin: $padding;
@ -6,53 +8,7 @@
background: $color-bg-1;
}
// 没有背景色的页面
.snow-page-clear {
margin: $padding;
}
.border-red {
box-shadow: $shadow-border-1;
}
// 通用全外边距
.margin {
margin: $margin;
}
// 下边距
.margin-bottom {
margin-bottom: $margin;
}
// 左间距-行内文字
.margin-left-text {
margin-left: $margin-text;
}
// 右间距-行内文字
.margin-right-text {
margin-right: $margin-text;
}
// 中等卡片大小
.card-middling {
width: 200px;
}
// 一行完全居中
.row-center {
display: flex;
justify-content: center;
align-items: center;
}
// 垂直居中从左到右
.row-start-center {
display: flex;
justify-content: start;
align-items: center;
}
// 垂直居中左右占满
.flex-row-between-center {
display: flex;
justify-content: space-between;
align-items: center;
}

View File

@ -32,3 +32,8 @@ body {
background: $color-bg-2; // body背景颜色
color: $color-text-1; // 整体文字的颜色
}
// 设置nprogress进度条样式
#nprogress .bar {
background: $color-primary !important;
}

View File

@ -12,6 +12,7 @@ declare namespace Menu {
interface MetaType {
title: string;
hide: boolean;
disable: boolean;
keepAlive: boolean;
affix: boolean;
link?: string;
@ -19,6 +20,7 @@ declare namespace Menu {
roles: Array<string>;
icon?: string;
svgIcon?: string;
sort?: number;
}
}
/* tabs菜单 */

View File

@ -99,4 +99,8 @@ const financeData = ref([
font-size: $font-size-body-3;
color: $color-text-1;
}
.margin-left-text {
margin-left: $margin-text;
}
</style>

View File

@ -72,6 +72,19 @@ const shortcut = ref([
color: $color-text-2;
}
}
.card-middling {
width: 200px;
}
.row-center {
display: flex;
justify-content: center;
align-items: center;
}
}
.margin-left-text {
margin-left: $margin-text;
}
.box-title {
display: flex;