提交 0692b479 作者: vben

refactor: refactor layout

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