feat(projects): 新增顶部菜单
This commit is contained in:
parent
e9db67ee12
commit
221d2cc02d
@ -1,5 +1,5 @@
|
||||
export { ContentType, EnumDataType, EnumLoginModule } from './common';
|
||||
export { EnumAnimate } from './animate';
|
||||
export { EnumNavMode, EnumNavTheme, EnumMultiTabMode } from './theme';
|
||||
export { EnumNavMode, EnumNavTheme, EnumMultiTabMode, EnumHorizontalMenuPosition } from './theme';
|
||||
export { EnumRoutePath, EnumRouteTitle } from './route';
|
||||
export { EnumStorageKey } from './storage';
|
||||
|
@ -13,7 +13,15 @@ export enum EnumNavTheme {
|
||||
'header-dark' = '暗色的侧边栏和顶栏'
|
||||
}
|
||||
|
||||
/** 多页签风格 */
|
||||
export enum EnumMultiTabMode {
|
||||
'button' = '按钮风格',
|
||||
'browser' = '浏览器风格'
|
||||
}
|
||||
|
||||
/** 水平模式的菜单位置 */
|
||||
export enum EnumHorizontalMenuPosition {
|
||||
'flex-start' = '居左',
|
||||
'center' = '居中',
|
||||
'flex-end' = '居右'
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export { UserInfo } from './business';
|
||||
export { ThemeSettings, NavMode, MultiTabMode, AnimateType } from './theme';
|
||||
export { ThemeSettings, NavMode, MultiTabMode, AnimateType, HorizontalMenuPosition } from './theme';
|
||||
export { CustomRoute, RoutePathKey, GlobalMenuOption, LoginModuleType } from './common';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { EnumAnimate, EnumNavMode, EnumNavTheme, EnumMultiTabMode } from '@/enum';
|
||||
import { EnumAnimate, EnumNavMode, EnumNavTheme, EnumMultiTabMode, EnumHorizontalMenuPosition } from '@/enum';
|
||||
|
||||
export interface ThemeSettings {
|
||||
/** 深色模式 */
|
||||
@ -56,6 +56,13 @@ interface HeaderStyle {
|
||||
bgColor: string;
|
||||
}
|
||||
|
||||
export type HorizontalMenuPosition = keyof typeof EnumHorizontalMenuPosition;
|
||||
|
||||
interface HorizontalMenuPositionList {
|
||||
value: HorizontalMenuPosition;
|
||||
label: EnumHorizontalMenuPosition;
|
||||
}
|
||||
|
||||
interface MenuStyle {
|
||||
/** 菜单宽度 */
|
||||
width: number;
|
||||
@ -67,6 +74,10 @@ interface MenuStyle {
|
||||
fixed: boolean;
|
||||
/** 分割菜单 */
|
||||
splitMenu: boolean;
|
||||
/** 水平模式的菜单的位置 */
|
||||
horizontalPosition: HorizontalMenuPosition;
|
||||
/** 水平模式的菜单的位置列表 */
|
||||
horizontalPositionList: HorizontalMenuPositionList[];
|
||||
}
|
||||
|
||||
export type MultiTabMode = keyof typeof EnumMultiTabMode;
|
||||
|
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<n-menu :value="activeKey" mode="horizontal" :options="menus" @update:value="handleUpdateMenu" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import type { MenuOption } from 'naive-ui';
|
||||
import { NMenu } from 'naive-ui';
|
||||
import { menus } from '@/router';
|
||||
import { GlobalMenuOption } from '@/interface';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const activeKey = computed(() => getActiveKey());
|
||||
|
||||
function getActiveKey() {
|
||||
return route.name as string;
|
||||
}
|
||||
|
||||
function handleUpdateMenu(key: string, item: MenuOption) {
|
||||
const menuItem = item as GlobalMenuOption;
|
||||
router.push(menuItem.routePath);
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
@ -5,11 +5,12 @@
|
||||
<div v-if="!theme.isVerticalNav" class="menu-width h-full">
|
||||
<global-logo />
|
||||
</div>
|
||||
<div class="flex-y-center h-full">
|
||||
<div class="flex-1-hidden flex-y-center h-full" :style="{ justifyContent: theme.menuStyle.horizontalPosition }">
|
||||
<menu-collapse v-if="theme.navStyle.mode !== 'horizontal'" />
|
||||
<global-breadcrumb v-if="theme.crumbsStyle.visible" />
|
||||
<global-breadcrumb v-if="theme.crumbsStyle.visible && theme.navStyle.mode !== 'horizontal'" />
|
||||
<header-menu v-if="theme.navStyle.mode === 'horizontal'" />
|
||||
</div>
|
||||
<div class="flex-1 flex justify-end h-full">
|
||||
<div class="flex justify-end h-full">
|
||||
<gihub-site />
|
||||
<full-screen />
|
||||
<user-avatar />
|
||||
@ -25,6 +26,7 @@ import { NLayoutHeader } from 'naive-ui';
|
||||
import { useThemeStore } from '@/store';
|
||||
import { GlobalBreadcrumb, UserAvatar, MenuCollapse, FullScreen, GihubSite, SettingDrawerButton } from './components';
|
||||
import { GlobalLogo } from '../common';
|
||||
import HeaderMenu from './components/HeaderMenu.vue';
|
||||
|
||||
defineProps({
|
||||
zIndex: {
|
||||
|
@ -4,25 +4,13 @@
|
||||
<setting-menu-item label="分割菜单">
|
||||
<n-switch :value="theme.menuStyle.splitMenu" @update:value="handleSplitMenu" />
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="固定头部和多页签">
|
||||
<n-switch :value="splitMenu" :disabled="disabledSplitMenu" @update:value="handleFixedHeaderAndTab" />
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="头部高度">
|
||||
<n-input-number
|
||||
<setting-menu-item label="顶部菜单位置">
|
||||
<n-select
|
||||
class="w-120px"
|
||||
size="small"
|
||||
:value="theme.headerStyle.height"
|
||||
:step="1"
|
||||
@update:value="handleHeaderHeight"
|
||||
/>
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="多页签高度">
|
||||
<n-input-number
|
||||
class="w-120px"
|
||||
size="small"
|
||||
:value="theme.multiTabStyle.height"
|
||||
:step="1"
|
||||
@update:value="handleMultiTabHeight"
|
||||
:value="theme.menuStyle.horizontalPosition"
|
||||
:options="theme.menuStyle.horizontalPositionList"
|
||||
@update:value="handleHorizontalMenuPosition"
|
||||
/>
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="菜单展开宽度">
|
||||
@ -45,18 +33,40 @@
|
||||
@update:value="handleMixMenuWidth"
|
||||
/>
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="固定头部和多页签">
|
||||
<n-switch :value="splitMenu" :disabled="disabledSplitMenu" @update:value="handleFixedHeaderAndTab" />
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="头部高度">
|
||||
<n-input-number
|
||||
class="w-120px"
|
||||
size="small"
|
||||
:value="theme.headerStyle.height"
|
||||
:step="1"
|
||||
@update:value="handleHeaderHeight"
|
||||
/>
|
||||
</setting-menu-item>
|
||||
<setting-menu-item label="多页签高度">
|
||||
<n-input-number
|
||||
class="w-120px"
|
||||
size="small"
|
||||
:value="theme.multiTabStyle.height"
|
||||
:step="1"
|
||||
@update:value="handleMultiTabHeight"
|
||||
/>
|
||||
</setting-menu-item>
|
||||
</n-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { NDivider, NSpace, NSwitch, NInputNumber } from 'naive-ui';
|
||||
import { NDivider, NSpace, NSwitch, NSelect, NInputNumber } from 'naive-ui';
|
||||
import { useThemeStore } from '@/store';
|
||||
import { SettingMenuItem } from '../common';
|
||||
|
||||
const theme = useThemeStore();
|
||||
const {
|
||||
handleSplitMenu,
|
||||
handleHorizontalMenuPosition,
|
||||
handleFixedHeaderAndTab,
|
||||
handleHeaderHeight,
|
||||
handleMultiTabHeight,
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<n-layout class="h-full" has-sider>
|
||||
<global-sider v-if="theme.isVerticalNav" :z-index="3" />
|
||||
<global-header v-if="isHorizontalMix" :z-index="2" />
|
||||
<global-header v-if="isHorizontalMix" :z-index="4" />
|
||||
<div class="flex-1-hidden flex h-full">
|
||||
<global-sider v-if="isHorizontalMix" class="sider-margin" :z-index="3" />
|
||||
<n-scrollbar
|
||||
@ -39,6 +39,11 @@ const { scrollbar, resetScrollBehavior } = useScrollBehavior();
|
||||
const routeProps = useRouteProps();
|
||||
|
||||
const isHorizontalMix = computed(() => theme.navStyle.mode === 'horizontal-mix');
|
||||
|
||||
const headerHeight = computed(() => {
|
||||
const { height } = theme.headerStyle;
|
||||
return `${height}px`;
|
||||
});
|
||||
const headerAndMultiTabHeight = computed(() => {
|
||||
const {
|
||||
headerStyle: { height: hHeight },
|
||||
@ -59,7 +64,7 @@ watch(
|
||||
z-index: 11;
|
||||
}
|
||||
.sider-margin {
|
||||
margin-top: v-bind(headerAndMultiTabHeight);
|
||||
margin-top: v-bind(headerHeight);
|
||||
}
|
||||
.content-padding {
|
||||
padding-top: v-bind(headerAndMultiTabHeight);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { ThemeSettings } from '../interface';
|
||||
import { EnumAnimate, EnumMultiTabMode } from '../enum';
|
||||
import { EnumAnimate, EnumMultiTabMode, EnumHorizontalMenuPosition } from '../enum';
|
||||
|
||||
const themeColorList = [
|
||||
'#409EFF',
|
||||
@ -41,7 +41,13 @@ const themeSettings: ThemeSettings = {
|
||||
mixWidth: 80,
|
||||
collapsedWidth: 64,
|
||||
fixed: true,
|
||||
splitMenu: false
|
||||
splitMenu: false,
|
||||
horizontalPosition: 'flex-start',
|
||||
horizontalPositionList: [
|
||||
{ value: 'flex-start', label: EnumHorizontalMenuPosition['flex-start'] },
|
||||
{ value: 'center', label: EnumHorizontalMenuPosition.center },
|
||||
{ value: 'flex-end', label: EnumHorizontalMenuPosition['flex-end'] }
|
||||
]
|
||||
},
|
||||
headerStyle: {
|
||||
height: 56,
|
||||
|
@ -2,7 +2,7 @@ import { defineStore } from 'pinia';
|
||||
import type { GlobalThemeOverrides } from 'naive-ui';
|
||||
import { themeSettings } from '@/settings';
|
||||
import { store } from '@/store';
|
||||
import type { ThemeSettings, NavMode, MultiTabMode, AnimateType } from '@/interface';
|
||||
import type { ThemeSettings, NavMode, MultiTabMode, AnimateType, HorizontalMenuPosition } from '@/interface';
|
||||
import { getHoverAndPressedColor } from './helpers';
|
||||
|
||||
type ThemeState = ThemeSettings;
|
||||
@ -85,6 +85,10 @@ const themeStore = defineStore({
|
||||
this.menuStyle.mixWidth = width;
|
||||
}
|
||||
},
|
||||
/** 更改顶部水平菜单的位置 */
|
||||
handleHorizontalMenuPosition(position: HorizontalMenuPosition) {
|
||||
this.menuStyle.horizontalPosition = position;
|
||||
},
|
||||
/** 更改头部的高度 */
|
||||
handleHeaderHeight(height: number | null) {
|
||||
if (height !== null) {
|
||||
|
Loading…
Reference in New Issue
Block a user