mirror of
https://github.com/vbenjs/vue-vben-admin.git
synced 2025-02-03 02:54:40 +08:00
feat(trigger): add trigger config
This commit is contained in:
parent
58f988a718
commit
4f6b65b8a1
@ -1,9 +1,17 @@
|
|||||||
## Wip
|
## Wip
|
||||||
|
|
||||||
|
### ✨ Features
|
||||||
|
|
||||||
|
- 菜单 trigger 可以选择位置
|
||||||
|
- 增加富文本嵌入表单的示例
|
||||||
|
- 表单组件 schema 增加 `required`属性。简化配置
|
||||||
|
- openModal 和 openDrawer 第二个参数可以代替`transferModalData`传参到内部
|
||||||
|
|
||||||
### ⚡ Performance Improvements
|
### ⚡ Performance Improvements
|
||||||
|
|
||||||
- 菜单性能继续优化,更流畅
|
- 菜单性能继续优化,更流畅
|
||||||
- 优化懒加载组件及示例
|
- 优化懒加载组件及示例
|
||||||
|
- layout 样式微调
|
||||||
|
|
||||||
### 🎫 Chores
|
### 🎫 Chores
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
"echarts": "^4.9.0",
|
"echarts": "^4.9.0",
|
||||||
"lodash-es": "^4.17.15",
|
"lodash-es": "^4.17.15",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
|
"moment": "^2.29.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"qrcode": "^1.4.4",
|
"qrcode": "^1.4.4",
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import 'moment/locale/zh-cn';
|
import 'moment/dist/locale/zh-cn';
|
||||||
|
|
||||||
import { useConfigProvider, useInitAppConfigStore, useListenerNetWork } from './useApp';
|
import { useConfigProvider, useInitAppConfigStore, useListenerNetWork } from './useApp';
|
||||||
import { useLockPage } from '/@/hooks/web/useLockPage';
|
import { useLockPage } from '/@/hooks/web/useLockPage';
|
||||||
|
@ -73,7 +73,7 @@ export default defineComponent({
|
|||||||
offset += 46;
|
offset += 46;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
height: `calc(100% - ${offset - 10}px)`,
|
height: `calc(100% - ${offset - 12}px)`,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ export default defineComponent({
|
|||||||
* @description: 渲染图标
|
* @description: 渲染图标
|
||||||
*/
|
*/
|
||||||
function renderIcon(icon: string) {
|
function renderIcon(icon: string) {
|
||||||
return icon ? <Icon icon={icon} size={18} class="mr-1 menu-item-icon" /> : null;
|
return icon ? <Icon icon={icon} size={18} class="menu-item-icon" /> : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
line-height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > li > .ant-menu-submenu-title {
|
& > li > .ant-menu-submenu-title {
|
||||||
@ -183,9 +184,17 @@
|
|||||||
transition: unset;
|
transition: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.basic-menu__sidebar-hor).ant-menu-inline-collapsed {
|
||||||
|
.basic-menu-item__level1 {
|
||||||
|
> div {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.ant-menu-dark:not(.basic-menu__sidebar-hor):not(.basic-menu__second) {
|
&.ant-menu-dark:not(.basic-menu__sidebar-hor):not(.basic-menu__second) {
|
||||||
// Reset menu item row height
|
// Reset menu item row height
|
||||||
.ant-menu-item,
|
.ant-menu-item:not(.basic-menu-item__level1),
|
||||||
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
|
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
|
||||||
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
|
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
|
||||||
height: @app-menu-item-height;
|
height: @app-menu-item-height;
|
||||||
|
@ -17,6 +17,16 @@ export enum MenuThemeEnum {
|
|||||||
LIGHT = 'light',
|
LIGHT = 'light',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 折叠触发器位置
|
||||||
|
export enum TriggerEnum {
|
||||||
|
// 不显示
|
||||||
|
NONE = 'NONE',
|
||||||
|
// 菜单底部
|
||||||
|
FOOTER = 'FOOTER',
|
||||||
|
// 头部
|
||||||
|
HEADER = 'HEADER',
|
||||||
|
}
|
||||||
|
|
||||||
export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline';
|
export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline';
|
||||||
|
|
||||||
// menu mode
|
// menu mode
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-logo anticon" @click="handleGoHome" :style="wrapStyle">
|
<div class="app-logo anticon" :class="theme" @click="handleGoHome" :style="wrapStyle">
|
||||||
<img :src="logo" />
|
<img :src="logo" />
|
||||||
<div v-if="show" class="logo-title ml-2 ellipsis">{{ globSetting.title }}</div>
|
<div v-if="show" class="logo-title ml-2 ellipsis">{{ globSetting.title }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,6 +26,9 @@
|
|||||||
type: Boolean as PropType<boolean>,
|
type: Boolean as PropType<boolean>,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
|
theme: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const showRef = ref<boolean>(!!props.showTitle);
|
const showRef = ref<boolean>(!!props.showTitle);
|
||||||
@ -80,6 +83,9 @@
|
|||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
// justify-content: center;
|
// justify-content: center;
|
||||||
|
&.light {
|
||||||
|
border-bottom: 1px solid @border-color-base;
|
||||||
|
}
|
||||||
|
|
||||||
.logo-title {
|
.logo-title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { Layout } from 'ant-design-vue';
|
// import { Layout } from 'ant-design-vue';
|
||||||
// hooks
|
// hooks
|
||||||
|
|
||||||
import { ContentEnum } from '/@/enums/appEnum';
|
import { ContentEnum } from '/@/enums/appEnum';
|
||||||
@ -13,9 +13,9 @@ export default defineComponent({
|
|||||||
const { contentMode } = getProjectConfig;
|
const { contentMode } = getProjectConfig;
|
||||||
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
||||||
return (
|
return (
|
||||||
<Layout.Content class={`layout-content ${wrapClass} `}>
|
// <Layout.Content class={`layout-content ${wrapClass} `}>
|
||||||
{() => <PageLayout />}
|
<PageLayout class={`layout-content ${wrapClass} `} />
|
||||||
</Layout.Content>
|
// </Layout.Content>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,7 @@ import UserDropdown from './UserDropdown';
|
|||||||
import LayoutMenu from './LayoutMenu';
|
import LayoutMenu from './LayoutMenu';
|
||||||
import LayoutBreadcrumb from './LayoutBreadcrumb';
|
import LayoutBreadcrumb from './LayoutBreadcrumb';
|
||||||
import LockAction from './actions/LockActionItem';
|
import LockAction from './actions/LockActionItem';
|
||||||
|
import LayoutTrigger from './LayoutTrigger';
|
||||||
import NoticeAction from './actions/notice/NoticeActionItem.vue';
|
import NoticeAction from './actions/notice/NoticeActionItem.vue';
|
||||||
import {
|
import {
|
||||||
RedoOutlined,
|
RedoOutlined,
|
||||||
@ -25,7 +26,7 @@ import { useModal } from '/@/components/Modal/index';
|
|||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
import { errorStore } from '/@/store/modules/error';
|
import { errorStore } from '/@/store/modules/error';
|
||||||
|
|
||||||
import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { GITHUB_URL } from '/@/settings/siteSetting';
|
import { GITHUB_URL } from '/@/settings/siteSetting';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DefaultLayoutHeader',
|
name: 'DefaultLayoutHeader',
|
||||||
@ -75,6 +76,13 @@ export default defineComponent({
|
|||||||
return theme ? `layout-header__header--${theme}` : '';
|
return theme ? `layout-header__header--${theme}` : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showHeaderTrigger = computed(() => {
|
||||||
|
const { show, trigger, hidden } = unref(getProjectConfigRef).menuSetting;
|
||||||
|
|
||||||
|
if (!show || !hidden) return false;
|
||||||
|
return trigger === TriggerEnum.HEADER;
|
||||||
|
});
|
||||||
|
|
||||||
function handleToErrorList() {
|
function handleToErrorList() {
|
||||||
errorStore.commitErrorListCountState(0);
|
errorStore.commitErrorListCountState(0);
|
||||||
push('/exception/error-log');
|
push('/exception/error-log');
|
||||||
@ -92,6 +100,7 @@ export default defineComponent({
|
|||||||
const {
|
const {
|
||||||
useErrorHandle,
|
useErrorHandle,
|
||||||
showLogo,
|
showLogo,
|
||||||
|
multiTabsSetting: { show: showTab },
|
||||||
headerSetting: {
|
headerSetting: {
|
||||||
theme: headerTheme,
|
theme: headerTheme,
|
||||||
useLockPage,
|
useLockPage,
|
||||||
@ -114,11 +123,17 @@ export default defineComponent({
|
|||||||
{() => (
|
{() => (
|
||||||
<>
|
<>
|
||||||
<div class="layout-header__content ">
|
<div class="layout-header__content ">
|
||||||
{showLogo && !isSidebarType && <Logo class={`layout-header__logo`} />}
|
{showLogo && !isSidebarType && (
|
||||||
|
<Logo class={`layout-header__logo`} theme={headerTheme} />
|
||||||
{mode !== MenuModeEnum.HORIZONTAL && showBreadCrumb && !splitMenu && (
|
|
||||||
<LayoutBreadcrumb showIcon={showBreadCrumbIcon} />
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div class="layout-header__left">
|
||||||
|
{unref(showHeaderTrigger) && <LayoutTrigger theme={headerTheme} sider={false} />}
|
||||||
|
{mode !== MenuModeEnum.HORIZONTAL && showBreadCrumb && !splitMenu && (
|
||||||
|
<LayoutBreadcrumb showIcon={showBreadCrumbIcon} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
{unref(showTopMenu) && (
|
{unref(showTopMenu) && (
|
||||||
<div
|
<div
|
||||||
class={[`layout-header__menu `]}
|
class={[`layout-header__menu `]}
|
||||||
@ -193,7 +208,7 @@ export default defineComponent({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{showRedo && (
|
{showRedo && showTab && (
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
{{
|
{{
|
||||||
title: () => '刷新',
|
title: () => '刷新',
|
||||||
|
@ -68,9 +68,6 @@ export default defineComponent({
|
|||||||
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
|
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
genMenus();
|
|
||||||
});
|
|
||||||
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
|
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
|
||||||
|
|
||||||
// watch(
|
// watch(
|
||||||
@ -90,6 +87,7 @@ export default defineComponent({
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[() => permissionStore.getLastBuildMenuTimeState, permissionStore.getBackMenuListState],
|
[() => permissionStore.getLastBuildMenuTimeState, permissionStore.getBackMenuListState],
|
||||||
() => {
|
() => {
|
||||||
@ -112,7 +110,7 @@ export default defineComponent({
|
|||||||
if (!children) {
|
if (!children) {
|
||||||
appStore.commitProjectConfigState({
|
appStore.commitProjectConfigState({
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
show: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
flatMenusRef.value = [];
|
flatMenusRef.value = [];
|
||||||
@ -122,7 +120,7 @@ export default defineComponent({
|
|||||||
const flatChildren = await getFlatChildrenMenus(children);
|
const flatChildren = await getFlatChildrenMenus(children);
|
||||||
appStore.commitProjectConfigState({
|
appStore.commitProjectConfigState({
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
show: true,
|
hidden: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
flatMenusRef.value = flatChildren;
|
flatMenusRef.value = flatChildren;
|
||||||
@ -193,6 +191,10 @@ export default defineComponent({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
genMenus();
|
||||||
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const {
|
const {
|
||||||
showLogo,
|
showLogo,
|
||||||
@ -229,7 +231,11 @@ export default defineComponent({
|
|||||||
{{
|
{{
|
||||||
header: () =>
|
header: () =>
|
||||||
isShowLogo && (
|
isShowLogo && (
|
||||||
<Logo showTitle={!collapsed} class={[`layout-menu__logo`, themeData]} />
|
<Logo
|
||||||
|
showTitle={!collapsed}
|
||||||
|
class={[`layout-menu__logo`, themeData]}
|
||||||
|
theme={themeData}
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
</BasicMenu>
|
</BasicMenu>
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { computed, defineComponent, nextTick, onMounted, ref, unref } from 'vue';
|
import { computed, defineComponent, nextTick, onMounted, ref, unref } from 'vue';
|
||||||
|
|
||||||
import { Layout } from 'ant-design-vue';
|
import { Layout } from 'ant-design-vue';
|
||||||
import SideBarTrigger from './SideBarTrigger';
|
import LayoutTrigger from './LayoutTrigger';
|
||||||
import { menuStore } from '/@/store/modules/menu';
|
import { menuStore } from '/@/store/modules/menu';
|
||||||
|
|
||||||
// import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png';
|
// import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png';
|
||||||
// import lightMiniImg from '/@/assets/images/sidebar/light-mini.png';
|
// import lightMiniImg from '/@/assets/images/sidebar/light-mini.png';
|
||||||
// import lightImg from '/@/assets/images/sidebar/light.png';
|
// import lightImg from '/@/assets/images/sidebar/light.png';
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum, MenuSplitTyeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
|
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
|
||||||
import { useDebounce } from '/@/hooks/core/useDebounce';
|
import { useDebounce } from '/@/hooks/core/useDebounce';
|
||||||
import LayoutMenu from './LayoutMenu';
|
import LayoutMenu from './LayoutMenu';
|
||||||
@ -133,6 +133,25 @@ export default defineComponent({
|
|||||||
return unref(brokenRef) ? 0 : unref(getMiniWidth);
|
return unref(brokenRef) ? 0 : unref(getMiniWidth);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showTrigger = computed(() => {
|
||||||
|
const {
|
||||||
|
menuSetting: { trigger },
|
||||||
|
} = unref(getProjectConfigRef);
|
||||||
|
return trigger !== TriggerEnum.NONE && trigger === TriggerEnum.FOOTER;
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleSiderClick(e: ChangeEvent) {
|
||||||
|
if (!e || !e.target || e.target.className !== 'basic-menu__content') return;
|
||||||
|
|
||||||
|
const { collapsed, show } = appStore.getProjectConfig.menuSetting;
|
||||||
|
if (!collapsed || !show) return;
|
||||||
|
appStore.commitProjectConfigState({
|
||||||
|
menuSetting: {
|
||||||
|
collapsed: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderDragLine() {
|
function renderDragLine() {
|
||||||
const { menuSetting: { hasDrag = true } = {} } = unref(getProjectConfigRef);
|
const { menuSetting: { hasDrag = true } = {} } = unref(getProjectConfigRef);
|
||||||
return (
|
return (
|
||||||
@ -149,8 +168,22 @@ export default defineComponent({
|
|||||||
menuSetting: { theme, split: splitMenu },
|
menuSetting: { theme, split: splitMenu },
|
||||||
} = unref(getProjectConfigRef);
|
} = unref(getProjectConfigRef);
|
||||||
const { getCollapsedState, getMenuWidthState } = menuStore;
|
const { getCollapsedState, getMenuWidthState } = menuStore;
|
||||||
|
|
||||||
|
const triggerDom = unref(showTrigger)
|
||||||
|
? {
|
||||||
|
trigger: () => <LayoutTrigger />,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
|
const triggerAttr = unref(showTrigger)
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
trigger: null,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Sider
|
<Layout.Sider
|
||||||
|
onClick={handleSiderClick}
|
||||||
onCollapse={onCollapseChange}
|
onCollapse={onCollapseChange}
|
||||||
breakpoint="md"
|
breakpoint="md"
|
||||||
width={getMenuWidthState}
|
width={getMenuWidthState}
|
||||||
@ -161,9 +194,10 @@ export default defineComponent({
|
|||||||
class="layout-sidebar"
|
class="layout-sidebar"
|
||||||
ref={sideRef}
|
ref={sideRef}
|
||||||
onBreakpoint={handleBreakpoint}
|
onBreakpoint={handleBreakpoint}
|
||||||
|
{...triggerAttr}
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
trigger: () => <SideBarTrigger />,
|
...triggerDom,
|
||||||
default: () => (
|
default: () => (
|
||||||
<>
|
<>
|
||||||
<LayoutMenu
|
<LayoutMenu
|
||||||
|
43
src/layouts/default/LayoutTrigger.tsx
Normal file
43
src/layouts/default/LayoutTrigger.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import {
|
||||||
|
DoubleRightOutlined,
|
||||||
|
DoubleLeftOutlined,
|
||||||
|
MenuUnfoldOutlined,
|
||||||
|
MenuFoldOutlined,
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
// store
|
||||||
|
import { menuStore } from '/@/store/modules/menu';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutTrigger',
|
||||||
|
props: {
|
||||||
|
sider: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
function toggleMenu() {
|
||||||
|
menuStore.commitCollapsedState(!menuStore.getCollapsedState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const siderTrigger = menuStore.getCollapsedState ? (
|
||||||
|
<DoubleRightOutlined />
|
||||||
|
) : (
|
||||||
|
<DoubleLeftOutlined />
|
||||||
|
);
|
||||||
|
if (props.sider) return siderTrigger;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span class={['layout-trigger', props.theme]} onClick={toggleMenu}>
|
||||||
|
{menuStore.getCollapsedState ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@ -1,12 +0,0 @@
|
|||||||
import { DoubleRightOutlined, DoubleLeftOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
// store
|
|
||||||
import { menuStore } from '/@/store/modules/menu';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'SideBarTrigger',
|
|
||||||
setup() {
|
|
||||||
return () => (menuStore.getCollapsedState ? <DoubleRightOutlined /> : <DoubleLeftOutlined />);
|
|
||||||
},
|
|
||||||
});
|
|
@ -17,11 +17,10 @@
|
|||||||
&__main {
|
&__main {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// overflow: hidden;
|
|
||||||
// overflow: auto;
|
|
||||||
|
|
||||||
&.fixed {
|
&.fixed {
|
||||||
overflow: auto;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.fixed.lock {
|
&.fixed.lock {
|
||||||
@ -373,9 +372,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-breadcrumb {
|
.layout-header__left {
|
||||||
padding: 0 16px;
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.layout-trigger {
|
||||||
|
padding: 4px 10px 0 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.light {
|
||||||
|
&:hover {
|
||||||
|
background: @header-light-bg-hover-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
fill: #000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark {
|
||||||
|
&:hover {
|
||||||
|
background: @header-dark-bg-hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout-breadcrumb {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-layout-sider-trigger {
|
.ant-layout-sider-trigger {
|
||||||
|
@ -73,7 +73,7 @@ export default defineComponent({
|
|||||||
showSettingButton,
|
showSettingButton,
|
||||||
multiTabsSetting: { show: showTabs },
|
multiTabsSetting: { show: showTabs },
|
||||||
headerSetting: { fixed },
|
headerSetting: { fixed },
|
||||||
menuSetting: { split, show },
|
menuSetting: { split, hidden },
|
||||||
} = unref(getProjectConfigRef);
|
} = unref(getProjectConfigRef);
|
||||||
|
|
||||||
const fixedHeaderCls = fixed
|
const fixedHeaderCls = fixed
|
||||||
@ -82,7 +82,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
const { isLock } = getLockInfo;
|
const { isLock } = getLockInfo;
|
||||||
|
|
||||||
const showSideBar = split ? show : true;
|
const showSideBar = split ? hidden : true;
|
||||||
return (
|
return (
|
||||||
<Layout class="default-layout relative">
|
<Layout class="default-layout relative">
|
||||||
{() => (
|
{() => (
|
||||||
@ -107,9 +107,7 @@ export default defineComponent({
|
|||||||
unref(showHeaderRef) && <LayoutHeader />}
|
unref(showHeaderRef) && <LayoutHeader />}
|
||||||
|
|
||||||
{showTabs && !unref(getFullContent) && (
|
{showTabs && !unref(getFullContent) && (
|
||||||
<Layout.Header class={`default-layout__tabs`}>
|
<MultipleTabs class={`default-layout__tabs`} />
|
||||||
{() => <MultipleTabs />}
|
|
||||||
</Layout.Header>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{useOpenBackTop && <BackTop target={getTarget} />}
|
{useOpenBackTop && <BackTop target={getTarget} />}
|
||||||
|
@ -2,7 +2,13 @@ import { defineComponent, computed, unref, ref } from 'vue';
|
|||||||
import { BasicDrawer } from '/@/components/Drawer/index';
|
import { BasicDrawer } from '/@/components/Drawer/index';
|
||||||
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
||||||
import Button from '/@/components/Button/index.vue';
|
import Button from '/@/components/Button/index.vue';
|
||||||
import { MenuModeEnum, MenuTypeEnum, MenuThemeEnum, TopMenuAlignEnum } from '/@/enums/menuEnum';
|
import {
|
||||||
|
MenuModeEnum,
|
||||||
|
MenuTypeEnum,
|
||||||
|
MenuThemeEnum,
|
||||||
|
TopMenuAlignEnum,
|
||||||
|
TriggerEnum,
|
||||||
|
} from '/@/enums/menuEnum';
|
||||||
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
import { ContentEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||||
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||||
import { appStore } from '/@/store/modules/app';
|
import { appStore } from '/@/store/modules/app';
|
||||||
@ -23,41 +29,49 @@ const themeOptions = [
|
|||||||
{
|
{
|
||||||
value: MenuThemeEnum.LIGHT,
|
value: MenuThemeEnum.LIGHT,
|
||||||
label: '亮色',
|
label: '亮色',
|
||||||
key: MenuThemeEnum.LIGHT,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: MenuThemeEnum.DARK,
|
value: MenuThemeEnum.DARK,
|
||||||
label: '暗色',
|
label: '暗色',
|
||||||
key: MenuThemeEnum.DARK,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const contentModeOptions = [
|
const contentModeOptions = [
|
||||||
{
|
{
|
||||||
value: ContentEnum.FULL,
|
value: ContentEnum.FULL,
|
||||||
label: '流式',
|
label: '流式',
|
||||||
key: ContentEnum.FULL,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: ContentEnum.FIXED,
|
value: ContentEnum.FIXED,
|
||||||
label: '定宽',
|
label: '定宽',
|
||||||
key: ContentEnum.FIXED,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const topMenuAlignOptions = [
|
const topMenuAlignOptions = [
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.CENTER,
|
value: TopMenuAlignEnum.CENTER,
|
||||||
label: '居中',
|
label: '居中',
|
||||||
key: TopMenuAlignEnum.CENTER,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.START,
|
value: TopMenuAlignEnum.START,
|
||||||
label: '居左',
|
label: '居左',
|
||||||
key: TopMenuAlignEnum.START,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: TopMenuAlignEnum.END,
|
value: TopMenuAlignEnum.END,
|
||||||
label: '居右',
|
label: '居右',
|
||||||
key: TopMenuAlignEnum.END,
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const menuTriggerOptions = [
|
||||||
|
{
|
||||||
|
value: TriggerEnum.NONE,
|
||||||
|
label: '不显示',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TriggerEnum.FOOTER,
|
||||||
|
label: '底部',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: TriggerEnum.HEADER,
|
||||||
|
label: '顶部',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -181,7 +195,7 @@ export default defineComponent({
|
|||||||
baseHandler('splitMenu', e);
|
baseHandler('splitMenu', e);
|
||||||
},
|
},
|
||||||
def: split,
|
def: split,
|
||||||
disabled: !unref(getShowMenuRef),
|
disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX,
|
||||||
}),
|
}),
|
||||||
renderSelectItem('顶栏主题', {
|
renderSelectItem('顶栏主题', {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
@ -215,6 +229,7 @@ export default defineComponent({
|
|||||||
menuWidth,
|
menuWidth,
|
||||||
topMenuAlign,
|
topMenuAlign,
|
||||||
collapsedShowTitle,
|
collapsedShowTitle,
|
||||||
|
trigger,
|
||||||
} = {},
|
} = {},
|
||||||
} = appStore.getProjectConfig;
|
} = appStore.getProjectConfig;
|
||||||
return [
|
return [
|
||||||
@ -262,6 +277,13 @@ export default defineComponent({
|
|||||||
options: topMenuAlignOptions,
|
options: topMenuAlignOptions,
|
||||||
disabled: !unref(getShowHeaderRef),
|
disabled: !unref(getShowHeaderRef),
|
||||||
}),
|
}),
|
||||||
|
renderSelectItem('菜单折叠按钮', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler('menuTrigger', e);
|
||||||
|
},
|
||||||
|
def: trigger,
|
||||||
|
options: menuTriggerOptions,
|
||||||
|
}),
|
||||||
renderSelectItem('内容区域宽度', {
|
renderSelectItem('内容区域宽度', {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler('contentMode', e);
|
baseHandler('contentMode', e);
|
||||||
@ -298,7 +320,7 @@ export default defineComponent({
|
|||||||
disabled={!unref(getShowMenuRef)}
|
disabled={!unref(getShowMenuRef)}
|
||||||
defaultValue={menuWidth}
|
defaultValue={menuWidth}
|
||||||
formatter={(value: string) => `${parseInt(value)}px`}
|
formatter={(value: string) => `${parseInt(value)}px`}
|
||||||
onChange={(e) => {
|
onChange={(e: any) => {
|
||||||
baseHandler('menuWidth', e);
|
baseHandler('menuWidth', e);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -424,13 +446,21 @@ export default defineComponent({
|
|||||||
if (event === 'layout') {
|
if (event === 'layout') {
|
||||||
const { mode, type, split } = value;
|
const { mode, type, split } = value;
|
||||||
const splitOpt = split === undefined ? { split } : {};
|
const splitOpt = split === undefined ? { split } : {};
|
||||||
|
let headerSetting = {};
|
||||||
|
if (type === MenuTypeEnum.TOP_MENU) {
|
||||||
|
headerSetting = {
|
||||||
|
theme: MenuThemeEnum.DARK,
|
||||||
|
};
|
||||||
|
}
|
||||||
config = {
|
config = {
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
mode,
|
mode,
|
||||||
type,
|
type,
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
|
show: true,
|
||||||
...splitOpt,
|
...splitOpt,
|
||||||
},
|
},
|
||||||
|
headerSetting,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (event === 'hasDrag') {
|
if (event === 'hasDrag') {
|
||||||
@ -440,6 +470,13 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (event === 'menuTrigger') {
|
||||||
|
config = {
|
||||||
|
menuSetting: {
|
||||||
|
trigger: value,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
if (event === 'openPageLoading') {
|
if (event === 'openPageLoading') {
|
||||||
config = {
|
config = {
|
||||||
openPageLoading: value,
|
openPageLoading: value,
|
||||||
@ -647,7 +684,7 @@ export default defineComponent({
|
|||||||
<Switch
|
<Switch
|
||||||
{...opt}
|
{...opt}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={(e) => {
|
onChange={(e: any) => {
|
||||||
handler && handler(e);
|
handler && handler(e);
|
||||||
}}
|
}}
|
||||||
checkedChildren="开"
|
checkedChildren="开"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { ProjectConfig } from '/@/types/config';
|
import type { ProjectConfig } from '/@/types/config';
|
||||||
|
|
||||||
import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum } from '/@/enums/menuEnum';
|
import { MenuTypeEnum, MenuThemeEnum, MenuModeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||||
import { primaryColor } from '../../build/config/lessModifyVars';
|
import { primaryColor } from '../../build/config/lessModifyVars';
|
||||||
import { isProdMode } from '/@/utils/env';
|
import { isProdMode } from '/@/utils/env';
|
||||||
@ -23,6 +23,7 @@ const setting: ProjectConfig = {
|
|||||||
// 是否显示logo
|
// 是否显示logo
|
||||||
showLogo: true,
|
showLogo: true,
|
||||||
|
|
||||||
|
// 头部配置
|
||||||
headerSetting: {
|
headerSetting: {
|
||||||
fixed: true,
|
fixed: true,
|
||||||
// 是否显示顶部
|
// 是否显示顶部
|
||||||
@ -50,8 +51,10 @@ const setting: ProjectConfig = {
|
|||||||
collapsedShowTitle: false,
|
collapsedShowTitle: false,
|
||||||
// 是否可拖拽
|
// 是否可拖拽
|
||||||
hasDrag: false,
|
hasDrag: false,
|
||||||
// 是否显示
|
// 是否显示 没有dom
|
||||||
show: true,
|
show: true,
|
||||||
|
// 是否显示 有dom
|
||||||
|
hidden: false,
|
||||||
// 是否显示搜索框
|
// 是否显示搜索框
|
||||||
showSearch: true,
|
showSearch: true,
|
||||||
// 菜单宽度
|
// 菜单宽度
|
||||||
@ -67,7 +70,9 @@ const setting: ProjectConfig = {
|
|||||||
// 顶部菜单布局
|
// 顶部菜单布局
|
||||||
topMenuAlign: 'center',
|
topMenuAlign: 'center',
|
||||||
// 折叠菜单时候隐藏搜索框
|
// 折叠菜单时候隐藏搜索框
|
||||||
collapsedShowSearch: true,
|
collapsedShowSearch: false,
|
||||||
|
// 折叠触发器的位置
|
||||||
|
trigger: TriggerEnum.HEADER,
|
||||||
},
|
},
|
||||||
// 消息配置
|
// 消息配置
|
||||||
messageSetting: {
|
messageSetting: {
|
||||||
|
4
src/types/config.d.ts
vendored
4
src/types/config.d.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
// 左侧菜单, 顶部菜单
|
// 左侧菜单, 顶部菜单
|
||||||
import { MenuTypeEnum, MenuModeEnum, MenuThemeEnum } from '/@/enums/menuEnum';
|
import { MenuTypeEnum, MenuModeEnum, MenuThemeEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||||
import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
import { ContentEnum, PermissionModeEnum, RouterTransitionEnum } from '/@/enums/appEnum';
|
||||||
|
|
||||||
export interface MessageSetting {
|
export interface MessageSetting {
|
||||||
@ -15,6 +15,7 @@ export interface MenuSetting {
|
|||||||
hasDrag: boolean;
|
hasDrag: boolean;
|
||||||
showSearch: boolean;
|
showSearch: boolean;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
|
hidden: boolean;
|
||||||
split: boolean;
|
split: boolean;
|
||||||
menuWidth: number;
|
menuWidth: number;
|
||||||
mode: MenuModeEnum;
|
mode: MenuModeEnum;
|
||||||
@ -22,6 +23,7 @@ export interface MenuSetting {
|
|||||||
theme: MenuThemeEnum;
|
theme: MenuThemeEnum;
|
||||||
topMenuAlign: 'start' | 'center' | 'end';
|
topMenuAlign: 'start' | 'center' | 'end';
|
||||||
collapsedShowSearch: boolean;
|
collapsedShowSearch: boolean;
|
||||||
|
trigger: TriggerEnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MultiTabsSetting {
|
export interface MultiTabsSetting {
|
||||||
|
@ -42,6 +42,7 @@ export function genRouteModule(moduleList: AppRouteModule[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 动态引入
|
// 动态引入
|
||||||
|
// TODO 错误写法
|
||||||
function asyncImportRoute(routes: AppRouteRecordRaw[]) {
|
function asyncImportRoute(routes: AppRouteRecordRaw[]) {
|
||||||
routes.forEach((item) => {
|
routes.forEach((item) => {
|
||||||
let { component } = item;
|
let { component } = item;
|
||||||
|
@ -119,12 +119,7 @@ const viteConfig: UserConfig = {
|
|||||||
},
|
},
|
||||||
// The package will be recompiled using rollup, and the new package compiled into the esm module specification will be put into node_modules/.vite_opt_cache
|
// The package will be recompiled using rollup, and the new package compiled into the esm module specification will be put into node_modules/.vite_opt_cache
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: [
|
include: ['echarts/map/js/china', 'ant-design-vue/es/locale/zh_CN', '@ant-design/icons-vue'],
|
||||||
'echarts/map/js/china',
|
|
||||||
'ant-design-vue/es/locale/zh_CN',
|
|
||||||
'@ant-design/icons-vue',
|
|
||||||
'moment/locale/zh-cn',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Local cross-domain proxy
|
// Local cross-domain proxy
|
||||||
|
@ -5513,7 +5513,7 @@ modify-values@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
|
resolved "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
|
||||||
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
|
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
|
||||||
|
|
||||||
moment@^2.27.0:
|
moment@^2.27.0, moment@^2.29.1:
|
||||||
version "2.29.1"
|
version "2.29.1"
|
||||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
|
Loading…
Reference in New Issue
Block a user