mirror of
https://github.com/vbenjs/gf-vben-admin.git
synced 2025-02-02 19:08:40 +08:00
refactor: refactor layout
This commit is contained in:
parent
25d43a5f7c
commit
0692b4798c
@ -1,5 +1,9 @@
|
||||
## Wip
|
||||
|
||||
### ✨ Refactor
|
||||
|
||||
- 重构整体 layout。更改代码实现方式。代码更精简
|
||||
|
||||
### ✨ Features
|
||||
|
||||
- 缓存可以配置是否加密
|
||||
@ -7,6 +11,7 @@
|
||||
### 🎫 Chores
|
||||
|
||||
- 移除 messageSetting 配置
|
||||
- 暂时删除 `@vueuse/core`.等稳定后在集成。目前不太稳定。
|
||||
|
||||
## 2.0.0-rc.11 (2020-11-18)
|
||||
|
||||
|
@ -154,15 +154,17 @@ const globTransform = function (config: SharedConfig): Transform {
|
||||
|
||||
const groups: Array<string>[] = [];
|
||||
const replaceFiles = files.map((f, i) => {
|
||||
const fileNameWithAlias = resolver.fileToRequest(f);
|
||||
|
||||
const file = bareExporter + fileNameWithAlias + bareExporter;
|
||||
const filePath = resolver.fileToRequest(f);
|
||||
const file = bareExporter + filePath + bareExporter;
|
||||
|
||||
if (isLocale) {
|
||||
const globrexRes = globrex(globPath, { extended: true, globstar: true });
|
||||
|
||||
// Get segments for files like an en/system ch/modules for:
|
||||
// ['en', 'system'] ['ch', 'modules']
|
||||
|
||||
// TODO The window system and mac system path are inconsistent?
|
||||
const fileNameWithAlias = filePath.replace(/^(\/src\/)/, '/@/');
|
||||
const matchedGroups = globrexRes.regex.exec(fileNameWithAlias);
|
||||
|
||||
if (matchedGroups && matchedGroups.length) {
|
||||
|
@ -22,7 +22,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^2.0.0-rc.2",
|
||||
"@vueuse/core": "^4.0.0-rc.3",
|
||||
"ant-design-vue": "2.0.0-beta.15",
|
||||
"apexcharts": "3.22.0",
|
||||
"axios": "^0.21.0",
|
||||
|
@ -1,7 +1,11 @@
|
||||
<template>
|
||||
<div class="app-logo anticon" :class="theme" @click="handleGoHome">
|
||||
<div
|
||||
class="app-logo anticon"
|
||||
:class="{ theme, 'collapsed-show-title': getCollapsedShowTitle }"
|
||||
@click="handleGoHome"
|
||||
>
|
||||
<img src="/@/assets/images/logo.png" />
|
||||
<div class="app-logo__title ml-2 ellipsis">{{ globSetting.title }}</div>
|
||||
<div class="app-logo__title ml-2 ellipsis" v-show="showTitle">{{ globSetting.title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
@ -10,6 +14,7 @@
|
||||
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { useGo } from '/@/hooks/web/usePage';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
|
||||
import { PageEnum } from '/@/enums/pageEnum';
|
||||
|
||||
@ -22,8 +27,13 @@
|
||||
theme: {
|
||||
type: String as PropType<string>,
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { getCollapsedShowTitle } = useMenuSetting();
|
||||
const globSetting = useGlobSetting();
|
||||
const go = useGo();
|
||||
|
||||
@ -34,6 +44,7 @@
|
||||
return {
|
||||
handleGoHome,
|
||||
globSetting,
|
||||
getCollapsedShowTitle,
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -44,9 +55,13 @@
|
||||
.app-logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 16px;
|
||||
padding-left: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&.collapsed-show-title {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
&.light {
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
}
|
||||
@ -64,6 +79,7 @@
|
||||
font-weight: 700;
|
||||
opacity: 0;
|
||||
transition: all 0.5s;
|
||||
|
||||
.respond-to(medium,{
|
||||
opacity: 1;
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ export default defineComponent({
|
||||
? `${opt.wrapClassName} ${prefixCls}__detail`
|
||||
: `${prefixCls}__detail`;
|
||||
if (!opt.getContainer) {
|
||||
opt.getContainer = `.default-layout__main`;
|
||||
opt.getContainer = '.layout-content';
|
||||
}
|
||||
}
|
||||
return opt;
|
||||
|
@ -80,7 +80,7 @@ export default defineComponent({
|
||||
offset += 46;
|
||||
}
|
||||
return {
|
||||
height: `calc(100% - ${offset - 12}px)`,
|
||||
height: `calc(100% - ${offset}px)`,
|
||||
position: 'relative',
|
||||
overflowY: 'auto',
|
||||
};
|
||||
|
@ -219,11 +219,7 @@ export default defineComponent({
|
||||
emit('register', modalMethods, uuid);
|
||||
|
||||
return () => (
|
||||
<Modal
|
||||
onCancel={handleCancel}
|
||||
getContainer={() => document.querySelector('.default-layout__main')}
|
||||
{...{ ...attrs, ...props, ...unref(getProps) }}
|
||||
>
|
||||
<Modal onCancel={handleCancel} {...{ ...attrs, ...props, ...unref(getProps) }}>
|
||||
{{
|
||||
footer: () => renderFooter(),
|
||||
closeIcon: () => renderClose(),
|
||||
|
@ -33,6 +33,7 @@ export function useModal(): UseModalReturnType {
|
||||
|
||||
modalRef.value = modalMethod;
|
||||
}
|
||||
|
||||
const getInstance = () => {
|
||||
const instance = unref(modalRef);
|
||||
if (!instance) {
|
||||
@ -50,6 +51,7 @@ export function useModal(): UseModalReturnType {
|
||||
getInstance().setModalProps({
|
||||
visible: visible,
|
||||
});
|
||||
|
||||
if (data) {
|
||||
dataTransferRef[unref(uidRef)] = openOnSet
|
||||
? {
|
||||
|
@ -43,7 +43,6 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe
|
||||
const tableEl: Element = table.$el;
|
||||
if (!tableEl) return;
|
||||
const headEl = tableEl.querySelector('.ant-table-thead ');
|
||||
// const layoutMain: Element | null = document.querySelector('.default-layout__main ');
|
||||
if (!headEl) return;
|
||||
|
||||
// 表格距离底部高度
|
||||
|
@ -35,7 +35,7 @@ html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.color-weak {
|
||||
filter: invert(80%);
|
||||
@ -160,9 +160,7 @@ object {
|
||||
vertical-align: baseline !important;
|
||||
}
|
||||
|
||||
#app,
|
||||
#app > div,
|
||||
.ant-layout {
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@ -170,8 +168,8 @@ object {
|
||||
.ant-layout {
|
||||
background: #f0f2f5;
|
||||
|
||||
&-content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
// &-content {
|
||||
// position: relative;
|
||||
// overflow: hidden;
|
||||
// }
|
||||
}
|
||||
|
@ -101,14 +101,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.reset-layout() {
|
||||
.ant-layout {
|
||||
background: #f1f1f6 !important;
|
||||
|
||||
&-content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
src/hooks/core/useContext.ts
Normal file
22
src/hooks/core/useContext.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { InjectionKey, provide, inject, reactive, readonly } from 'vue';
|
||||
|
||||
export const createContext = <T>(
|
||||
context: any,
|
||||
contextInjectKey: InjectionKey<T> = Symbol(),
|
||||
_readonly = true
|
||||
) => {
|
||||
const state = reactive({
|
||||
...context,
|
||||
});
|
||||
const provideData = _readonly ? readonly(state) : state;
|
||||
provide(contextInjectKey, provideData);
|
||||
};
|
||||
|
||||
export const useContext = <T>(
|
||||
contextInjectKey: InjectionKey<T> = Symbol(),
|
||||
defaultValue?: any,
|
||||
_readonly = true
|
||||
): T => {
|
||||
const state = inject(contextInjectKey, defaultValue || {});
|
||||
return _readonly ? readonly(state) : state;
|
||||
};
|
@ -7,20 +7,50 @@ import { appStore } from '/@/store/modules/app';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
|
||||
import { MenuModeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
export function useHeaderSetting() {
|
||||
const { getShow: getShowMultipleTab } = useMultipleTabSetting();
|
||||
const { getMode, getSplit, getShowHeaderTrigger, getIsSidebarType } = useMenuSetting();
|
||||
const { getFullContent } = useFullContent();
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
const {
|
||||
getMenuMode,
|
||||
getSplit,
|
||||
getShowHeaderTrigger,
|
||||
getIsSidebarType,
|
||||
getIsTopMenu,
|
||||
} = useMenuSetting();
|
||||
const { getShowBreadCrumb, getShowLogo } = useRootSetting();
|
||||
|
||||
const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
|
||||
|
||||
const getShowFullHeaderRef = computed(() => {
|
||||
return (
|
||||
!unref(getFullContent) &&
|
||||
unref(getShowMixHeaderRef) &&
|
||||
unref(getShowHeader) &&
|
||||
!unref(getIsTopMenu)
|
||||
);
|
||||
});
|
||||
|
||||
const getShowInsetHeaderRef = computed(() => {
|
||||
const need = !unref(getFullContent) && unref(getShowHeader);
|
||||
return (need && !unref(getShowMixHeaderRef)) || (need && unref(getIsTopMenu));
|
||||
});
|
||||
|
||||
// Get header configuration
|
||||
const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting);
|
||||
|
||||
const getShowDoc = computed(() => unref(getHeaderSetting).showDoc);
|
||||
|
||||
const getTheme = computed(() => unref(getHeaderSetting).theme);
|
||||
const getHeaderTheme = computed(() => unref(getHeaderSetting).theme);
|
||||
|
||||
const getShowHeader = computed(() => unref(getHeaderSetting).show);
|
||||
|
||||
const getFixed = computed(() => unref(getHeaderSetting).fixed);
|
||||
|
||||
const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
|
||||
|
||||
const getShowRedo = computed(() => unref(getHeaderSetting).showRedo && unref(getShowMultipleTab));
|
||||
|
||||
@ -30,9 +60,11 @@ export function useHeaderSetting() {
|
||||
|
||||
const getShowNotice = computed(() => unref(getHeaderSetting).showNotice);
|
||||
|
||||
const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
|
||||
|
||||
const getShowBread = computed(() => {
|
||||
return (
|
||||
unref(getMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
|
||||
unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
|
||||
);
|
||||
});
|
||||
|
||||
@ -55,7 +87,7 @@ export function useHeaderSetting() {
|
||||
getHeaderSetting,
|
||||
|
||||
getShowDoc,
|
||||
getTheme,
|
||||
getHeaderTheme,
|
||||
getShowRedo,
|
||||
getUseLockPage,
|
||||
getShowFullScreen,
|
||||
@ -63,5 +95,12 @@ export function useHeaderSetting() {
|
||||
getShowBread,
|
||||
getShowContent,
|
||||
getShowHeaderLogo,
|
||||
getShowHeader,
|
||||
getFixed,
|
||||
getShowMixHeaderRef,
|
||||
getShowFullHeaderRef,
|
||||
getShowInsetHeaderRef,
|
||||
getUnFixedAndFull,
|
||||
getHeaderBgColor,
|
||||
};
|
||||
}
|
||||
|
@ -11,24 +11,28 @@ export function useMenuSetting() {
|
||||
// Get menu configuration
|
||||
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
|
||||
|
||||
const getMiniWidth = computed(() => unref(getMenuSetting).menuWidth);
|
||||
|
||||
const getCollapsed = computed(() => unref(getMenuSetting).collapsed);
|
||||
|
||||
const getType = computed(() => unref(getMenuSetting).type);
|
||||
const getMenuType = computed(() => unref(getMenuSetting).type);
|
||||
|
||||
const getMode = computed(() => unref(getMenuSetting).mode);
|
||||
const getMenuMode = computed(() => unref(getMenuSetting).mode);
|
||||
|
||||
const getShow = computed(() => unref(getMenuSetting).show);
|
||||
const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
|
||||
|
||||
const getShowMenu = computed(() => unref(getMenuSetting).show);
|
||||
|
||||
const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
|
||||
|
||||
const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
|
||||
|
||||
const getTrigger = computed(() => unref(getMenuSetting).trigger);
|
||||
|
||||
const getTheme = computed(() => unref(getMenuSetting).theme);
|
||||
const getMenuTheme = computed(() => unref(getMenuSetting).theme);
|
||||
|
||||
const getSplit = computed(() => unref(getMenuSetting).split);
|
||||
|
||||
const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);
|
||||
|
||||
const getHasDrag = computed(() => unref(getMenuSetting).hasDrag);
|
||||
|
||||
const getAccordion = computed(() => unref(getMenuSetting).accordion);
|
||||
@ -39,17 +43,19 @@ export function useMenuSetting() {
|
||||
|
||||
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
|
||||
|
||||
const getIsSidebarType = computed(() => unref(getType) === MenuTypeEnum.SIDEBAR);
|
||||
const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
|
||||
|
||||
const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
|
||||
|
||||
const getShowTopMenu = computed(() => {
|
||||
return unref(getMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
|
||||
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
|
||||
});
|
||||
|
||||
const getShowHeaderTrigger = computed(() => {
|
||||
if (
|
||||
unref(getType) === MenuTypeEnum.TOP_MENU ||
|
||||
!unref(getShow) ||
|
||||
!unref(getMenuSetting).hidden
|
||||
unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
|
||||
!unref(getShowMenu) ||
|
||||
!unref(getMenuHidden)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -60,12 +66,16 @@ export function useMenuSetting() {
|
||||
const getShowSearch = computed(() => {
|
||||
return (
|
||||
unref(getMenuSetting).showSearch &&
|
||||
!(unref(getType) === MenuTypeEnum.MIX && unref(getMode) === MenuModeEnum.HORIZONTAL)
|
||||
!(unref(getMenuType) === MenuTypeEnum.MIX && unref(getMenuMode) === MenuModeEnum.HORIZONTAL)
|
||||
);
|
||||
});
|
||||
|
||||
const getIsHorizontal = computed(() => {
|
||||
return unref(getMode) === MenuModeEnum.HORIZONTAL;
|
||||
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
|
||||
});
|
||||
|
||||
const getRealWidth = computed(() => {
|
||||
return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
|
||||
});
|
||||
|
||||
const getMiniWidthNumber = computed(() => {
|
||||
@ -74,8 +84,8 @@ export function useMenuSetting() {
|
||||
});
|
||||
|
||||
const getCalcContentWidth = computed(() => {
|
||||
const width = unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMiniWidth);
|
||||
return `calc(100% - ${width}px)`;
|
||||
const width = unref(getIsTopMenu) || !unref(getShowMenu) ? 0 : unref(getRealWidth);
|
||||
return `calc(100% - ${unref(width)}px)`;
|
||||
});
|
||||
|
||||
// Set menu configuration
|
||||
@ -94,18 +104,19 @@ export function useMenuSetting() {
|
||||
|
||||
toggleCollapsed,
|
||||
|
||||
getMenuFixed,
|
||||
getMenuSetting,
|
||||
getMiniWidth,
|
||||
getType,
|
||||
getMode,
|
||||
getShow,
|
||||
getRealWidth,
|
||||
getMenuType,
|
||||
getMenuMode,
|
||||
getShowMenu,
|
||||
getCollapsed,
|
||||
getMiniWidthNumber,
|
||||
getCalcContentWidth,
|
||||
getMenuWidth,
|
||||
getTrigger,
|
||||
getSplit,
|
||||
getTheme,
|
||||
getMenuTheme,
|
||||
getHasDrag,
|
||||
getIsHorizontal,
|
||||
getShowSearch,
|
||||
@ -116,5 +127,8 @@ export function useMenuSetting() {
|
||||
getShowTopMenu,
|
||||
getShowHeaderTrigger,
|
||||
getTopMenuAlign,
|
||||
getMenuHidden,
|
||||
getIsTopMenu,
|
||||
getMenuBgColor,
|
||||
};
|
||||
}
|
||||
|
@ -9,7 +9,9 @@ export function useMultipleTabSetting() {
|
||||
|
||||
const getMax = computed(() => unref(getMultipleTabSetting).max);
|
||||
|
||||
const getShow = computed(() => unref(getMultipleTabSetting).show);
|
||||
const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
|
||||
|
||||
const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick);
|
||||
|
||||
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
|
||||
appStore.commitProjectConfigState({ multiTabsSetting });
|
||||
@ -20,6 +22,7 @@ export function useMultipleTabSetting() {
|
||||
|
||||
getMultipleTabSetting,
|
||||
getMax,
|
||||
getShow,
|
||||
getShowMultipleTab,
|
||||
getShowQuick,
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import type { ProjectConfig } from '/@/types/config';
|
||||
import { computed, unref } from 'vue';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { ContentEnum } from '/@/enums/appEnum';
|
||||
|
||||
type RootSetting = Omit<
|
||||
ProjectConfig,
|
||||
@ -13,6 +14,8 @@ export function useRootSetting() {
|
||||
|
||||
const getOpenPageLoading = computed(() => unref(getRootSetting).openPageLoading);
|
||||
|
||||
const getPageLoading = computed(() => appStore.getPageLoading);
|
||||
|
||||
const getOpenRouterTransition = computed(() => unref(getRootSetting).openRouterTransition);
|
||||
|
||||
const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
|
||||
@ -25,12 +28,30 @@ export function useRootSetting() {
|
||||
|
||||
const getShowLogo = computed(() => unref(getRootSetting).showLogo);
|
||||
|
||||
const getContentMode = computed(() => unref(getRootSetting).contentMode);
|
||||
|
||||
const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop);
|
||||
|
||||
const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton);
|
||||
|
||||
const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle);
|
||||
|
||||
const getShowFooter = computed(() => unref(getRootSetting).showFooter);
|
||||
|
||||
const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb);
|
||||
|
||||
const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon);
|
||||
|
||||
const getFullContent = computed(() => unref(getRootSetting).fullContent);
|
||||
|
||||
const getColorWeak = computed(() => unref(getRootSetting).colorWeak);
|
||||
|
||||
const getGrayMode = computed(() => unref(getRootSetting).grayMode);
|
||||
|
||||
const getLayoutContentMode = computed(() =>
|
||||
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
|
||||
);
|
||||
|
||||
function setRootSetting(setting: RootSetting) {
|
||||
appStore.commitProjectConfigState(setting);
|
||||
}
|
||||
@ -38,7 +59,12 @@ export function useRootSetting() {
|
||||
return {
|
||||
setRootSetting,
|
||||
|
||||
getFullContent,
|
||||
getColorWeak,
|
||||
getGrayMode,
|
||||
getRootSetting,
|
||||
getLayoutContentMode,
|
||||
getPageLoading,
|
||||
getOpenPageLoading,
|
||||
getOpenRouterTransition,
|
||||
getOpenKeepAlive,
|
||||
@ -49,5 +75,9 @@ export function useRootSetting() {
|
||||
getUseErrorHandle,
|
||||
getShowBreadCrumb,
|
||||
getShowBreadCrumbIcon,
|
||||
getUseOpenBackTop,
|
||||
getShowSettingButton,
|
||||
getShowFooter,
|
||||
getContentMode,
|
||||
};
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { computed, defineComponent, unref } from 'vue';
|
||||
import { Layout } from 'ant-design-vue';
|
||||
import { FullLoading } from '/@/components/Loading/index';
|
||||
|
||||
import { RouterView } from 'vue-router';
|
||||
|
||||
import { ContentEnum } from '/@/enums/appEnum';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
export default defineComponent({
|
||||
name: 'DefaultLayoutContent',
|
||||
setup() {
|
||||
const getProjectConfigRef = computed(() => {
|
||||
return appStore.getProjectConfig;
|
||||
});
|
||||
|
||||
return () => {
|
||||
const { contentMode, openPageLoading } = unref(getProjectConfigRef);
|
||||
const { getPageLoading } = appStore;
|
||||
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
||||
return (
|
||||
<div class={[`default-layout__main`]}>
|
||||
{openPageLoading && (
|
||||
<FullLoading class={[`default-layout__loading`, !getPageLoading && 'hidden']} />
|
||||
)}
|
||||
<Layout.Content class={`layout-content ${wrapClass} `}>
|
||||
{() => <RouterView />}
|
||||
</Layout.Content>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import type { PropType } from 'vue';
|
||||
import type { PropType, FunctionalComponent } from 'vue';
|
||||
|
||||
import { defineComponent, unref } from 'vue';
|
||||
import {
|
||||
@ -10,6 +10,22 @@ import {
|
||||
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
|
||||
const SiderTrigger: FunctionalComponent = () => {
|
||||
const { getCollapsed } = useMenuSetting();
|
||||
return unref(getCollapsed) ? <DoubleRightOutlined /> : <DoubleLeftOutlined />;
|
||||
};
|
||||
|
||||
const HeaderTrigger: FunctionalComponent<{
|
||||
theme?: string;
|
||||
}> = (props) => {
|
||||
const { toggleCollapsed, getCollapsed } = useMenuSetting();
|
||||
return (
|
||||
<span class={['layout-trigger', props.theme]} onClick={toggleCollapsed}>
|
||||
{unref(getCollapsed) ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutTrigger',
|
||||
props: {
|
||||
@ -22,20 +38,8 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { toggleCollapsed, getCollapsed } = useMenuSetting();
|
||||
|
||||
return () => {
|
||||
const siderTrigger = unref(getCollapsed) ? <DoubleRightOutlined /> : <DoubleLeftOutlined />;
|
||||
|
||||
if (props.sider) {
|
||||
return siderTrigger;
|
||||
}
|
||||
|
||||
return (
|
||||
<span class={['layout-trigger', props.theme]} onClick={toggleCollapsed}>
|
||||
{unref(getCollapsed) ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||
</span>
|
||||
);
|
||||
return props.sider ? <SiderTrigger /> : <HeaderTrigger theme={props.theme} />;
|
||||
};
|
||||
},
|
||||
});
|
||||
|
21
src/layouts/default/content/index.less
Normal file
21
src/layouts/default/content/index.less
Normal file
@ -0,0 +1,21 @@
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.layout-content {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
|
||||
&.fixed {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
&__loading {
|
||||
position: fixed;
|
||||
z-index: @page-loading-z-index;
|
||||
|
||||
> .basic-loading {
|
||||
margin-bottom: 20%;
|
||||
}
|
||||
}
|
||||
}
|
26
src/layouts/default/content/index.tsx
Normal file
26
src/layouts/default/content/index.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import './index.less';
|
||||
|
||||
import { defineComponent, unref } from 'vue';
|
||||
import { FullLoading } from '/@/components/Loading/index';
|
||||
|
||||
import { RouterView } from 'vue-router';
|
||||
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutContent',
|
||||
setup() {
|
||||
const { getOpenPageLoading, getLayoutContentMode, getPageLoading } = useRootSetting();
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div class={['layout-content', unref(getLayoutContentMode)]}>
|
||||
{unref(getOpenPageLoading) && (
|
||||
<FullLoading class={[`layout-content__loading`, { hidden: !unref(getPageLoading) }]} />
|
||||
)}
|
||||
<RouterView />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
28
src/layouts/default/footer/index.less
Normal file
28
src/layouts/default/footer/index.less
Normal file
@ -0,0 +1,28 @@
|
||||
@normal-color: rgba(0, 0, 0, 0.45);
|
||||
|
||||
@hover-color: rgba(0, 0, 0, 0.85);
|
||||
|
||||
.layout-footer {
|
||||
color: @normal-color;
|
||||
text-align: center;
|
||||
|
||||
&__links {
|
||||
margin-bottom: 8px;
|
||||
|
||||
a {
|
||||
color: @normal-color;
|
||||
|
||||
&:hover {
|
||||
color: @hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.github {
|
||||
margin: 0 30px;
|
||||
|
||||
&:hover {
|
||||
color: @hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
src/layouts/default/footer/index.tsx
Normal file
31
src/layouts/default/footer/index.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import './index.less';
|
||||
|
||||
import { defineComponent } from 'vue';
|
||||
import { Layout } from 'ant-design-vue';
|
||||
|
||||
import { GithubFilled } from '@ant-design/icons-vue';
|
||||
|
||||
import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
|
||||
import { openWindow } from '/@/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutContent',
|
||||
setup() {
|
||||
return () => {
|
||||
return (
|
||||
<Layout.Footer class="layout-footer">
|
||||
{() => (
|
||||
<>
|
||||
<div class="layout-footer__links">
|
||||
<a onClick={() => openWindow(SITE_URL)}>在线预览</a>
|
||||
<GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
|
||||
<a onClick={() => openWindow(DOC_URL)}>在线文档</a>
|
||||
</div>
|
||||
<div>Copyright ©2020 Vben Admin</div>
|
||||
</>
|
||||
)}
|
||||
</Layout.Footer>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@ -1,13 +1,15 @@
|
||||
import './index.less';
|
||||
|
||||
import type { FunctionalComponent } from 'vue';
|
||||
|
||||
import { defineComponent, unref, computed, ref, nextTick } from 'vue';
|
||||
|
||||
import { Layout, Tooltip, Badge } from 'ant-design-vue';
|
||||
import { AppLogo } from '/@/components/Application';
|
||||
import UserDropdown from './UserDropdown';
|
||||
import LayoutMenu from '/@/layouts/default/menu/LayoutMenu';
|
||||
import LayoutMenu from '../menu';
|
||||
import LayoutBreadcrumb from './LayoutBreadcrumb';
|
||||
import LockAction from './LockActionItem';
|
||||
import LockAction from '../lock/LockAction';
|
||||
import LayoutTrigger from '../LayoutTrigger';
|
||||
import NoticeAction from './notice/NoticeActionItem.vue';
|
||||
import {
|
||||
@ -34,9 +36,30 @@ import { PageEnum } from '/@/enums/pageEnum';
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
import { Component } from '/@/components/types';
|
||||
|
||||
interface TooltipItemProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const TooltipItem: FunctionalComponent<TooltipItemProps> = (props, { slots }) => {
|
||||
return (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => props.title,
|
||||
default: () => slots.default?.(),
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutHeader',
|
||||
setup() {
|
||||
props: {
|
||||
fixed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
let logoEl: Element | null;
|
||||
|
||||
const logoWidthRef = ref(200);
|
||||
@ -48,7 +71,7 @@ export default defineComponent({
|
||||
const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();
|
||||
|
||||
const {
|
||||
getTheme,
|
||||
getHeaderTheme,
|
||||
getShowRedo,
|
||||
getUseLockPage,
|
||||
getShowFullScreen,
|
||||
@ -69,8 +92,7 @@ export default defineComponent({
|
||||
let width = 0;
|
||||
if (!logoEl) {
|
||||
logoEl = logoRef.value.$el;
|
||||
}
|
||||
if (logoEl) {
|
||||
} else {
|
||||
width += logoEl.clientWidth;
|
||||
}
|
||||
logoWidthRef.value = width + 80;
|
||||
@ -81,7 +103,7 @@ export default defineComponent({
|
||||
);
|
||||
|
||||
const headerClass = computed(() => {
|
||||
const theme = unref(getTheme);
|
||||
const theme = unref(getHeaderTheme);
|
||||
return theme ? `layout-header__header--${theme}` : '';
|
||||
});
|
||||
|
||||
@ -99,9 +121,6 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 锁定屏幕
|
||||
*/
|
||||
function handleLockPage() {
|
||||
openModal(true);
|
||||
}
|
||||
@ -111,13 +130,13 @@ export default defineComponent({
|
||||
return (
|
||||
<div class="layout-header__content ">
|
||||
{unref(getShowHeaderLogo) && (
|
||||
<AppLogo class={`layout-header__logo`} ref={logoRef} theme={unref(getTheme)} />
|
||||
<AppLogo class={`layout-header__logo`} ref={logoRef} theme={unref(getHeaderTheme)} />
|
||||
)}
|
||||
|
||||
{unref(getShowContent) && (
|
||||
<div class="layout-header__left">
|
||||
{unref(getShowHeaderTrigger) && (
|
||||
<LayoutTrigger theme={unref(getTheme)} sider={false} />
|
||||
<LayoutTrigger theme={unref(getHeaderTheme)} sider={false} />
|
||||
)}
|
||||
{unref(getShowBread) && <LayoutBreadcrumb showIcon={unref(getShowBreadCrumbIcon)} />}
|
||||
</div>
|
||||
@ -128,7 +147,7 @@ export default defineComponent({
|
||||
<LayoutMenu
|
||||
isHorizontal={true}
|
||||
class={`justify-${unref(getTopMenuAlign)}`}
|
||||
theme={unref(getTheme)}
|
||||
theme={unref(getHeaderTheme)}
|
||||
splitType={unref(getSplitType)}
|
||||
menuMode={unref(getMenuMode)}
|
||||
showSearch={false}
|
||||
@ -151,64 +170,47 @@ export default defineComponent({
|
||||
return (
|
||||
<div class={`layout-header__action`}>
|
||||
{unref(getUseErrorHandle) && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '错误日志',
|
||||
default: () => (
|
||||
<Badge
|
||||
count={errorStore.getErrorListCountState}
|
||||
offset={[0, 10]}
|
||||
dot
|
||||
overflowCount={99}
|
||||
>
|
||||
{() => renderActionDefault(BugOutlined, handleToErrorList)}
|
||||
</Badge>
|
||||
),
|
||||
}}
|
||||
</Tooltip>
|
||||
<TooltipItem title="错误日志">
|
||||
{() => (
|
||||
<Badge
|
||||
count={errorStore.getErrorListCountState}
|
||||
offset={[0, 10]}
|
||||
dot
|
||||
overflowCount={99}
|
||||
>
|
||||
{() => renderActionDefault(BugOutlined, handleToErrorList)}
|
||||
</Badge>
|
||||
)}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getUseLockPage) && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '锁定屏幕',
|
||||
default: () => renderActionDefault(LockOutlined, handleLockPage),
|
||||
}}
|
||||
</Tooltip>
|
||||
<TooltipItem title="锁定屏幕">
|
||||
{() => renderActionDefault(LockOutlined, handleLockPage)}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowNotice) && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '消息通知',
|
||||
default: () => <NoticeAction />,
|
||||
}}
|
||||
</Tooltip>
|
||||
<TooltipItem title="消息通知">{() => <NoticeAction />}</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowRedo) && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => '刷新',
|
||||
default: () => renderActionDefault(RedoOutlined, refreshPage),
|
||||
}}
|
||||
</Tooltip>
|
||||
<TooltipItem title="刷新">
|
||||
{() => renderActionDefault(RedoOutlined, refreshPage)}
|
||||
</TooltipItem>
|
||||
)}
|
||||
|
||||
{unref(getShowFullScreen) && (
|
||||
<Tooltip>
|
||||
{{
|
||||
title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'),
|
||||
default: () => {
|
||||
const Icon = !unref(isFullscreenRef) ? (
|
||||
<FullscreenOutlined />
|
||||
) : (
|
||||
<FullscreenExitOutlined />
|
||||
);
|
||||
return renderActionDefault(Icon, toggleFullscreen);
|
||||
},
|
||||
<TooltipItem title={unref(isFullscreenRef) ? '退出全屏' : '全屏'}>
|
||||
{() => {
|
||||
const Icon = !unref(isFullscreenRef) ? (
|
||||
<FullscreenOutlined />
|
||||
) : (
|
||||
<FullscreenExitOutlined />
|
||||
);
|
||||
return renderActionDefault(Icon, toggleFullscreen);
|
||||
}}
|
||||
</Tooltip>
|
||||
</TooltipItem>
|
||||
)}
|
||||
<UserDropdown class={`layout-header__user-dropdown`} />
|
||||
</div>
|
||||
@ -227,7 +229,9 @@ export default defineComponent({
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}>
|
||||
<Layout.Header
|
||||
class={['layout-header', 'flex p-0 px-4 ', unref(headerClass), { fixed: props.fixed }]}
|
||||
>
|
||||
{() => renderHeaderDefault()}
|
||||
</Layout.Header>
|
||||
);
|
||||
|
10
src/layouts/default/header/LayoutMultipleHeader.less
Normal file
10
src/layouts/default/header/LayoutMultipleHeader.less
Normal file
@ -0,0 +1,10 @@
|
||||
.multiple-tab-header {
|
||||
flex: 0 0 auto;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
118
src/layouts/default/header/LayoutMultipleHeader.tsx
Normal file
118
src/layouts/default/header/LayoutMultipleHeader.tsx
Normal file
@ -0,0 +1,118 @@
|
||||
import './LayoutMultipleHeader.less';
|
||||
|
||||
import { defineComponent, unref, computed, ref, watch, nextTick, CSSProperties } from 'vue';
|
||||
|
||||
import LayoutHeader from './LayoutHeader';
|
||||
import MultipleTabs from '../multitabs/index';
|
||||
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
import { useLayoutContext } from '../useLayoutContext';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutMultipleHeader',
|
||||
setup() {
|
||||
const placeholderHeightRef = ref(0);
|
||||
const fullHeaderHeightRef = ref(0);
|
||||
const headerElRef = ref<ComponentRef>(null);
|
||||
const tabElRef = ref<ComponentRef>(null);
|
||||
|
||||
const injectValue = useLayoutContext();
|
||||
|
||||
const { getCalcContentWidth } = useMenuSetting();
|
||||
|
||||
const {
|
||||
getFixed,
|
||||
getShowInsetHeaderRef,
|
||||
getShowFullHeaderRef,
|
||||
getShowHeader,
|
||||
getUnFixedAndFull,
|
||||
} = useHeaderSetting();
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
|
||||
const showTabsRef = computed(() => {
|
||||
return unref(getShowMultipleTab) && !unref(getFullContent);
|
||||
});
|
||||
|
||||
const getPlaceholderDomStyle = computed(() => {
|
||||
return {
|
||||
height: `${unref(placeholderHeightRef)}px`,
|
||||
};
|
||||
});
|
||||
|
||||
const getIsShowPlaceholderDom = computed(() => {
|
||||
return unref(getFixed) || unref(getShowFullHeaderRef);
|
||||
});
|
||||
|
||||
const getWrapStyle = computed(() => {
|
||||
const style: CSSProperties = {};
|
||||
if (unref(getFixed)) {
|
||||
style.width = unref(getCalcContentWidth);
|
||||
}
|
||||
if (unref(getShowFullHeaderRef)) {
|
||||
style.top = `${unref(fullHeaderHeightRef)}px`;
|
||||
}
|
||||
return style;
|
||||
});
|
||||
|
||||
const getIsFixed = computed(() => {
|
||||
return unref(getFixed) || unref(getShowFullHeaderRef);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => [
|
||||
unref(getFixed),
|
||||
unref(getShowFullHeaderRef),
|
||||
unref(getShowHeader),
|
||||
unref(getShowMultipleTab),
|
||||
],
|
||||
() => {
|
||||
if (unref(getUnFixedAndFull)) return;
|
||||
nextTick(() => {
|
||||
const headerEl = unref(headerElRef)?.$el;
|
||||
const tabEl = unref(tabElRef)?.$el;
|
||||
const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el;
|
||||
|
||||
let height = 0;
|
||||
if (headerEl && !unref(getShowFullHeaderRef)) {
|
||||
height += headerEl.offsetHeight;
|
||||
}
|
||||
|
||||
if (tabEl) {
|
||||
height += tabEl.offsetHeight;
|
||||
}
|
||||
|
||||
if (fullHeaderEl && unref(getShowFullHeaderRef)) {
|
||||
const fullHeaderHeight = fullHeaderEl.offsetHeight;
|
||||
height += fullHeaderHeight;
|
||||
fullHeaderHeightRef.value = fullHeaderHeight;
|
||||
}
|
||||
placeholderHeightRef.value = height;
|
||||
});
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<>
|
||||
{unref(getIsShowPlaceholderDom) && <div style={unref(getPlaceholderDomStyle)} />}
|
||||
<div
|
||||
style={unref(getWrapStyle)}
|
||||
class={['multiple-tab-header', { fixed: unref(getIsFixed) }]}
|
||||
>
|
||||
{unref(getShowInsetHeaderRef) && <LayoutHeader ref={headerElRef} />}
|
||||
{unref(showTabsRef) && <MultipleTabs ref={tabElRef} />}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@ -15,15 +15,31 @@ import { DOC_URL } from '/@/settings/siteSetting';
|
||||
import { openWindow } from '/@/utils';
|
||||
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { FunctionalComponent } from 'vue';
|
||||
|
||||
interface RenderItemParams {
|
||||
type MenuEvent = 'loginOut' | 'doc';
|
||||
interface MenuItemProps {
|
||||
icon: string;
|
||||
text: string;
|
||||
key: string;
|
||||
key: MenuEvent;
|
||||
}
|
||||
|
||||
const prefixCls = 'user-dropdown';
|
||||
|
||||
const MenuItem: FunctionalComponent<MenuItemProps> = (props) => {
|
||||
const { key, icon, text } = props;
|
||||
return (
|
||||
<Menu.Item key={key}>
|
||||
{() => (
|
||||
<span class="flex items-center">
|
||||
<Icon icon={icon} class="mr-1" />
|
||||
<span>{text}</span>
|
||||
</span>
|
||||
)}
|
||||
</Menu.Item>
|
||||
);
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'UserDropdown',
|
||||
setup() {
|
||||
@ -44,27 +60,17 @@ export default defineComponent({
|
||||
openWindow(DOC_URL);
|
||||
}
|
||||
|
||||
function handleMenuClick(e: any) {
|
||||
if (e.key === 'loginOut') {
|
||||
handleLoginOut();
|
||||
} else if (e.key === 'doc') {
|
||||
openDoc();
|
||||
function handleMenuClick(e: { key: MenuEvent }) {
|
||||
switch (e.key) {
|
||||
case 'loginOut':
|
||||
handleLoginOut();
|
||||
break;
|
||||
case 'doc':
|
||||
openDoc();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function renderItem({ icon, text, key }: RenderItemParams) {
|
||||
return (
|
||||
<Menu.Item key={key}>
|
||||
{() => (
|
||||
<span class="flex items-center">
|
||||
<Icon icon={icon} class="mr-1" />
|
||||
<span>{text}</span>
|
||||
</span>
|
||||
)}
|
||||
</Menu.Item>
|
||||
);
|
||||
}
|
||||
|
||||
function renderSlotsDefault() {
|
||||
const { realName } = unref(getUserInfo);
|
||||
return (
|
||||
@ -83,13 +89,9 @@ export default defineComponent({
|
||||
<Menu onClick={handleMenuClick}>
|
||||
{() => (
|
||||
<>
|
||||
{showDoc && renderItem({ key: 'doc', text: '文档', icon: 'gg:loadbar-doc' })}
|
||||
{showDoc && <MenuItem key="doc" text="文档" icon="gg:loadbar-doc" />}
|
||||
{showDoc && <Divider />}
|
||||
{renderItem({
|
||||
key: 'loginOut',
|
||||
text: '退出系统',
|
||||
icon: 'ant-design:poweroff-outlined',
|
||||
})}
|
||||
<MenuItem key="loginOut" text="退出系统" icon="ant-design:poweroff-outlined" />
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
|
@ -10,13 +10,21 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__left {
|
||||
display: flex;
|
||||
// flex-grow: 1;
|
||||
align-items: center;
|
||||
|
||||
.layout-trigger {
|
||||
padding: 4px 10px 0 16px;
|
||||
padding: 1px 10px 0 16px;
|
||||
cursor: pointer;
|
||||
|
||||
.anticon {
|
||||
@ -150,6 +158,7 @@
|
||||
}
|
||||
|
||||
&__inner,
|
||||
&__inner.is-link,
|
||||
&__separator {
|
||||
color: @white;
|
||||
}
|
||||
|
@ -1,39 +1,12 @@
|
||||
@import (reference) '../../design/index.less';
|
||||
|
||||
.default-layout {
|
||||
&__content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
&.fixed {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&__loading {
|
||||
position: absolute;
|
||||
z-index: @page-loading-z-index;
|
||||
}
|
||||
|
||||
&__main {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
&.fixed {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&.fixed.lock {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-content {
|
||||
position: relative;
|
||||
|
||||
&.fixed {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
> .ant-layout {
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -1,129 +1,92 @@
|
||||
import { defineComponent, unref, computed } from 'vue';
|
||||
import './index.less';
|
||||
|
||||
import { defineComponent, unref, computed, ref } from 'vue';
|
||||
import { Layout, BackTop } from 'ant-design-vue';
|
||||
import LayoutHeader from './header/LayoutHeader';
|
||||
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import LayoutContent from './LayoutContent';
|
||||
import LayoutSideBar from './sider/LayoutSideBar';
|
||||
import LayoutContent from './content';
|
||||
import LayoutFooter from './footer';
|
||||
import LayoutLockPage from './lock';
|
||||
import LayoutSideBar from './sider';
|
||||
import SettingBtn from './setting/index.vue';
|
||||
import MultipleTabs from './multitabs/index';
|
||||
import LayoutMultipleHeader from './header/LayoutMultipleHeader';
|
||||
|
||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
import { MenuModeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { createLayoutContext } from './useLayoutContext';
|
||||
|
||||
import LockPage from '/@/views/sys/lock/index.vue';
|
||||
import { registerGlobComp } from '/@/components/registerGlobComp';
|
||||
|
||||
import './index.less';
|
||||
export default defineComponent({
|
||||
name: 'DefaultLayout',
|
||||
setup() {
|
||||
const { currentRoute } = useRouter();
|
||||
const headerRef = ref<ComponentRef>(null);
|
||||
|
||||
createLayoutContext({ fullHeaderRef: headerRef });
|
||||
|
||||
// ! Only register global components here
|
||||
// ! Can reduce the size of the first screen code
|
||||
// default layout It is loaded after login. So it won’t be packaged to the first screen
|
||||
registerGlobComp();
|
||||
|
||||
const { getShowFullHeaderRef } = useHeaderSetting();
|
||||
|
||||
const { getUseOpenBackTop, getShowSettingButton, getShowFooter } = useRootSetting();
|
||||
|
||||
const { getShowMenu, getMenuMode, getSplit } = useMenuSetting();
|
||||
|
||||
const { getFullContent } = useFullContent();
|
||||
|
||||
const getProjectConfigRef = computed(() => appStore.getProjectConfig);
|
||||
|
||||
const getLockMainScrollStateRef = computed(() => appStore.getLockMainScrollState);
|
||||
|
||||
const showHeaderRef = computed(() => {
|
||||
const {
|
||||
headerSetting: { show },
|
||||
} = unref(getProjectConfigRef);
|
||||
return show;
|
||||
});
|
||||
|
||||
const showMixHeaderRef = computed(() => {
|
||||
const {
|
||||
menuSetting: { type },
|
||||
} = unref(getProjectConfigRef);
|
||||
return type !== MenuTypeEnum.SIDEBAR && unref(showHeaderRef);
|
||||
});
|
||||
|
||||
const getIsLockRef = computed(() => {
|
||||
const { getLockInfo } = appStore;
|
||||
const { isLock } = getLockInfo;
|
||||
return isLock;
|
||||
const getShowLayoutFooter = computed(() => {
|
||||
return unref(getShowFooter) && !unref(currentRoute).meta?.hiddenFooter;
|
||||
});
|
||||
|
||||
const showSideBarRef = computed(() => {
|
||||
const {
|
||||
menuSetting: { show, mode, split },
|
||||
} = unref(getProjectConfigRef);
|
||||
return split || (show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent));
|
||||
return (
|
||||
unref(getSplit) ||
|
||||
(unref(getShowMenu) &&
|
||||
unref(getMenuMode) !== MenuModeEnum.HORIZONTAL &&
|
||||
!unref(getFullContent))
|
||||
);
|
||||
});
|
||||
|
||||
const showFullHeaderRef = computed(() => {
|
||||
return !unref(getFullContent) && unref(showMixHeaderRef) && unref(showHeaderRef);
|
||||
});
|
||||
|
||||
const showInsetHeaderRef = computed(() => {
|
||||
return !unref(getFullContent) && !unref(showMixHeaderRef) && unref(showHeaderRef);
|
||||
});
|
||||
|
||||
const fixedHeaderClsRef = computed(() => {
|
||||
const {
|
||||
headerSetting: { fixed },
|
||||
} = unref(getProjectConfigRef);
|
||||
const fixedHeaderCls = fixed
|
||||
? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '')
|
||||
: '';
|
||||
return fixedHeaderCls;
|
||||
});
|
||||
|
||||
const showTabsRef = computed(() => {
|
||||
const {
|
||||
multiTabsSetting: { show },
|
||||
} = unref(getProjectConfigRef);
|
||||
return show && !unref(getFullContent);
|
||||
});
|
||||
|
||||
const showClassSideBarRef = computed(() => {
|
||||
const {
|
||||
menuSetting: { split, hidden },
|
||||
} = unref(getProjectConfigRef);
|
||||
return split ? hidden : true;
|
||||
});
|
||||
|
||||
function getTarget(): any {
|
||||
const {
|
||||
headerSetting: { fixed },
|
||||
} = unref(getProjectConfigRef);
|
||||
return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`);
|
||||
function renderFeatures() {
|
||||
return (
|
||||
<>
|
||||
<LayoutLockPage />
|
||||
{/* back top */}
|
||||
{unref(getUseOpenBackTop) && <BackTop target={() => document.body} />}
|
||||
{/* open setting drawer */}
|
||||
{unref(getShowSettingButton) && <SettingBtn />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
const { useOpenBackTop, showSettingButton } = unref(getProjectConfigRef);
|
||||
return (
|
||||
<Layout class="default-layout relative">
|
||||
<Layout class="default-layout">
|
||||
{() => (
|
||||
<>
|
||||
{/* lock page */}
|
||||
{unref(getIsLockRef) && <LockPage />}
|
||||
{/* back top */}
|
||||
{useOpenBackTop && <BackTop target={getTarget} />}
|
||||
{/* open setting drawer */}
|
||||
{showSettingButton && <SettingBtn />}
|
||||
{renderFeatures()}
|
||||
|
||||
{unref(showFullHeaderRef) && <LayoutHeader />}
|
||||
{unref(getShowFullHeaderRef) && <LayoutHeader fixed={true} ref={headerRef} />}
|
||||
|
||||
<Layout>
|
||||
{() => (
|
||||
<>
|
||||
{unref(showSideBarRef) && (
|
||||
<LayoutSideBar class={unref(showClassSideBarRef) ? '' : 'hidden'} />
|
||||
)}
|
||||
<Layout class={[`default-layout__content`, unref(fixedHeaderClsRef)]}>
|
||||
{unref(showSideBarRef) && <LayoutSideBar />}
|
||||
<Layout>
|
||||
{() => (
|
||||
<>
|
||||
{unref(showInsetHeaderRef) && <LayoutHeader />}
|
||||
|
||||
{unref(showTabsRef) && <MultipleTabs />}
|
||||
|
||||
<LayoutContent class={unref(fixedHeaderClsRef)} />
|
||||
<LayoutMultipleHeader />
|
||||
<LayoutContent />
|
||||
{unref(getShowLayoutFooter) && <LayoutFooter />}
|
||||
</>
|
||||
)}
|
||||
</Layout>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import './LockActionItem.less';
|
||||
import './LockAction.less';
|
||||
|
||||
import { defineComponent } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal/index';
|
17
src/layouts/default/lock/index.tsx
Normal file
17
src/layouts/default/lock/index.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { defineComponent, unref, computed } from 'vue';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import LockPage from '/@/views/sys/lock/index.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutLockPage',
|
||||
setup() {
|
||||
const getIsLockRef = computed(() => {
|
||||
const { getLockInfo } = appStore;
|
||||
const { isLock } = getLockInfo;
|
||||
return isLock;
|
||||
});
|
||||
return () => {
|
||||
return unref(getIsLockRef) ? <LockPage /> : null;
|
||||
};
|
||||
},
|
||||
});
|
@ -17,7 +17,7 @@ import { useSplitMenu } from './useLayoutMenu';
|
||||
import { openWindow } from '/@/utils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DefaultLayoutMenu',
|
||||
name: 'LayoutMenu',
|
||||
props: {
|
||||
theme: {
|
||||
type: String as PropType<string>,
|
||||
@ -50,12 +50,12 @@ export default defineComponent({
|
||||
const {
|
||||
setMenuSetting,
|
||||
getShowSearch,
|
||||
getMode,
|
||||
getType,
|
||||
getMenuMode,
|
||||
getMenuType,
|
||||
getCollapsedShowTitle,
|
||||
getCollapsedShowSearch,
|
||||
getIsSidebarType,
|
||||
getTheme,
|
||||
getMenuTheme,
|
||||
getCollapsed,
|
||||
getAccordion,
|
||||
} = useMenuSetting();
|
||||
@ -66,9 +66,9 @@ export default defineComponent({
|
||||
|
||||
const showLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
|
||||
|
||||
const getMenuMode = computed(() => props.menuMode || unref(getMode));
|
||||
const getComputedMenuMode = computed(() => props.menuMode || unref(getMenuMode));
|
||||
|
||||
const getMenuTheme = computed(() => props.theme || unref(getTheme));
|
||||
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
|
||||
|
||||
const appendClass = computed(() => props.splitType === MenuSplitTyeEnum.TOP);
|
||||
|
||||
@ -111,8 +111,8 @@ export default defineComponent({
|
||||
return (
|
||||
<AppLogo
|
||||
showTitle={!unref(getCollapsed)}
|
||||
class={[`layout-menu__logo`, unref(getMenuTheme)]}
|
||||
theme={unref(getMenuTheme)}
|
||||
class={[`layout-menu__logo`, unref(getComputedMenuTheme)]}
|
||||
theme={unref(getComputedMenuTheme)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -124,10 +124,10 @@ export default defineComponent({
|
||||
beforeClickFn={beforeMenuClickFn}
|
||||
isHorizontal={props.isHorizontal}
|
||||
appendClass={unref(appendClass)}
|
||||
type={unref(getType)}
|
||||
mode={unref(getMenuMode)}
|
||||
type={unref(getMenuType)}
|
||||
mode={unref(getComputedMenuMode)}
|
||||
collapsedShowTitle={unref(getCollapsedShowTitle)}
|
||||
theme={unref(getMenuTheme)}
|
||||
theme={unref(getComputedMenuTheme)}
|
||||
showLogo={unref(showLogo)}
|
||||
search={unref(showSearch)}
|
||||
items={unref(menusRef)}
|
@ -6,7 +6,6 @@ import { TabItem, tabStore } from '/@/store/modules/tab';
|
||||
import { getScaleAction, TabContentProps } from './tab.data';
|
||||
|
||||
import { Dropdown } from '/@/components/Dropdown/index';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
import { RightOutlined } from '@ant-design/icons-vue';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
@ -57,18 +56,11 @@ export default defineComponent({
|
||||
/**
|
||||
* @description: 渲染图标
|
||||
*/
|
||||
function renderIcon() {
|
||||
const { tabItem } = props;
|
||||
if (!tabItem) return;
|
||||
const icon = tabItem.meta && tabItem.meta.icon;
|
||||
if (!icon || !unref(getProjectConfigRef).multiTabsSetting.showIcon) return null;
|
||||
return <Icon icon={icon} class="align-middle " style={{ marginBottom: '2px' }} />;
|
||||
}
|
||||
|
||||
function renderTabContent() {
|
||||
const { tabItem: { meta } = {} } = props;
|
||||
return (
|
||||
<div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}>
|
||||
{renderIcon()}
|
||||
<span class="ml-1">{meta && meta.title}</span>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,29 +1,36 @@
|
||||
import { defineComponent, computed, unref, ref } from 'vue';
|
||||
import { BasicDrawer } from '/@/components/Drawer/index';
|
||||
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
||||
import Button from '/@/components/Button/index.vue';
|
||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
import { ProjectConfig } from '/@/types/config';
|
||||
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
|
||||
import type { ProjectConfig } from '/@/types/config';
|
||||
|
||||
import defaultSetting from '/@/settings/projectSetting';
|
||||
|
||||
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
||||
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
||||
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
||||
import { defineComponent, computed, unref, FunctionalComponent } from 'vue';
|
||||
import { BasicDrawer } from '/@/components/Drawer/index';
|
||||
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
||||
import Button from '/@/components/Button/index.vue';
|
||||
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
import { MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
import { appStore } from '/@/store/modules/app';
|
||||
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
|
||||
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
|
||||
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
|
||||
|
||||
import { baseHandler } from './handler';
|
||||
|
||||
import {
|
||||
HandlerEnum,
|
||||
contentModeOptions,
|
||||
topMenuAlignOptions,
|
||||
menuTriggerOptions,
|
||||
routerTransitionOptions,
|
||||
} from './const';
|
||||
menuTypeList,
|
||||
} from './enum';
|
||||
|
||||
import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting';
|
||||
|
||||
interface SwitchOptions {
|
||||
@ -40,215 +47,280 @@ interface SelectConfig {
|
||||
handler?: Fn;
|
||||
}
|
||||
|
||||
interface ThemeOptions {
|
||||
def?: string;
|
||||
handler?: Fn;
|
||||
interface ThemePickerProps {
|
||||
colorList: string[];
|
||||
handler: Fn;
|
||||
def: string;
|
||||
}
|
||||
|
||||
const { createSuccessModal, createMessage } = useMessage();
|
||||
|
||||
/**
|
||||
* Menu type Picker comp
|
||||
*/
|
||||
const MenuTypePicker: FunctionalComponent = () => {
|
||||
const { getIsHorizontal, getMenuType } = useMenuSetting();
|
||||
return (
|
||||
<div class={`setting-drawer__siderbar`}>
|
||||
{menuTypeList.map((item) => {
|
||||
const { title, type: ItemType, mode, src } = item;
|
||||
return (
|
||||
<Tooltip title={title} placement="bottom" key={title}>
|
||||
{{
|
||||
default: () => (
|
||||
<div
|
||||
onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {
|
||||
mode: mode,
|
||||
type: ItemType,
|
||||
split: unref(getIsHorizontal) ? false : undefined,
|
||||
})}
|
||||
>
|
||||
<CheckOutlined
|
||||
class={['check-icon', unref(getMenuType) === ItemType ? 'active' : '']}
|
||||
/>
|
||||
<img src={src} />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ThemePicker: FunctionalComponent<ThemePickerProps> = (props) => {
|
||||
return (
|
||||
<div class={`setting-drawer__theme-item`}>
|
||||
{props.colorList.map((color) => {
|
||||
return (
|
||||
<span
|
||||
onClick={() => props.handler?.(color)}
|
||||
key={color}
|
||||
class={[props.def === color ? 'active' : '']}
|
||||
style={{
|
||||
background: color,
|
||||
}}
|
||||
>
|
||||
<CheckOutlined class="icon" />
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* FooterButton component
|
||||
*/
|
||||
const FooterButton: FunctionalComponent = () => {
|
||||
const { getRootSetting } = useRootSetting();
|
||||
function handleCopy() {
|
||||
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
||||
unref(isSuccessRef) &&
|
||||
createSuccessModal({
|
||||
title: '操作成功',
|
||||
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
||||
});
|
||||
}
|
||||
function handleResetSetting() {
|
||||
try {
|
||||
appStore.commitProjectConfigState(defaultSetting);
|
||||
const { colorWeak, grayMode } = defaultSetting;
|
||||
// updateTheme(themeColor);
|
||||
updateColorWeak(colorWeak);
|
||||
updateGrayMode(grayMode);
|
||||
createMessage.success('重置成功!');
|
||||
} catch (error) {
|
||||
createMessage.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleClearAndRedo() {
|
||||
localStorage.clear();
|
||||
appStore.resumeAllState();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="setting-drawer__footer">
|
||||
<Button type="primary" block onClick={handleCopy}>
|
||||
{() => (
|
||||
<>
|
||||
<CopyOutlined class="mr-2" />
|
||||
拷贝
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button block class="mt-2" onClick={handleResetSetting} color="warning">
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
重置
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button block class="mt-2" onClick={handleClearAndRedo} color="error">
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
清空缓存并返回登录页
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingDrawer',
|
||||
setup(_, { attrs }) {
|
||||
const { createSuccessModal, createMessage } = useMessage();
|
||||
const {
|
||||
getContentMode,
|
||||
getRouterTransition,
|
||||
getOpenRouterTransition,
|
||||
getOpenPageLoading,
|
||||
getShowFooter,
|
||||
getShowBreadCrumb,
|
||||
getShowBreadCrumbIcon,
|
||||
getShowLogo,
|
||||
getFullContent,
|
||||
getColorWeak,
|
||||
getGrayMode,
|
||||
} = useRootSetting();
|
||||
|
||||
const getProjectConfigRef = computed(() => {
|
||||
return appStore.getProjectConfig;
|
||||
});
|
||||
const {
|
||||
getIsHorizontal,
|
||||
getShowMenu,
|
||||
getMenuType,
|
||||
getTrigger,
|
||||
getCollapsedShowTitle,
|
||||
getMenuFixed,
|
||||
getCollapsed,
|
||||
getShowSearch,
|
||||
getHasDrag,
|
||||
getTopMenuAlign,
|
||||
getAccordion,
|
||||
getMenuWidth,
|
||||
getMenuBgColor,
|
||||
getIsTopMenu,
|
||||
getSplit,
|
||||
} = useMenuSetting();
|
||||
|
||||
const getIsHorizontalRef = computed(() => {
|
||||
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
|
||||
});
|
||||
const { getShowHeader, getFixed: getHeaderFixed, getHeaderBgColor } = useHeaderSetting();
|
||||
|
||||
const getShowHeaderRef = computed(() => {
|
||||
return unref(getProjectConfigRef).headerSetting.show;
|
||||
});
|
||||
const { getShowMultipleTab, getShowQuick } = useMultipleTabSetting();
|
||||
|
||||
const getShowMenuRef = computed(() => {
|
||||
return unref(getProjectConfigRef).menuSetting.show && !unref(getIsHorizontalRef);
|
||||
return unref(getShowMenu) && !unref(getIsHorizontal);
|
||||
});
|
||||
|
||||
const getShowTabsRef = computed(() => {
|
||||
return unref(getProjectConfigRef).multiTabsSetting.show;
|
||||
});
|
||||
|
||||
function handleCopy() {
|
||||
const { isSuccessRef } = useCopyToClipboard(
|
||||
JSON.stringify(unref(getProjectConfigRef), null, 2)
|
||||
);
|
||||
unref(isSuccessRef) &&
|
||||
createSuccessModal({
|
||||
title: '操作成功',
|
||||
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
||||
});
|
||||
}
|
||||
|
||||
function handleResetSetting() {
|
||||
try {
|
||||
appStore.commitProjectConfigState(defaultSetting);
|
||||
const { colorWeak, grayMode } = defaultSetting;
|
||||
// updateTheme(themeColor);
|
||||
updateColorWeak(colorWeak);
|
||||
updateGrayMode(grayMode);
|
||||
createMessage.success('重置成功!');
|
||||
} catch (error) {
|
||||
createMessage.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleClearAndRedo() {
|
||||
localStorage.clear();
|
||||
appStore.resumeAllState();
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function renderSidebar() {
|
||||
const {
|
||||
menuSetting: { type, split },
|
||||
} = unref(getProjectConfigRef);
|
||||
|
||||
const typeList = ref([
|
||||
{
|
||||
title: '左侧菜单模式',
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.SIDEBAR,
|
||||
src: sidebarImg,
|
||||
},
|
||||
{
|
||||
title: '混合模式',
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.MIX,
|
||||
src: mixImg,
|
||||
},
|
||||
|
||||
{
|
||||
title: '顶部菜单模式',
|
||||
mode: MenuModeEnum.HORIZONTAL,
|
||||
type: MenuTypeEnum.TOP_MENU,
|
||||
src: menuTopImg,
|
||||
},
|
||||
]);
|
||||
return [
|
||||
<div class={`setting-drawer__siderbar`}>
|
||||
{unref(typeList).map((item) => {
|
||||
const { title, type: ItemType, mode, src } = item;
|
||||
return (
|
||||
<Tooltip title={title} placement="bottom" key={title}>
|
||||
{{
|
||||
default: () => (
|
||||
<div
|
||||
onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {
|
||||
mode: mode,
|
||||
type: ItemType,
|
||||
split: unref(getIsHorizontalRef) ? false : undefined,
|
||||
})}
|
||||
>
|
||||
<CheckOutlined class={['check-icon', type === ItemType ? 'active' : '']} />
|
||||
<img src={src} />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
</Tooltip>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<MenuTypePicker />
|
||||
{renderSwitchItem('分割菜单', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
||||
},
|
||||
def: unref(getSplit),
|
||||
disabled: !unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX,
|
||||
})}
|
||||
</div>,
|
||||
renderSwitchItem('分割菜单', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
||||
},
|
||||
def: split,
|
||||
disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX,
|
||||
}),
|
||||
// renderSelectItem('顶栏主题', {
|
||||
// handler: (e) => {
|
||||
// baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||
// },
|
||||
// def: headerTheme,
|
||||
// options: themeOptions,
|
||||
// disabled: !unref(getShowHeaderRef),
|
||||
// }),
|
||||
// renderSelectItem('菜单主题', {
|
||||
// handler: (e) => {
|
||||
// baseHandler(HandlerEnum.MENU_THEME, e);
|
||||
// },
|
||||
// def: menuTheme,
|
||||
// options: themeOptions,
|
||||
// disabled: !unref(getShowMenuRef),
|
||||
// }),
|
||||
];
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderTheme() {
|
||||
return (
|
||||
<>
|
||||
<Divider>{() => '顶栏主题'}</Divider>
|
||||
<ThemePicker
|
||||
colorList={HEADER_PRESET_BG_COLOR_LIST}
|
||||
def={unref(getHeaderBgColor)}
|
||||
handler={(e) => {
|
||||
baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||
}}
|
||||
/>
|
||||
<Divider>{() => '菜单主题'}</Divider>
|
||||
<ThemePicker
|
||||
colorList={SIDE_BAR_BG_COLOR_LIST}
|
||||
def={unref(getMenuBgColor)}
|
||||
handler={(e) => {
|
||||
baseHandler(HandlerEnum.MENU_THEME, e);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description:
|
||||
*/
|
||||
function renderFeatures() {
|
||||
const {
|
||||
contentMode,
|
||||
headerSetting: { fixed },
|
||||
menuSetting: {
|
||||
hasDrag,
|
||||
collapsed,
|
||||
showSearch,
|
||||
menuWidth,
|
||||
topMenuAlign,
|
||||
collapsedShowTitle,
|
||||
trigger,
|
||||
accordion,
|
||||
} = {},
|
||||
} = appStore.getProjectConfig;
|
||||
return [
|
||||
renderSwitchItem('侧边菜单拖拽', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_HAS_DRAG, e);
|
||||
},
|
||||
def: hasDrag,
|
||||
def: unref(getHasDrag),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('侧边菜单搜索', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e);
|
||||
},
|
||||
def: showSearch,
|
||||
def: unref(getShowSearch),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('侧边菜单手风琴模式', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_ACCORDION, e);
|
||||
},
|
||||
def: accordion,
|
||||
def: unref(getAccordion),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('折叠菜单', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_COLLAPSED, e);
|
||||
},
|
||||
def: collapsed,
|
||||
def: unref(getCollapsed),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSwitchItem('折叠菜单显示名称', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e);
|
||||
},
|
||||
def: collapsedShowTitle,
|
||||
disabled: !unref(getShowMenuRef) || !collapsed,
|
||||
def: unref(getCollapsedShowTitle),
|
||||
disabled: !unref(getShowMenuRef) || !unref(getCollapsed),
|
||||
}),
|
||||
renderSwitchItem('固定header', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_FIXED, e);
|
||||
},
|
||||
def: fixed,
|
||||
disabled: !unref(getShowHeaderRef),
|
||||
def: unref(getHeaderFixed),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('固定Siderbar', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_FIXED, e);
|
||||
},
|
||||
def: unref(getMenuFixed),
|
||||
disabled: !unref(getShowMenuRef),
|
||||
}),
|
||||
renderSelectItem('顶部菜单布局', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_TOP_ALIGN, e);
|
||||
},
|
||||
def: topMenuAlign,
|
||||
def: unref(getTopMenuAlign),
|
||||
options: topMenuAlignOptions,
|
||||
disabled: !unref(getShowHeaderRef),
|
||||
disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)),
|
||||
}),
|
||||
renderSelectItem('菜单折叠按钮', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_TRIGGER, e);
|
||||
},
|
||||
def: trigger,
|
||||
disabled: !unref(getShowMenuRef),
|
||||
def: unref(getTrigger),
|
||||
options: menuTriggerOptions,
|
||||
}),
|
||||
|
||||
@ -256,7 +328,7 @@ export default defineComponent({
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.CONTENT_MODE, e);
|
||||
},
|
||||
def: contentMode,
|
||||
def: unref(getContentMode),
|
||||
options: contentModeOptions,
|
||||
}),
|
||||
<div class={`setting-drawer__cell-item`}>
|
||||
@ -286,7 +358,7 @@ export default defineComponent({
|
||||
min={100}
|
||||
step={10}
|
||||
disabled={!unref(getShowMenuRef)}
|
||||
defaultValue={menuWidth}
|
||||
defaultValue={unref(getMenuWidth)}
|
||||
formatter={(value: string) => `${parseInt(value)}px`}
|
||||
onChange={(e: any) => {
|
||||
baseHandler(HandlerEnum.MENU_WIDTH, e);
|
||||
@ -295,120 +367,111 @@ export default defineComponent({
|
||||
</div>,
|
||||
];
|
||||
}
|
||||
function renderTransition() {
|
||||
const { routerTransition, openRouterTransition, openPageLoading } = appStore.getProjectConfig;
|
||||
|
||||
function renderContent() {
|
||||
return [
|
||||
renderSwitchItem('面包屑', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
||||
},
|
||||
def: unref(getShowBreadCrumb),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('面包屑图标', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
||||
},
|
||||
def: unref(getShowBreadCrumbIcon),
|
||||
disabled: !unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('标签页', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW, e);
|
||||
},
|
||||
def: unref(getShowMultipleTab),
|
||||
}),
|
||||
renderSwitchItem('标签页快捷按钮', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
||||
},
|
||||
def: unref(getShowQuick),
|
||||
disabled: !unref(getShowMultipleTab),
|
||||
}),
|
||||
|
||||
renderSwitchItem('左侧菜单', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
||||
},
|
||||
def: unref(getShowMenu),
|
||||
disabled: unref(getIsHorizontal),
|
||||
}),
|
||||
renderSwitchItem('顶栏', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
||||
},
|
||||
def: unref(getShowHeader),
|
||||
}),
|
||||
renderSwitchItem('Logo', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_LOGO, e);
|
||||
},
|
||||
def: unref(getShowLogo),
|
||||
}),
|
||||
renderSwitchItem('页脚', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_FOOTER, e);
|
||||
},
|
||||
def: unref(getShowFooter),
|
||||
}),
|
||||
renderSwitchItem('全屏内容', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
||||
},
|
||||
def: unref(getFullContent),
|
||||
}),
|
||||
renderSwitchItem('灰色模式', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.GRAY_MODE, e);
|
||||
},
|
||||
def: unref(getGrayMode),
|
||||
}),
|
||||
renderSwitchItem('色弱模式', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
||||
},
|
||||
def: unref(getColorWeak),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
function renderTransition() {
|
||||
return (
|
||||
<>
|
||||
{renderSwitchItem('页面切换loading', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
||||
},
|
||||
def: openPageLoading,
|
||||
def: unref(getOpenPageLoading),
|
||||
})}
|
||||
|
||||
{renderSwitchItem('切换动画', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
||||
},
|
||||
def: openRouterTransition,
|
||||
def: unref(getOpenRouterTransition),
|
||||
})}
|
||||
|
||||
{renderSelectItem('路由动画', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
||||
},
|
||||
def: routerTransition,
|
||||
def: unref(getRouterTransition),
|
||||
options: routerTransitionOptions,
|
||||
disabled: !openRouterTransition,
|
||||
disabled: !unref(getOpenRouterTransition),
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
function renderContent() {
|
||||
const {
|
||||
grayMode,
|
||||
colorWeak,
|
||||
fullContent,
|
||||
showLogo,
|
||||
headerSetting: { show: showHeader },
|
||||
menuSetting: { show: showMenu },
|
||||
multiTabsSetting: { show: showMultiple, showQuick, showIcon: showTabIcon },
|
||||
showBreadCrumb,
|
||||
showBreadCrumbIcon,
|
||||
} = unref(getProjectConfigRef);
|
||||
return [
|
||||
renderSwitchItem('面包屑', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
||||
},
|
||||
def: showBreadCrumb,
|
||||
disabled: !unref(getShowHeaderRef),
|
||||
}),
|
||||
renderSwitchItem('面包屑图标', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
||||
},
|
||||
def: showBreadCrumbIcon,
|
||||
disabled: !unref(getShowHeaderRef),
|
||||
}),
|
||||
renderSwitchItem('标签页', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW, e);
|
||||
},
|
||||
def: showMultiple,
|
||||
}),
|
||||
renderSwitchItem('标签页快捷按钮', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
||||
},
|
||||
def: showQuick,
|
||||
disabled: !unref(getShowTabsRef),
|
||||
}),
|
||||
renderSwitchItem('标签页图标', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.TABS_SHOW_ICON, e);
|
||||
},
|
||||
def: showTabIcon,
|
||||
disabled: !unref(getShowTabsRef),
|
||||
}),
|
||||
renderSwitchItem('左侧菜单', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
||||
},
|
||||
def: showMenu,
|
||||
disabled: unref(getIsHorizontalRef),
|
||||
}),
|
||||
renderSwitchItem('顶栏', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
||||
},
|
||||
def: showHeader,
|
||||
}),
|
||||
renderSwitchItem('Logo', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.SHOW_LOGO, e);
|
||||
},
|
||||
def: showLogo,
|
||||
}),
|
||||
renderSwitchItem('全屏内容', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
||||
},
|
||||
def: fullContent,
|
||||
}),
|
||||
renderSwitchItem('灰色模式', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.GRAY_MODE, e);
|
||||
},
|
||||
def: grayMode,
|
||||
}),
|
||||
renderSwitchItem('色弱模式', {
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
||||
},
|
||||
def: colorWeak,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
function renderSelectItem(text: string, config?: SelectConfig) {
|
||||
const { handler, def, disabled = false, options } = config || {};
|
||||
@ -449,50 +512,6 @@ export default defineComponent({
|
||||
);
|
||||
}
|
||||
|
||||
function renderTheme() {
|
||||
const { headerBgColor, menuBgColor } = unref(getProjectConfigRef);
|
||||
return (
|
||||
<>
|
||||
<Divider>{() => '顶栏主题'}</Divider>
|
||||
{renderThemeItem(HEADER_PRESET_BG_COLOR_LIST, {
|
||||
def: headerBgColor,
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||
},
|
||||
})}
|
||||
<Divider>{() => '菜单主题'}</Divider>
|
||||
{renderThemeItem(SIDE_BAR_BG_COLOR_LIST, {
|
||||
def: menuBgColor,
|
||||
handler: (e) => {
|
||||
baseHandler(HandlerEnum.MENU_THEME, e);
|
||||
},
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function renderThemeItem(colorList: string[], opt: ThemeOptions) {
|
||||
const { def, handler } = opt;
|
||||
return (
|
||||
<div class={`setting-drawer__theme-item`}>
|
||||
{colorList.map((item) => {
|
||||
return (
|
||||
<span
|
||||
onClick={() => handler && handler(item)}
|
||||
key={item}
|
||||
class={[def === item ? 'active' : '']}
|
||||
style={{
|
||||
background: item,
|
||||
}}
|
||||
>
|
||||
<CheckOutlined class="icon" />
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return () => (
|
||||
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
|
||||
{{
|
||||
@ -500,9 +519,7 @@ export default defineComponent({
|
||||
<>
|
||||
<Divider>{() => '导航栏模式'}</Divider>
|
||||
{renderSidebar()}
|
||||
|
||||
{renderTheme()}
|
||||
|
||||
<Divider>{() => '界面功能'}</Divider>
|
||||
{renderFeatures()}
|
||||
<Divider>{() => '界面显示'}</Divider>
|
||||
@ -510,32 +527,7 @@ export default defineComponent({
|
||||
<Divider>{() => '切换动画'}</Divider>
|
||||
{renderTransition()}
|
||||
<Divider />
|
||||
<div class="setting-drawer__footer">
|
||||
<Button type="primary" block onClick={handleCopy}>
|
||||
{() => (
|
||||
<>
|
||||
<CopyOutlined class="mr-2" />
|
||||
拷贝
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button block class="mt-2" onClick={handleResetSetting} color="warning">
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
重置
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button block class="mt-2" onClick={handleClearAndRedo} color="error">
|
||||
{() => (
|
||||
<>
|
||||
<RedoOutlined class="mr-2" />
|
||||
清空缓存并返回登录页
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<FooterButton />
|
||||
</>
|
||||
),
|
||||
}}
|
||||
|
@ -1,5 +1,9 @@
|
||||
import { ContentEnum, RouterTransitionEnum, ThemeEnum } from '/@/enums/appEnum';
|
||||
import { TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||
import { MenuModeEnum, MenuTypeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
||||
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
||||
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
||||
|
||||
export enum HandlerEnum {
|
||||
CHANGE_LAYOUT,
|
||||
@ -15,6 +19,7 @@ export enum HandlerEnum {
|
||||
MENU_THEME,
|
||||
MENU_SPLIT,
|
||||
MENU_SHOW_SEARCH,
|
||||
MENU_FIXED,
|
||||
|
||||
// header
|
||||
HEADER_SHOW,
|
||||
@ -23,7 +28,6 @@ export enum HandlerEnum {
|
||||
|
||||
TABS_SHOW_QUICK,
|
||||
TABS_SHOW,
|
||||
TABS_SHOW_ICON,
|
||||
|
||||
OPEN_PAGE_LOADING,
|
||||
OPEN_ROUTE_TRANSITION,
|
||||
@ -36,6 +40,7 @@ export enum HandlerEnum {
|
||||
GRAY_MODE,
|
||||
COLOR_WEAK,
|
||||
SHOW_LOGO,
|
||||
SHOW_FOOTER,
|
||||
}
|
||||
|
||||
export const themeOptions = [
|
||||
@ -102,3 +107,25 @@ export const routerTransitionOptions = [
|
||||
value: item,
|
||||
};
|
||||
});
|
||||
|
||||
export const menuTypeList = [
|
||||
{
|
||||
title: '左侧菜单模式',
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.SIDEBAR,
|
||||
src: sidebarImg,
|
||||
},
|
||||
{
|
||||
title: '混合模式',
|
||||
mode: MenuModeEnum.INLINE,
|
||||
type: MenuTypeEnum.MIX,
|
||||
src: mixImg,
|
||||
},
|
||||
|
||||
{
|
||||
title: '顶部菜单模式',
|
||||
mode: MenuModeEnum.HORIZONTAL,
|
||||
type: MenuTypeEnum.TOP_MENU,
|
||||
src: menuTopImg,
|
||||
},
|
||||
];
|
@ -1,5 +1,4 @@
|
||||
import { HandlerEnum } from './const';
|
||||
// import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
||||
import { HandlerEnum } from './enum';
|
||||
import {
|
||||
updateColorWeak,
|
||||
updateGrayMode,
|
||||
@ -19,12 +18,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
case HandlerEnum.CHANGE_LAYOUT:
|
||||
const { mode, type, split } = value;
|
||||
const splitOpt = split === undefined ? { split } : {};
|
||||
// let headerSetting = {};
|
||||
// if (type === MenuTypeEnum.TOP_MENU) {
|
||||
// headerSetting = {
|
||||
// theme: MenuThemeEnum.DARK,
|
||||
// };
|
||||
// }
|
||||
|
||||
return {
|
||||
menuSetting: {
|
||||
mode,
|
||||
@ -33,159 +27,103 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf
|
||||
show: true,
|
||||
...splitOpt,
|
||||
},
|
||||
// headerSetting,
|
||||
};
|
||||
|
||||
case HandlerEnum.MENU_HAS_DRAG:
|
||||
return {
|
||||
menuSetting: {
|
||||
hasDrag: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { hasDrag: value } };
|
||||
|
||||
case HandlerEnum.MENU_ACCORDION:
|
||||
return {
|
||||
menuSetting: {
|
||||
accordion: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { accordion: value } };
|
||||
|
||||
case HandlerEnum.MENU_TRIGGER:
|
||||
return {
|
||||
menuSetting: {
|
||||
trigger: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { trigger: value } };
|
||||
|
||||
case HandlerEnum.MENU_TOP_ALIGN:
|
||||
return {
|
||||
menuSetting: {
|
||||
topMenuAlign: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { topMenuAlign: value } };
|
||||
|
||||
case HandlerEnum.MENU_COLLAPSED:
|
||||
return {
|
||||
menuSetting: {
|
||||
collapsed: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { collapsed: value } };
|
||||
|
||||
case HandlerEnum.MENU_WIDTH:
|
||||
return {
|
||||
menuSetting: {
|
||||
menuWidth: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { menuWidth: value } };
|
||||
|
||||
case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE:
|
||||
return {
|
||||
menuSetting: {
|
||||
collapsedShowTitle: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { collapsedShowTitle: value } };
|
||||
|
||||
case HandlerEnum.MENU_SHOW_SIDEBAR:
|
||||
return {
|
||||
menuSetting: {
|
||||
show: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { show: value } };
|
||||
|
||||
case HandlerEnum.MENU_THEME:
|
||||
updateSidebarBgColor(value);
|
||||
return {
|
||||
menuBgColor: value,
|
||||
// menuSetting: {
|
||||
// theme: value,
|
||||
// },
|
||||
};
|
||||
return { menuSetting: { bgColor: value } };
|
||||
|
||||
case HandlerEnum.MENU_SPLIT:
|
||||
return {
|
||||
menuSetting: {
|
||||
split: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { split: value } };
|
||||
|
||||
case HandlerEnum.MENU_FIXED:
|
||||
return { menuSetting: { fixed: value } };
|
||||
|
||||
case HandlerEnum.MENU_SHOW_SEARCH:
|
||||
return {
|
||||
menuSetting: {
|
||||
showSearch: value,
|
||||
},
|
||||
};
|
||||
return { menuSetting: { showSearch: value } };
|
||||
|
||||
// ============root==================
|
||||
|
||||
case HandlerEnum.OPEN_PAGE_LOADING:
|
||||
return {
|
||||
openPageLoading: value,
|
||||
};
|
||||
appStore.commitPageLoadingState(false);
|
||||
return { openPageLoading: value };
|
||||
|
||||
case HandlerEnum.OPEN_ROUTE_TRANSITION:
|
||||
return {
|
||||
openRouterTransition: value,
|
||||
};
|
||||
return { openRouterTransition: value };
|
||||
|
||||
case HandlerEnum.ROUTER_TRANSITION:
|
||||
return {
|
||||
routerTransition: value,
|
||||
};
|
||||
return { routerTransition: value };
|
||||
|
||||
case HandlerEnum.LOCK_TIME:
|
||||
return {
|
||||
lockTime: value,
|
||||
};
|
||||
return { lockTime: value };
|
||||
|
||||
case HandlerEnum.FULL_CONTENT:
|
||||
return {
|
||||
fullContent: value,
|
||||
};
|
||||
return { fullContent: value };
|
||||
|
||||
case HandlerEnum.CONTENT_MODE:
|
||||
return {
|
||||
contentMode: value,
|
||||
};
|
||||
return { contentMode: value };
|
||||
|
||||
case HandlerEnum.SHOW_BREADCRUMB:
|
||||
return {
|
||||
showBreadCrumb: value,
|
||||
};
|
||||
return { showBreadCrumb: value };
|
||||
|
||||
case HandlerEnum.SHOW_BREADCRUMB_ICON:
|
||||
return {
|
||||
showBreadCrumbIcon: value,
|
||||
};
|
||||
return { showBreadCrumbIcon: value };
|
||||
|
||||
case HandlerEnum.GRAY_MODE:
|
||||
updateGrayMode(value);
|
||||
return {
|
||||
grayMode: value,
|
||||
};
|
||||
return { grayMode: value };
|
||||
|
||||
case HandlerEnum.SHOW_FOOTER:
|
||||
return { showFooter: value };
|
||||
|
||||
case HandlerEnum.COLOR_WEAK:
|
||||
updateColorWeak(value);
|
||||
return {
|
||||
colorWeak: value,
|
||||
};
|
||||
return { colorWeak: value };
|
||||
|
||||
case HandlerEnum.SHOW_LOGO:
|
||||
return {
|
||||
showLogo: value,
|
||||
};
|
||||
return { showLogo: value };
|
||||
|
||||
// ============tabs==================
|
||||
case HandlerEnum.TABS_SHOW_QUICK:
|
||||
return {
|
||||
multiTabsSetting: {
|
||||
showQuick: value,
|
||||
},
|
||||
};
|
||||
case HandlerEnum.TABS_SHOW_ICON:
|
||||
return {
|
||||
multiTabsSetting: {
|
||||
showIcon: value,
|
||||
},
|
||||
};
|
||||
return { multiTabsSetting: { showQuick: value } };
|
||||
|
||||
case HandlerEnum.TABS_SHOW:
|
||||
return {
|
||||
multiTabsSetting: {
|
||||
show: value,
|
||||
},
|
||||
};
|
||||
return { multiTabsSetting: { show: value } };
|
||||
|
||||
// ============header==================
|
||||
case HandlerEnum.HEADER_THEME:
|
||||
updateHeaderBgColor(value);
|
||||
return {
|
||||
headerBgColor: value,
|
||||
};
|
||||
return { headerSetting: { bgColor: value } };
|
||||
|
||||
case HandlerEnum.HEADER_FIXED:
|
||||
return {
|
||||
headerSetting: {
|
||||
fixed: value,
|
||||
},
|
||||
};
|
||||
return { headerSetting: { fixed: value } };
|
||||
|
||||
case HandlerEnum.HEADER_SHOW:
|
||||
return {
|
||||
headerSetting: {
|
||||
show: value,
|
||||
},
|
||||
};
|
||||
return { headerSetting: { show: value } };
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
import SettingDrawer from './SettingDrawer';
|
||||
|
||||
import { useDrawer } from '/@/components/Drawer';
|
||||
//
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SettingBtn',
|
||||
components: { SettingOutlined, SettingDrawer },
|
||||
|
@ -1,77 +0,0 @@
|
||||
import './index.less';
|
||||
|
||||
import { computed, defineComponent, ref, unref } from 'vue';
|
||||
|
||||
import { Layout } from 'ant-design-vue';
|
||||
import LayoutMenu from '/@/layouts/default/menu/LayoutMenu';
|
||||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutSideBar',
|
||||
setup() {
|
||||
const dragBarRef = ref<Nullable<HTMLDivElement>>(null);
|
||||
const sideRef = ref<Nullable<HTMLDivElement>>(null);
|
||||
|
||||
const { getCollapsed, getMenuWidth, getSplit, getTheme } = useMenuSetting();
|
||||
|
||||
const { getTriggerAttr, getTriggerSlot } = useTrigger();
|
||||
|
||||
const { renderDragLine } = useDragLine(sideRef, dragBarRef);
|
||||
|
||||
const {
|
||||
getCollapsedWidth,
|
||||
onBreakpointChange,
|
||||
onCollapseChange,
|
||||
onSiderClick,
|
||||
} = useSiderEvent();
|
||||
|
||||
const getMode = computed(() => {
|
||||
return unref(getSplit) ? MenuModeEnum.INLINE : null;
|
||||
});
|
||||
|
||||
const getSplitType = computed(() => {
|
||||
return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE;
|
||||
});
|
||||
|
||||
function renderDefault() {
|
||||
return (
|
||||
<>
|
||||
<LayoutMenu
|
||||
theme={unref(getTheme)}
|
||||
menuMode={unref(getMode)}
|
||||
splitType={unref(getSplitType)}
|
||||
/>
|
||||
{renderDragLine()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<Layout.Sider
|
||||
ref={sideRef}
|
||||
class="layout-sidebar"
|
||||
breakpoint="md"
|
||||
collapsible
|
||||
width={unref(getMenuWidth)}
|
||||
collapsed={unref(getCollapsed)}
|
||||
collapsedWidth={unref(getCollapsedWidth)}
|
||||
theme={unref(getTheme)}
|
||||
onClick={onSiderClick}
|
||||
onCollapse={onCollapseChange}
|
||||
onBreakpoint={onBreakpointChange}
|
||||
{...unref(getTriggerAttr)}
|
||||
>
|
||||
{{
|
||||
...unref(getTriggerSlot),
|
||||
default: () => renderDefault(),
|
||||
}}
|
||||
</Layout.Sider>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@ -1,7 +1,14 @@
|
||||
@import (reference) '../../../design/index.less';
|
||||
|
||||
.layout-sidebar {
|
||||
background-size: 100% 100%;
|
||||
overflow: hidden;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.ant-layout-sider-dark {
|
||||
background: @sider-dark-bg-color;
|
||||
@ -9,6 +16,7 @@
|
||||
|
||||
&:not(.ant-layout-sider-dark) {
|
||||
border-right: 1px solid @border-color-light;
|
||||
box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
|
||||
}
|
||||
|
||||
.ant-layout-sider-zero-width-trigger {
|
||||
|
150
src/layouts/default/sider/index.tsx
Normal file
150
src/layouts/default/sider/index.tsx
Normal file
@ -0,0 +1,150 @@
|
||||
import './index.less';
|
||||
|
||||
import { computed, defineComponent, ref, unref, watch, nextTick } from 'vue';
|
||||
|
||||
import { Layout } from 'ant-design-vue';
|
||||
import LayoutMenu from '../menu';
|
||||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
||||
import { useLayoutContext } from '../useLayoutContext';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'LayoutSideBar',
|
||||
setup() {
|
||||
const topRef = ref(0);
|
||||
const dragBarRef = ref<ElRef>(null);
|
||||
const sideRef = ref<ElRef>(null);
|
||||
|
||||
const {
|
||||
getCollapsed,
|
||||
getMenuWidth,
|
||||
getSplit,
|
||||
getMenuTheme,
|
||||
getRealWidth,
|
||||
getMenuHidden,
|
||||
getMenuFixed,
|
||||
} = useMenuSetting();
|
||||
|
||||
const { getShowFullHeaderRef, getUnFixedAndFull } = useHeaderSetting();
|
||||
|
||||
const injectValue = useLayoutContext();
|
||||
|
||||
const { getTriggerAttr, getTriggerSlot } = useTrigger();
|
||||
|
||||
const { renderDragLine } = useDragLine(sideRef, dragBarRef);
|
||||
|
||||
const {
|
||||
getCollapsedWidth,
|
||||
onBreakpointChange,
|
||||
onCollapseChange,
|
||||
onSiderClick,
|
||||
} = useSiderEvent();
|
||||
|
||||
const getMode = computed(() => {
|
||||
return unref(getSplit) ? MenuModeEnum.INLINE : null;
|
||||
});
|
||||
|
||||
const getSplitType = computed(() => {
|
||||
return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE;
|
||||
});
|
||||
|
||||
const showClassSideBarRef = computed(() => {
|
||||
return unref(getSplit) ? unref(getMenuHidden) : true;
|
||||
});
|
||||
|
||||
const getSiderClass = computed(() => {
|
||||
return {
|
||||
'layout-sidebar': true,
|
||||
fixed: unref(getMenuFixed),
|
||||
hidden: !unref(showClassSideBarRef),
|
||||
};
|
||||
});
|
||||
|
||||
const getSiderStyle = computed(() => {
|
||||
const top = `${unref(topRef)}px`;
|
||||
if (!unref(getMenuFixed)) {
|
||||
return { top };
|
||||
}
|
||||
return {
|
||||
top,
|
||||
height: `calc(100% - ${top})`,
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => getShowFullHeaderRef.value,
|
||||
() => {
|
||||
topRef.value = 0;
|
||||
if (unref(getUnFixedAndFull)) return;
|
||||
nextTick(() => {
|
||||
const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el;
|
||||
if (!fullHeaderEl) return;
|
||||
topRef.value = fullHeaderEl.offsetHeight;
|
||||
});
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const getHiddenDomStyle = computed(() => {
|
||||
const width = `${unref(getRealWidth)}px`;
|
||||
return {
|
||||
width: width,
|
||||
overflow: 'hidden',
|
||||
flex: `0 0 ${width}`,
|
||||
'max-width': width,
|
||||
'min-width': width,
|
||||
transition: 'all 0.2s',
|
||||
};
|
||||
});
|
||||
|
||||
function renderDefault() {
|
||||
return (
|
||||
<>
|
||||
<LayoutMenu
|
||||
theme={unref(getMenuTheme)}
|
||||
menuMode={unref(getMode)}
|
||||
splitType={unref(getSplitType)}
|
||||
/>
|
||||
{renderDragLine()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<>
|
||||
{unref(getMenuFixed) && (
|
||||
<div style={unref(getHiddenDomStyle)} class={{ hidden: !unref(showClassSideBarRef) }} />
|
||||
)}
|
||||
|
||||
<Layout.Sider
|
||||
ref={sideRef}
|
||||
breakpoint="md"
|
||||
collapsible
|
||||
class={unref(getSiderClass)}
|
||||
style={unref(getSiderStyle)}
|
||||
width={unref(getMenuWidth)}
|
||||
collapsed={unref(getCollapsed)}
|
||||
collapsedWidth={unref(getCollapsedWidth)}
|
||||
theme={unref(getMenuTheme)}
|
||||
onClick={onSiderClick}
|
||||
onCollapse={onCollapseChange}
|
||||
onBreakpoint={onBreakpointChange}
|
||||
{...unref(getTriggerAttr)}
|
||||
>
|
||||
{{
|
||||
...unref(getTriggerSlot),
|
||||
default: () => renderDefault(),
|
||||
}}
|
||||
</Layout.Sider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
@ -16,7 +16,7 @@ export function useSiderEvent() {
|
||||
const brokenRef = ref(false);
|
||||
const collapseRef = ref(true);
|
||||
|
||||
const { setMenuSetting, getCollapsed, getMiniWidthNumber, getShow } = useMenuSetting();
|
||||
const { setMenuSetting, getCollapsed, getMiniWidthNumber, getShowMenu } = useMenuSetting();
|
||||
|
||||
const getCollapsedWidth = computed(() => {
|
||||
return unref(brokenRef) ? 0 : unref(getMiniWidthNumber);
|
||||
@ -38,7 +38,7 @@ export function useSiderEvent() {
|
||||
|
||||
function onSiderClick(e: ChangeEvent) {
|
||||
if (!e || !e.target || e.target.className !== 'basic-menu__content') return;
|
||||
if (!unref(getCollapsed) || !unref(getShow)) return;
|
||||
if (!unref(getCollapsed) || !unref(getShowMenu)) return;
|
||||
setMenuSetting({ collapsed: false });
|
||||
}
|
||||
return { getCollapsedWidth, onCollapseChange, onBreakpointChange, onSiderClick };
|
||||
|
16
src/layouts/default/useLayoutContext.ts
Normal file
16
src/layouts/default/useLayoutContext.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { InjectionKey, Ref } from 'vue';
|
||||
import { createContext, useContext } from '/@/hooks/core/useContext';
|
||||
|
||||
export interface LayoutContextProps {
|
||||
fullHeaderRef: Ref<ComponentRef>;
|
||||
}
|
||||
|
||||
const layoutContextInjectKey: InjectionKey<LayoutContextProps> = Symbol();
|
||||
|
||||
export function createLayoutContext(context: LayoutContextProps) {
|
||||
return createContext<LayoutContextProps>(context, layoutContextInjectKey);
|
||||
}
|
||||
|
||||
export function useLayoutContext() {
|
||||
return useContext<LayoutContextProps>(layoutContextInjectKey);
|
||||
}
|
@ -12,7 +12,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||
|
||||
export function useFrameKeepAlive() {
|
||||
const { currentRoute } = useRouter();
|
||||
const { getShow } = useMultipleTabSetting();
|
||||
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||
|
||||
const getFramePages = computed(() => {
|
||||
const ret =
|
||||
@ -49,7 +49,7 @@ export function useFrameKeepAlive() {
|
||||
}
|
||||
|
||||
function hasRenderFrame(path: string) {
|
||||
return unref(getShow) ? unref(getOpenTabList).includes(path) : true;
|
||||
return unref(getShowMultipleTab) ? unref(getOpenTabList).includes(path) : true;
|
||||
}
|
||||
return { hasRenderFrame, getFramePages, showIframe, getAllFramePages };
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ interface DefaultContext {
|
||||
export default defineComponent({
|
||||
name: 'PageLayout',
|
||||
setup() {
|
||||
const { getShow } = useMenuSetting();
|
||||
const { getShowMenu } = useMenuSetting();
|
||||
const {
|
||||
getOpenKeepAlive,
|
||||
getRouterTransition,
|
||||
@ -32,7 +32,7 @@ export default defineComponent({
|
||||
|
||||
const transitionEvent = useTransition();
|
||||
|
||||
const openCacheRef = computed(() => unref(getOpenKeepAlive) && unref(getShow));
|
||||
const openCacheRef = computed(() => unref(getOpenKeepAlive) && unref(getShowMenu));
|
||||
|
||||
const getCacheTabsRef = computed(() => tabStore.getKeepAliveTabsState as string[]);
|
||||
|
||||
|
@ -21,12 +21,6 @@ const setting: ProjectConfig = {
|
||||
// TODO 主题色
|
||||
themeColor: primaryColor,
|
||||
|
||||
// header bg color
|
||||
headerBgColor: '#ffffff',
|
||||
|
||||
// sidebar menu bg color
|
||||
menuBgColor: '#273352',
|
||||
|
||||
// Whether to show the configuration button
|
||||
showSettingButton: true,
|
||||
|
||||
@ -48,8 +42,13 @@ const setting: ProjectConfig = {
|
||||
// 是否显示logo
|
||||
showLogo: true,
|
||||
|
||||
// 是否显示页脚
|
||||
showFooter: true,
|
||||
|
||||
// 头部配置
|
||||
headerSetting: {
|
||||
// header bg color
|
||||
bgColor: '#ffffff',
|
||||
fixed: true,
|
||||
// 是否显示顶部
|
||||
show: true,
|
||||
@ -69,6 +68,10 @@ const setting: ProjectConfig = {
|
||||
|
||||
// 菜单配置
|
||||
menuSetting: {
|
||||
// sidebar menu bg color
|
||||
bgColor: '#273352',
|
||||
|
||||
fixed: true,
|
||||
// 菜单折叠
|
||||
collapsed: false,
|
||||
// 折叠菜单时候是否显示菜单名
|
||||
@ -107,8 +110,7 @@ const setting: ProjectConfig = {
|
||||
show: true,
|
||||
// 开启快速操作
|
||||
showQuick: true,
|
||||
// 显示icon
|
||||
showIcon: false,
|
||||
|
||||
// 标签页缓存最大数量
|
||||
max: 12,
|
||||
},
|
||||
|
@ -2,3 +2,5 @@
|
||||
export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin';
|
||||
// vue-vben-admin-next-doc
|
||||
export const DOC_URL = 'https://vvbin.cn/doc-next/';
|
||||
// site url
|
||||
export const SITE_URL = 'https://vvbin.cn/next/';
|
||||
|
@ -53,7 +53,12 @@ export function initAppConfigStore() {
|
||||
if (!projCfg) {
|
||||
projCfg = projectSetting;
|
||||
}
|
||||
const { colorWeak, grayMode, headerBgColor, menuBgColor } = projCfg;
|
||||
const {
|
||||
colorWeak,
|
||||
grayMode,
|
||||
headerSetting: { bgColor: headerBgColor },
|
||||
menuSetting: { bgColor },
|
||||
} = projCfg;
|
||||
try {
|
||||
// if (
|
||||
// themeColor !== primaryColor &&
|
||||
@ -63,7 +68,7 @@ export function initAppConfigStore() {
|
||||
// updateTheme(themeColor);
|
||||
// }
|
||||
headerBgColor && updateHeaderBgColor(headerBgColor);
|
||||
menuBgColor && updateSidebarBgColor(menuBgColor);
|
||||
bgColor && updateSidebarBgColor(bgColor);
|
||||
grayMode && updateGrayMode(grayMode);
|
||||
colorWeak && updateColorWeak(colorWeak);
|
||||
} catch (error) {
|
||||
|
12
src/types/config.d.ts
vendored
12
src/types/config.d.ts
vendored
@ -4,6 +4,8 @@ import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from
|
||||
import type { LocaleType } from '/@/locales/types';
|
||||
|
||||
export interface MenuSetting {
|
||||
bgColor: string;
|
||||
fixed: boolean;
|
||||
collapsed: boolean;
|
||||
collapsedShowTitle: boolean;
|
||||
hasDrag: boolean;
|
||||
@ -26,13 +28,13 @@ export interface MultiTabsSetting {
|
||||
show: boolean;
|
||||
// 开启快速操作
|
||||
showQuick: boolean;
|
||||
// 显示icon
|
||||
showIcon: boolean;
|
||||
|
||||
// 缓存最大数量
|
||||
max: number;
|
||||
}
|
||||
|
||||
export interface HeaderSetting {
|
||||
bgColor: string;
|
||||
fixed: boolean;
|
||||
show: boolean;
|
||||
theme: ThemeEnum;
|
||||
@ -59,10 +61,7 @@ export interface LocaleSetting {
|
||||
|
||||
export interface ProjectConfig {
|
||||
locale: LocaleSetting;
|
||||
// header背景色
|
||||
headerBgColor: string;
|
||||
// 左侧菜单背景色
|
||||
menuBgColor: string;
|
||||
|
||||
// 是否显示配置按钮
|
||||
showSettingButton: boolean;
|
||||
// 权限模式
|
||||
@ -79,6 +78,7 @@ export interface ProjectConfig {
|
||||
contentMode: ContentEnum;
|
||||
// 是否显示logo
|
||||
showLogo: boolean;
|
||||
showFooter: boolean;
|
||||
headerSetting: HeaderSetting;
|
||||
// 菜单类型
|
||||
// menuType: MenuTypeEnum;
|
||||
|
8
src/types/global.d.ts
vendored
8
src/types/global.d.ts
vendored
@ -55,3 +55,11 @@ declare type TargetContext = '_self' | '_blank';
|
||||
declare type TimeoutHandle = ReturnType<typeof setTimeout>;
|
||||
|
||||
declare type IntervalHandle = ReturnType<typeof setInterval>;
|
||||
|
||||
declare interface ComponentElRef<T extends HTMLElement = HTMLDivElement> {
|
||||
$el: T;
|
||||
}
|
||||
|
||||
declare type ComponentRef<T extends HTMLElement = HTMLDivElement> = ComponentElRef<T> | null;
|
||||
|
||||
declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>;
|
||||
|
20
yarn.lock
20
yarn.lock
@ -1737,21 +1737,6 @@
|
||||
vscode-languageserver-textdocument "^1.0.1"
|
||||
vscode-uri "^2.1.2"
|
||||
|
||||
"@vueuse/core@^4.0.0-rc.3":
|
||||
version "4.0.0-rc.3"
|
||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-rc.3.tgz#5381ca657e10df596cd7027fc5c96b2d4b3a090c"
|
||||
integrity sha512-dQ/FZgo0z7kBFOvDWxuzaUrmuO8X1AlQk17e3PU1TVtG2Uu+mCvjPNbuvI2fjhTjl5rzPJawwoU2WZFj+nlFvw==
|
||||
dependencies:
|
||||
"@vueuse/shared" "4.0.0-rc.3"
|
||||
vue-demi latest
|
||||
|
||||
"@vueuse/shared@4.0.0-rc.3":
|
||||
version "4.0.0-rc.3"
|
||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-rc.3.tgz#42fb56fed3779f3b8a17a82c16a364bad20d01b7"
|
||||
integrity sha512-VY0x/XxpeTMHp/0FDiv1cgUUxkJGQl7liiM2AjR/J7+Ys/2Y2dijD5cAKViq9FGUPQQsOcLptMvMvUsDMoN4DA==
|
||||
dependencies:
|
||||
vue-demi latest
|
||||
|
||||
JSONStream@^1.0.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
|
||||
@ -8177,11 +8162,6 @@ vscode-uri@^2.1.2:
|
||||
resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c"
|
||||
integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==
|
||||
|
||||
vue-demi@latest:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.4.3.tgz#6aaa9b52f02c32b4f9d4d11f02a1ae71031453c3"
|
||||
integrity sha512-1DzLcZgHC9ZyFEYR4qZ83TdS1u9DglG8XVesBXqtbbmqFuO7sb8KG36kMfZCszieAweRDwAAVSAzjmEMG0+WwA==
|
||||
|
||||
vue-eslint-parser@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3"
|
||||
|
Loading…
Reference in New Issue
Block a user