mirror of
https://gitee.com/bootx/dax-pay-ui.git
synced 2025-09-17 17:32:47 +00:00
refactor: refactor layout
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
## Wip
|
## Wip
|
||||||
|
|
||||||
|
### ✨ Refactor
|
||||||
|
|
||||||
|
- 重构整体 layout。更改代码实现方式。代码更精简
|
||||||
|
|
||||||
### ✨ Features
|
### ✨ Features
|
||||||
|
|
||||||
- 缓存可以配置是否加密
|
- 缓存可以配置是否加密
|
||||||
@@ -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 {
|
|||||||
|
|
||||||
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 @@
|
|||||||
},
|
},
|
||||||
"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",
|
||||||
|
@@ -1,7 +1,11 @@
|
|||||||
<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 @@
|
|||||||
|
|
||||||
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 @@
|
|||||||
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 @@
|
|||||||
return {
|
return {
|
||||||
handleGoHome,
|
handleGoHome,
|
||||||
globSetting,
|
globSetting,
|
||||||
|
getCollapsedShowTitle,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -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 @@
|
|||||||
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({
|
|||||||
? `${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({
|
|||||||
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({
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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
|
|||||||
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,
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
.ant-layout {
|
.ant-layout {
|
||||||
background: #f0f2f5;
|
background: #f0f2f5;
|
||||||
|
|
||||||
&-content {
|
// &-content {
|
||||||
position: relative;
|
// position: relative;
|
||||||
overflow: hidden;
|
// overflow: hidden;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@@ -101,14 +101,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-layout() {
|
|
||||||
.ant-layout {
|
|
||||||
background: #f1f1f6 !important;
|
|
||||||
|
|
||||||
&-content {
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
22
src/hooks/core/useContext.ts
Normal file
22
src/hooks/core/useContext.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { InjectionKey, provide, inject, reactive, readonly } from 'vue';
|
||||||
|
|
||||||
|
export const createContext = <T>(
|
||||||
|
context: any,
|
||||||
|
contextInjectKey: InjectionKey<T> = Symbol(),
|
||||||
|
_readonly = true
|
||||||
|
) => {
|
||||||
|
const state = reactive({
|
||||||
|
...context,
|
||||||
|
});
|
||||||
|
const provideData = _readonly ? readonly(state) : state;
|
||||||
|
provide(contextInjectKey, provideData);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useContext = <T>(
|
||||||
|
contextInjectKey: InjectionKey<T> = Symbol(),
|
||||||
|
defaultValue?: any,
|
||||||
|
_readonly = true
|
||||||
|
): T => {
|
||||||
|
const state = inject(contextInjectKey, defaultValue || {});
|
||||||
|
return _readonly ? readonly(state) : state;
|
||||||
|
};
|
@@ -7,20 +7,50 @@ import { appStore } from '/@/store/modules/app';
|
|||||||
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
import { 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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
getHeaderSetting,
|
getHeaderSetting,
|
||||||
|
|
||||||
getShowDoc,
|
getShowDoc,
|
||||||
getTheme,
|
getHeaderTheme,
|
||||||
getShowRedo,
|
getShowRedo,
|
||||||
getUseLockPage,
|
getUseLockPage,
|
||||||
getShowFullScreen,
|
getShowFullScreen,
|
||||||
@@ -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() {
|
|||||||
// 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 getMode = computed(() => unref(getMenuSetting).mode);
|
const getMenuMode = computed(() => unref(getMenuSetting).mode);
|
||||||
|
|
||||||
const getShow = computed(() => unref(getMenuSetting).show);
|
const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
|
||||||
|
|
||||||
|
const getShowMenu = computed(() => unref(getMenuSetting).show);
|
||||||
|
|
||||||
|
const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
|
||||||
|
|
||||||
const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
|
const 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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
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() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
getShowTopMenu,
|
getShowTopMenu,
|
||||||
getShowHeaderTrigger,
|
getShowHeaderTrigger,
|
||||||
getTopMenuAlign,
|
getTopMenuAlign,
|
||||||
|
getMenuHidden,
|
||||||
|
getIsTopMenu,
|
||||||
|
getMenuBgColor,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -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() {
|
|||||||
|
|
||||||
getMultipleTabSetting,
|
getMultipleTabSetting,
|
||||||
getMax,
|
getMax,
|
||||||
getShow,
|
getShowMultipleTab,
|
||||||
|
getShowQuick,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
return {
|
return {
|
||||||
setRootSetting,
|
setRootSetting,
|
||||||
|
|
||||||
|
getFullContent,
|
||||||
|
getColorWeak,
|
||||||
|
getGrayMode,
|
||||||
getRootSetting,
|
getRootSetting,
|
||||||
|
getLayoutContentMode,
|
||||||
|
getPageLoading,
|
||||||
getOpenPageLoading,
|
getOpenPageLoading,
|
||||||
getOpenRouterTransition,
|
getOpenRouterTransition,
|
||||||
getOpenKeepAlive,
|
getOpenKeepAlive,
|
||||||
@@ -49,5 +75,9 @@ export function useRootSetting() {
|
|||||||
getUseErrorHandle,
|
getUseErrorHandle,
|
||||||
getShowBreadCrumb,
|
getShowBreadCrumb,
|
||||||
getShowBreadCrumbIcon,
|
getShowBreadCrumbIcon,
|
||||||
|
getUseOpenBackTop,
|
||||||
|
getShowSettingButton,
|
||||||
|
getShowFooter,
|
||||||
|
getContentMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,32 +0,0 @@
|
|||||||
import { computed, defineComponent, unref } from 'vue';
|
|
||||||
import { Layout } from 'ant-design-vue';
|
|
||||||
import { FullLoading } from '/@/components/Loading/index';
|
|
||||||
|
|
||||||
import { RouterView } from 'vue-router';
|
|
||||||
|
|
||||||
import { ContentEnum } from '/@/enums/appEnum';
|
|
||||||
import { appStore } from '/@/store/modules/app';
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'DefaultLayoutContent',
|
|
||||||
setup() {
|
|
||||||
const getProjectConfigRef = computed(() => {
|
|
||||||
return appStore.getProjectConfig;
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
const { contentMode, openPageLoading } = unref(getProjectConfigRef);
|
|
||||||
const { getPageLoading } = appStore;
|
|
||||||
const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed';
|
|
||||||
return (
|
|
||||||
<div class={[`default-layout__main`]}>
|
|
||||||
{openPageLoading && (
|
|
||||||
<FullLoading class={[`default-layout__loading`, !getPageLoading && 'hidden']} />
|
|
||||||
)}
|
|
||||||
<Layout.Content class={`layout-content ${wrapClass} `}>
|
|
||||||
{() => <RouterView />}
|
|
||||||
</Layout.Content>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,4 +1,4 @@
|
|||||||
import type { PropType } from 'vue';
|
import type { PropType, FunctionalComponent } from 'vue';
|
||||||
|
|
||||||
import { defineComponent, unref } from 'vue';
|
import { defineComponent, unref } from 'vue';
|
||||||
import {
|
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({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
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>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
21
src/layouts/default/content/index.less
Normal file
21
src/layouts/default/content/index.less
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@import (reference) '../../../design/index.less';
|
||||||
|
|
||||||
|
.layout-content {
|
||||||
|
position: relative;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
|
||||||
|
&.fixed {
|
||||||
|
width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__loading {
|
||||||
|
position: fixed;
|
||||||
|
z-index: @page-loading-z-index;
|
||||||
|
|
||||||
|
> .basic-loading {
|
||||||
|
margin-bottom: 20%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
src/layouts/default/content/index.tsx
Normal file
26
src/layouts/default/content/index.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import './index.less';
|
||||||
|
|
||||||
|
import { defineComponent, unref } from 'vue';
|
||||||
|
import { FullLoading } from '/@/components/Loading/index';
|
||||||
|
|
||||||
|
import { RouterView } from 'vue-router';
|
||||||
|
|
||||||
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutContent',
|
||||||
|
setup() {
|
||||||
|
const { getOpenPageLoading, getLayoutContentMode, getPageLoading } = useRootSetting();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<div class={['layout-content', unref(getLayoutContentMode)]}>
|
||||||
|
{unref(getOpenPageLoading) && (
|
||||||
|
<FullLoading class={[`layout-content__loading`, { hidden: !unref(getPageLoading) }]} />
|
||||||
|
)}
|
||||||
|
<RouterView />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
28
src/layouts/default/footer/index.less
Normal file
28
src/layouts/default/footer/index.less
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
@normal-color: rgba(0, 0, 0, 0.45);
|
||||||
|
|
||||||
|
@hover-color: rgba(0, 0, 0, 0.85);
|
||||||
|
|
||||||
|
.layout-footer {
|
||||||
|
color: @normal-color;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&__links {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @normal-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.github {
|
||||||
|
margin: 0 30px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @hover-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/layouts/default/footer/index.tsx
Normal file
31
src/layouts/default/footer/index.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import './index.less';
|
||||||
|
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { Layout } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { GithubFilled } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting';
|
||||||
|
import { openWindow } from '/@/utils';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutContent',
|
||||||
|
setup() {
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<Layout.Footer class="layout-footer">
|
||||||
|
{() => (
|
||||||
|
<>
|
||||||
|
<div class="layout-footer__links">
|
||||||
|
<a onClick={() => openWindow(SITE_URL)}>在线预览</a>
|
||||||
|
<GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" />
|
||||||
|
<a onClick={() => openWindow(DOC_URL)}>在线文档</a>
|
||||||
|
</div>
|
||||||
|
<div>Copyright ©2020 Vben Admin</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Layout.Footer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@@ -1,13 +1,15 @@
|
|||||||
import './index.less';
|
import './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';
|
|||||||
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({
|
|||||||
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({
|
|||||||
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({
|
|||||||
);
|
);
|
||||||
|
|
||||||
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({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 锁定屏幕
|
|
||||||
*/
|
|
||||||
function handleLockPage() {
|
function handleLockPage() {
|
||||||
openModal(true);
|
openModal(true);
|
||||||
}
|
}
|
||||||
@@ -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({
|
|||||||
<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,64 +170,47 @@ export default defineComponent({
|
|||||||
return (
|
return (
|
||||||
<div class={`layout-header__action`}>
|
<div class={`layout-header__action`}>
|
||||||
{unref(getUseErrorHandle) && (
|
{unref(getUseErrorHandle) && (
|
||||||
<Tooltip>
|
<TooltipItem title="错误日志">
|
||||||
{{
|
{() => (
|
||||||
title: () => '错误日志',
|
<Badge
|
||||||
default: () => (
|
count={errorStore.getErrorListCountState}
|
||||||
<Badge
|
offset={[0, 10]}
|
||||||
count={errorStore.getErrorListCountState}
|
dot
|
||||||
offset={[0, 10]}
|
overflowCount={99}
|
||||||
dot
|
>
|
||||||
overflowCount={99}
|
{() => renderActionDefault(BugOutlined, handleToErrorList)}
|
||||||
>
|
</Badge>
|
||||||
{() => renderActionDefault(BugOutlined, handleToErrorList)}
|
)}
|
||||||
</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) ? '退出全屏' : '全屏'),
|
const Icon = !unref(isFullscreenRef) ? (
|
||||||
default: () => {
|
<FullscreenOutlined />
|
||||||
const Icon = !unref(isFullscreenRef) ? (
|
) : (
|
||||||
<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({
|
|||||||
|
|
||||||
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>
|
||||||
);
|
);
|
||||||
|
10
src/layouts/default/header/LayoutMultipleHeader.less
Normal file
10
src/layouts/default/header/LayoutMultipleHeader.less
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.multiple-tab-header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
|
||||||
|
&.fixed {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
118
src/layouts/default/header/LayoutMultipleHeader.tsx
Normal file
118
src/layouts/default/header/LayoutMultipleHeader.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import './LayoutMultipleHeader.less';
|
||||||
|
|
||||||
|
import { defineComponent, unref, computed, ref, watch, nextTick, CSSProperties } from 'vue';
|
||||||
|
|
||||||
|
import LayoutHeader from './LayoutHeader';
|
||||||
|
import MultipleTabs from '../multitabs/index';
|
||||||
|
|
||||||
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
|
import { useFullContent } from '/@/hooks/web/useFullContent';
|
||||||
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||||
|
import { useLayoutContext } from '../useLayoutContext';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutMultipleHeader',
|
||||||
|
setup() {
|
||||||
|
const placeholderHeightRef = ref(0);
|
||||||
|
const fullHeaderHeightRef = ref(0);
|
||||||
|
const headerElRef = ref<ComponentRef>(null);
|
||||||
|
const tabElRef = ref<ComponentRef>(null);
|
||||||
|
|
||||||
|
const injectValue = useLayoutContext();
|
||||||
|
|
||||||
|
const { getCalcContentWidth } = useMenuSetting();
|
||||||
|
|
||||||
|
const {
|
||||||
|
getFixed,
|
||||||
|
getShowInsetHeaderRef,
|
||||||
|
getShowFullHeaderRef,
|
||||||
|
getShowHeader,
|
||||||
|
getUnFixedAndFull,
|
||||||
|
} = useHeaderSetting();
|
||||||
|
|
||||||
|
const { getFullContent } = useFullContent();
|
||||||
|
|
||||||
|
const { getShowMultipleTab } = useMultipleTabSetting();
|
||||||
|
|
||||||
|
const showTabsRef = computed(() => {
|
||||||
|
return unref(getShowMultipleTab) && !unref(getFullContent);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getPlaceholderDomStyle = computed(() => {
|
||||||
|
return {
|
||||||
|
height: `${unref(placeholderHeightRef)}px`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getIsShowPlaceholderDom = computed(() => {
|
||||||
|
return unref(getFixed) || unref(getShowFullHeaderRef);
|
||||||
|
});
|
||||||
|
|
||||||
|
const getWrapStyle = computed(() => {
|
||||||
|
const style: CSSProperties = {};
|
||||||
|
if (unref(getFixed)) {
|
||||||
|
style.width = unref(getCalcContentWidth);
|
||||||
|
}
|
||||||
|
if (unref(getShowFullHeaderRef)) {
|
||||||
|
style.top = `${unref(fullHeaderHeightRef)}px`;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getIsFixed = computed(() => {
|
||||||
|
return unref(getFixed) || unref(getShowFullHeaderRef);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [
|
||||||
|
unref(getFixed),
|
||||||
|
unref(getShowFullHeaderRef),
|
||||||
|
unref(getShowHeader),
|
||||||
|
unref(getShowMultipleTab),
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
if (unref(getUnFixedAndFull)) return;
|
||||||
|
nextTick(() => {
|
||||||
|
const headerEl = unref(headerElRef)?.$el;
|
||||||
|
const tabEl = unref(tabElRef)?.$el;
|
||||||
|
const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el;
|
||||||
|
|
||||||
|
let height = 0;
|
||||||
|
if (headerEl && !unref(getShowFullHeaderRef)) {
|
||||||
|
height += headerEl.offsetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tabEl) {
|
||||||
|
height += tabEl.offsetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fullHeaderEl && unref(getShowFullHeaderRef)) {
|
||||||
|
const fullHeaderHeight = fullHeaderEl.offsetHeight;
|
||||||
|
height += fullHeaderHeight;
|
||||||
|
fullHeaderHeightRef.value = fullHeaderHeight;
|
||||||
|
}
|
||||||
|
placeholderHeightRef.value = height;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{unref(getIsShowPlaceholderDom) && <div style={unref(getPlaceholderDomStyle)} />}
|
||||||
|
<div
|
||||||
|
style={unref(getWrapStyle)}
|
||||||
|
class={['multiple-tab-header', { fixed: unref(getIsFixed) }]}
|
||||||
|
>
|
||||||
|
{unref(getShowInsetHeaderRef) && <LayoutHeader ref={headerElRef} />}
|
||||||
|
{unref(showTabsRef) && <MultipleTabs ref={tabElRef} />}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@@ -15,15 +15,31 @@ import { DOC_URL } from '/@/settings/siteSetting';
|
|||||||
import { openWindow } from '/@/utils';
|
import { 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({
|
|||||||
openWindow(DOC_URL);
|
openWindow(DOC_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMenuClick(e: any) {
|
function handleMenuClick(e: { key: MenuEvent }) {
|
||||||
if (e.key === 'loginOut') {
|
switch (e.key) {
|
||||||
handleLoginOut();
|
case 'loginOut':
|
||||||
} else if (e.key === 'doc') {
|
handleLoginOut();
|
||||||
openDoc();
|
break;
|
||||||
|
case 'doc':
|
||||||
|
openDoc();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderItem({ icon, text, key }: RenderItemParams) {
|
|
||||||
return (
|
|
||||||
<Menu.Item key={key}>
|
|
||||||
{() => (
|
|
||||||
<span class="flex items-center">
|
|
||||||
<Icon icon={icon} class="mr-1" />
|
|
||||||
<span>{text}</span>
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSlotsDefault() {
|
function renderSlotsDefault() {
|
||||||
const { realName } = unref(getUserInfo);
|
const { realName } = unref(getUserInfo);
|
||||||
return (
|
return (
|
||||||
@@ -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 @@
|
|||||||
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 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__inner,
|
&__inner,
|
||||||
|
&__inner.is-link,
|
||||||
&__separator {
|
&__separator {
|
||||||
color: @white;
|
color: @white;
|
||||||
}
|
}
|
||||||
|
@@ -1,39 +1,12 @@
|
|||||||
@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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,129 +1,92 @@
|
|||||||
import { defineComponent, unref, computed } from 'vue';
|
import './index.less';
|
||||||
|
|
||||||
|
import { defineComponent, unref, computed, ref } from 'vue';
|
||||||
import { Layout, BackTop } from 'ant-design-vue';
|
import { 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, MenuTypeEnum } from '/@/enums/menuEnum';
|
import { MenuModeEnum } 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 { getShowFullHeaderRef } = useHeaderSetting();
|
||||||
|
|
||||||
|
const { getUseOpenBackTop, getShowSettingButton, getShowFooter } = useRootSetting();
|
||||||
|
|
||||||
|
const { getShowMenu, getMenuMode, getSplit } = useMenuSetting();
|
||||||
|
|
||||||
const { getFullContent } = useFullContent();
|
const { getFullContent } = useFullContent();
|
||||||
|
|
||||||
const getProjectConfigRef = computed(() => appStore.getProjectConfig);
|
const getShowLayoutFooter = computed(() => {
|
||||||
|
return unref(getShowFooter) && !unref(currentRoute).meta?.hiddenFooter;
|
||||||
const getLockMainScrollStateRef = computed(() => appStore.getLockMainScrollState);
|
|
||||||
|
|
||||||
const showHeaderRef = computed(() => {
|
|
||||||
const {
|
|
||||||
headerSetting: { show },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return show;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showMixHeaderRef = computed(() => {
|
|
||||||
const {
|
|
||||||
menuSetting: { type },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return type !== MenuTypeEnum.SIDEBAR && unref(showHeaderRef);
|
|
||||||
});
|
|
||||||
|
|
||||||
const getIsLockRef = computed(() => {
|
|
||||||
const { getLockInfo } = appStore;
|
|
||||||
const { isLock } = getLockInfo;
|
|
||||||
return isLock;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const 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(() => {
|
function renderFeatures() {
|
||||||
return !unref(getFullContent) && unref(showMixHeaderRef) && unref(showHeaderRef);
|
return (
|
||||||
});
|
<>
|
||||||
|
<LayoutLockPage />
|
||||||
const showInsetHeaderRef = computed(() => {
|
{/* back top */}
|
||||||
return !unref(getFullContent) && !unref(showMixHeaderRef) && unref(showHeaderRef);
|
{unref(getUseOpenBackTop) && <BackTop target={() => document.body} />}
|
||||||
});
|
{/* open setting drawer */}
|
||||||
|
{unref(getShowSettingButton) && <SettingBtn />}
|
||||||
const fixedHeaderClsRef = computed(() => {
|
</>
|
||||||
const {
|
);
|
||||||
headerSetting: { fixed },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
const fixedHeaderCls = fixed
|
|
||||||
? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '')
|
|
||||||
: '';
|
|
||||||
return fixedHeaderCls;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showTabsRef = computed(() => {
|
|
||||||
const {
|
|
||||||
multiTabsSetting: { show },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return show && !unref(getFullContent);
|
|
||||||
});
|
|
||||||
|
|
||||||
const showClassSideBarRef = computed(() => {
|
|
||||||
const {
|
|
||||||
menuSetting: { split, hidden },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return split ? hidden : true;
|
|
||||||
});
|
|
||||||
|
|
||||||
function getTarget(): any {
|
|
||||||
const {
|
|
||||||
headerSetting: { fixed },
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
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';
|
17
src/layouts/default/lock/index.tsx
Normal file
17
src/layouts/default/lock/index.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineComponent, unref, computed } from 'vue';
|
||||||
|
import { appStore } from '/@/store/modules/app';
|
||||||
|
import LockPage from '/@/views/sys/lock/index.vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutLockPage',
|
||||||
|
setup() {
|
||||||
|
const getIsLockRef = computed(() => {
|
||||||
|
const { getLockInfo } = appStore;
|
||||||
|
const { isLock } = getLockInfo;
|
||||||
|
return isLock;
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
return unref(getIsLockRef) ? <LockPage /> : null;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@@ -17,7 +17,7 @@ import { useSplitMenu } from './useLayoutMenu';
|
|||||||
import { openWindow } from '/@/utils';
|
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({
|
|||||||
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({
|
|||||||
|
|
||||||
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({
|
|||||||
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({
|
|||||||
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';
|
|||||||
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({
|
|||||||
/**
|
/**
|
||||||
* @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>
|
||||||
);
|
);
|
||||||
|
@@ -1,29 +1,36 @@
|
|||||||
import { defineComponent, computed, unref, ref } from 'vue';
|
import type { ProjectConfig } from '/@/types/config';
|
||||||
import { BasicDrawer } from '/@/components/Drawer/index';
|
|
||||||
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
|
||||||
import Button from '/@/components/Button/index.vue';
|
|
||||||
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
|
||||||
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { appStore } from '/@/store/modules/app';
|
|
||||||
import { ProjectConfig } from '/@/types/config';
|
|
||||||
|
|
||||||
import { useMessage } from '/@/hooks/web/useMessage';
|
|
||||||
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
|
|
||||||
|
|
||||||
import defaultSetting from '/@/settings/projectSetting';
|
import defaultSetting from '/@/settings/projectSetting';
|
||||||
|
|
||||||
import mixImg from '/@/assets/images/layout/menu-mix.svg';
|
import { defineComponent, computed, unref, FunctionalComponent } from 'vue';
|
||||||
import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg';
|
import { BasicDrawer } from '/@/components/Drawer/index';
|
||||||
import menuTopImg from '/@/assets/images/layout/menu-top.svg';
|
import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue';
|
||||||
|
import Button from '/@/components/Button/index.vue';
|
||||||
|
import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
import { MenuTypeEnum } from '/@/enums/menuEnum';
|
||||||
|
import { appStore } from '/@/store/modules/app';
|
||||||
|
|
||||||
|
import { useMessage } from '/@/hooks/web/useMessage';
|
||||||
|
import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
|
||||||
|
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
|
||||||
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
|
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
||||||
|
|
||||||
import { updateColorWeak, updateGrayMode } from '/@/setup/theme';
|
import { 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,215 +47,280 @@ interface SelectConfig {
|
|||||||
handler?: Fn;
|
handler?: Fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ThemeOptions {
|
interface ThemePickerProps {
|
||||||
def?: string;
|
colorList: string[];
|
||||||
handler?: Fn;
|
handler: Fn;
|
||||||
|
def: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { createSuccessModal, createMessage } = useMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menu type Picker comp
|
||||||
|
*/
|
||||||
|
const MenuTypePicker: FunctionalComponent = () => {
|
||||||
|
const { getIsHorizontal, getMenuType } = useMenuSetting();
|
||||||
|
return (
|
||||||
|
<div class={`setting-drawer__siderbar`}>
|
||||||
|
{menuTypeList.map((item) => {
|
||||||
|
const { title, type: ItemType, mode, src } = item;
|
||||||
|
return (
|
||||||
|
<Tooltip title={title} placement="bottom" key={title}>
|
||||||
|
{{
|
||||||
|
default: () => (
|
||||||
|
<div
|
||||||
|
onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {
|
||||||
|
mode: mode,
|
||||||
|
type: ItemType,
|
||||||
|
split: unref(getIsHorizontal) ? false : undefined,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<CheckOutlined
|
||||||
|
class={['check-icon', unref(getMenuType) === ItemType ? 'active' : '']}
|
||||||
|
/>
|
||||||
|
<img src={src} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ThemePicker: FunctionalComponent<ThemePickerProps> = (props) => {
|
||||||
|
return (
|
||||||
|
<div class={`setting-drawer__theme-item`}>
|
||||||
|
{props.colorList.map((color) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
onClick={() => props.handler?.(color)}
|
||||||
|
key={color}
|
||||||
|
class={[props.def === color ? 'active' : '']}
|
||||||
|
style={{
|
||||||
|
background: color,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CheckOutlined class="icon" />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FooterButton component
|
||||||
|
*/
|
||||||
|
const FooterButton: FunctionalComponent = () => {
|
||||||
|
const { getRootSetting } = useRootSetting();
|
||||||
|
function handleCopy() {
|
||||||
|
const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2));
|
||||||
|
unref(isSuccessRef) &&
|
||||||
|
createSuccessModal({
|
||||||
|
title: '操作成功',
|
||||||
|
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function handleResetSetting() {
|
||||||
|
try {
|
||||||
|
appStore.commitProjectConfigState(defaultSetting);
|
||||||
|
const { colorWeak, grayMode } = defaultSetting;
|
||||||
|
// updateTheme(themeColor);
|
||||||
|
updateColorWeak(colorWeak);
|
||||||
|
updateGrayMode(grayMode);
|
||||||
|
createMessage.success('重置成功!');
|
||||||
|
} catch (error) {
|
||||||
|
createMessage.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClearAndRedo() {
|
||||||
|
localStorage.clear();
|
||||||
|
appStore.resumeAllState();
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="setting-drawer__footer">
|
||||||
|
<Button type="primary" block onClick={handleCopy}>
|
||||||
|
{() => (
|
||||||
|
<>
|
||||||
|
<CopyOutlined class="mr-2" />
|
||||||
|
拷贝
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<Button block class="mt-2" onClick={handleResetSetting} color="warning">
|
||||||
|
{() => (
|
||||||
|
<>
|
||||||
|
<RedoOutlined class="mr-2" />
|
||||||
|
重置
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
<Button block class="mt-2" onClick={handleClearAndRedo} color="error">
|
||||||
|
{() => (
|
||||||
|
<>
|
||||||
|
<RedoOutlined class="mr-2" />
|
||||||
|
清空缓存并返回登录页
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SettingDrawer',
|
name: 'SettingDrawer',
|
||||||
setup(_, { attrs }) {
|
setup(_, { attrs }) {
|
||||||
const { createSuccessModal, createMessage } = useMessage();
|
const {
|
||||||
|
getContentMode,
|
||||||
|
getRouterTransition,
|
||||||
|
getOpenRouterTransition,
|
||||||
|
getOpenPageLoading,
|
||||||
|
getShowFooter,
|
||||||
|
getShowBreadCrumb,
|
||||||
|
getShowBreadCrumbIcon,
|
||||||
|
getShowLogo,
|
||||||
|
getFullContent,
|
||||||
|
getColorWeak,
|
||||||
|
getGrayMode,
|
||||||
|
} = useRootSetting();
|
||||||
|
|
||||||
const getProjectConfigRef = computed(() => {
|
const {
|
||||||
return appStore.getProjectConfig;
|
getIsHorizontal,
|
||||||
});
|
getShowMenu,
|
||||||
|
getMenuType,
|
||||||
|
getTrigger,
|
||||||
|
getCollapsedShowTitle,
|
||||||
|
getMenuFixed,
|
||||||
|
getCollapsed,
|
||||||
|
getShowSearch,
|
||||||
|
getHasDrag,
|
||||||
|
getTopMenuAlign,
|
||||||
|
getAccordion,
|
||||||
|
getMenuWidth,
|
||||||
|
getMenuBgColor,
|
||||||
|
getIsTopMenu,
|
||||||
|
getSplit,
|
||||||
|
} = useMenuSetting();
|
||||||
|
|
||||||
const getIsHorizontalRef = computed(() => {
|
const { getShowHeader, getFixed: getHeaderFixed, getHeaderBgColor } = useHeaderSetting();
|
||||||
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getShowHeaderRef = computed(() => {
|
const { getShowMultipleTab, getShowQuick } = useMultipleTabSetting();
|
||||||
return unref(getProjectConfigRef).headerSetting.show;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getShowMenuRef = computed(() => {
|
const getShowMenuRef = computed(() => {
|
||||||
return unref(getProjectConfigRef).menuSetting.show && !unref(getIsHorizontalRef);
|
return unref(getShowMenu) && !unref(getIsHorizontal);
|
||||||
});
|
});
|
||||||
|
|
||||||
const getShowTabsRef = computed(() => {
|
|
||||||
return unref(getProjectConfigRef).multiTabsSetting.show;
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleCopy() {
|
|
||||||
const { isSuccessRef } = useCopyToClipboard(
|
|
||||||
JSON.stringify(unref(getProjectConfigRef), null, 2)
|
|
||||||
);
|
|
||||||
unref(isSuccessRef) &&
|
|
||||||
createSuccessModal({
|
|
||||||
title: '操作成功',
|
|
||||||
content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleResetSetting() {
|
|
||||||
try {
|
|
||||||
appStore.commitProjectConfigState(defaultSetting);
|
|
||||||
const { colorWeak, grayMode } = defaultSetting;
|
|
||||||
// updateTheme(themeColor);
|
|
||||||
updateColorWeak(colorWeak);
|
|
||||||
updateGrayMode(grayMode);
|
|
||||||
createMessage.success('重置成功!');
|
|
||||||
} catch (error) {
|
|
||||||
createMessage.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleClearAndRedo() {
|
|
||||||
localStorage.clear();
|
|
||||||
appStore.resumeAllState();
|
|
||||||
location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSidebar() {
|
function renderSidebar() {
|
||||||
const {
|
return (
|
||||||
menuSetting: { type, split },
|
<>
|
||||||
} = unref(getProjectConfigRef);
|
<MenuTypePicker />
|
||||||
|
{renderSwitchItem('分割菜单', {
|
||||||
const typeList = ref([
|
handler: (e) => {
|
||||||
{
|
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
||||||
title: '左侧菜单模式',
|
},
|
||||||
mode: MenuModeEnum.INLINE,
|
def: unref(getSplit),
|
||||||
type: MenuTypeEnum.SIDEBAR,
|
disabled: !unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX,
|
||||||
src: sidebarImg,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '混合模式',
|
|
||||||
mode: MenuModeEnum.INLINE,
|
|
||||||
type: MenuTypeEnum.MIX,
|
|
||||||
src: mixImg,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: '顶部菜单模式',
|
|
||||||
mode: MenuModeEnum.HORIZONTAL,
|
|
||||||
type: MenuTypeEnum.TOP_MENU,
|
|
||||||
src: menuTopImg,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
return [
|
|
||||||
<div class={`setting-drawer__siderbar`}>
|
|
||||||
{unref(typeList).map((item) => {
|
|
||||||
const { title, type: ItemType, mode, src } = item;
|
|
||||||
return (
|
|
||||||
<Tooltip title={title} placement="bottom" key={title}>
|
|
||||||
{{
|
|
||||||
default: () => (
|
|
||||||
<div
|
|
||||||
onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, {
|
|
||||||
mode: mode,
|
|
||||||
type: ItemType,
|
|
||||||
split: unref(getIsHorizontalRef) ? false : undefined,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<CheckOutlined class={['check-icon', type === ItemType ? 'active' : '']} />
|
|
||||||
<img src={src} />
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
})}
|
})}
|
||||||
</div>,
|
</>
|
||||||
renderSwitchItem('分割菜单', {
|
);
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.MENU_SPLIT, e);
|
|
||||||
},
|
|
||||||
def: split,
|
|
||||||
disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX,
|
|
||||||
}),
|
|
||||||
// renderSelectItem('顶栏主题', {
|
|
||||||
// handler: (e) => {
|
|
||||||
// baseHandler(HandlerEnum.HEADER_THEME, e);
|
|
||||||
// },
|
|
||||||
// def: headerTheme,
|
|
||||||
// options: themeOptions,
|
|
||||||
// disabled: !unref(getShowHeaderRef),
|
|
||||||
// }),
|
|
||||||
// renderSelectItem('菜单主题', {
|
|
||||||
// handler: (e) => {
|
|
||||||
// baseHandler(HandlerEnum.MENU_THEME, e);
|
|
||||||
// },
|
|
||||||
// def: menuTheme,
|
|
||||||
// options: themeOptions,
|
|
||||||
// disabled: !unref(getShowMenuRef),
|
|
||||||
// }),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderTheme() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Divider>{() => '顶栏主题'}</Divider>
|
||||||
|
<ThemePicker
|
||||||
|
colorList={HEADER_PRESET_BG_COLOR_LIST}
|
||||||
|
def={unref(getHeaderBgColor)}
|
||||||
|
handler={(e) => {
|
||||||
|
baseHandler(HandlerEnum.HEADER_THEME, e);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Divider>{() => '菜单主题'}</Divider>
|
||||||
|
<ThemePicker
|
||||||
|
colorList={SIDE_BAR_BG_COLOR_LIST}
|
||||||
|
def={unref(getMenuBgColor)}
|
||||||
|
handler={(e) => {
|
||||||
|
baseHandler(HandlerEnum.MENU_THEME, e);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description:
|
* @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({
|
|||||||
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({
|
|||||||
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,120 +367,111 @@ export default defineComponent({
|
|||||||
</div>,
|
</div>,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
function renderTransition() {
|
|
||||||
const { routerTransition, openRouterTransition, openPageLoading } = appStore.getProjectConfig;
|
|
||||||
|
|
||||||
|
function renderContent() {
|
||||||
|
return [
|
||||||
|
renderSwitchItem('面包屑', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowBreadCrumb),
|
||||||
|
disabled: !unref(getShowHeader),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('面包屑图标', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowBreadCrumbIcon),
|
||||||
|
disabled: !unref(getShowHeader),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('标签页', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.TABS_SHOW, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowMultipleTab),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('标签页快捷按钮', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowQuick),
|
||||||
|
disabled: !unref(getShowMultipleTab),
|
||||||
|
}),
|
||||||
|
|
||||||
|
renderSwitchItem('左侧菜单', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowMenu),
|
||||||
|
disabled: unref(getIsHorizontal),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('顶栏', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowHeader),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('Logo', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.SHOW_LOGO, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowLogo),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('页脚', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.SHOW_FOOTER, e);
|
||||||
|
},
|
||||||
|
def: unref(getShowFooter),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('全屏内容', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
||||||
|
},
|
||||||
|
def: unref(getFullContent),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('灰色模式', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.GRAY_MODE, e);
|
||||||
|
},
|
||||||
|
def: unref(getGrayMode),
|
||||||
|
}),
|
||||||
|
renderSwitchItem('色弱模式', {
|
||||||
|
handler: (e) => {
|
||||||
|
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
||||||
|
},
|
||||||
|
def: unref(getColorWeak),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTransition() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{renderSwitchItem('页面切换loading', {
|
{renderSwitchItem('页面切换loading', {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e);
|
||||||
},
|
},
|
||||||
def: openPageLoading,
|
def: unref(getOpenPageLoading),
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{renderSwitchItem('切换动画', {
|
{renderSwitchItem('切换动画', {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e);
|
||||||
},
|
},
|
||||||
def: openRouterTransition,
|
def: unref(getOpenRouterTransition),
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{renderSelectItem('路由动画', {
|
{renderSelectItem('路由动画', {
|
||||||
handler: (e) => {
|
handler: (e) => {
|
||||||
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
baseHandler(HandlerEnum.ROUTER_TRANSITION, e);
|
||||||
},
|
},
|
||||||
def: routerTransition,
|
def: unref(getRouterTransition),
|
||||||
options: routerTransitionOptions,
|
options: routerTransitionOptions,
|
||||||
disabled: !openRouterTransition,
|
disabled: !unref(getOpenRouterTransition),
|
||||||
})}
|
})}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function renderContent() {
|
|
||||||
const {
|
|
||||||
grayMode,
|
|
||||||
colorWeak,
|
|
||||||
fullContent,
|
|
||||||
showLogo,
|
|
||||||
headerSetting: { show: showHeader },
|
|
||||||
menuSetting: { show: showMenu },
|
|
||||||
multiTabsSetting: { show: showMultiple, showQuick, showIcon: showTabIcon },
|
|
||||||
showBreadCrumb,
|
|
||||||
showBreadCrumbIcon,
|
|
||||||
} = unref(getProjectConfigRef);
|
|
||||||
return [
|
|
||||||
renderSwitchItem('面包屑', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB, e);
|
|
||||||
},
|
|
||||||
def: showBreadCrumb,
|
|
||||||
disabled: !unref(getShowHeaderRef),
|
|
||||||
}),
|
|
||||||
renderSwitchItem('面包屑图标', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e);
|
|
||||||
},
|
|
||||||
def: showBreadCrumbIcon,
|
|
||||||
disabled: !unref(getShowHeaderRef),
|
|
||||||
}),
|
|
||||||
renderSwitchItem('标签页', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.TABS_SHOW, e);
|
|
||||||
},
|
|
||||||
def: showMultiple,
|
|
||||||
}),
|
|
||||||
renderSwitchItem('标签页快捷按钮', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.TABS_SHOW_QUICK, e);
|
|
||||||
},
|
|
||||||
def: showQuick,
|
|
||||||
disabled: !unref(getShowTabsRef),
|
|
||||||
}),
|
|
||||||
renderSwitchItem('标签页图标', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.TABS_SHOW_ICON, e);
|
|
||||||
},
|
|
||||||
def: showTabIcon,
|
|
||||||
disabled: !unref(getShowTabsRef),
|
|
||||||
}),
|
|
||||||
renderSwitchItem('左侧菜单', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e);
|
|
||||||
},
|
|
||||||
def: showMenu,
|
|
||||||
disabled: unref(getIsHorizontalRef),
|
|
||||||
}),
|
|
||||||
renderSwitchItem('顶栏', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.HEADER_SHOW, e);
|
|
||||||
},
|
|
||||||
def: showHeader,
|
|
||||||
}),
|
|
||||||
renderSwitchItem('Logo', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.SHOW_LOGO, e);
|
|
||||||
},
|
|
||||||
def: showLogo,
|
|
||||||
}),
|
|
||||||
renderSwitchItem('全屏内容', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.FULL_CONTENT, e);
|
|
||||||
},
|
|
||||||
def: fullContent,
|
|
||||||
}),
|
|
||||||
renderSwitchItem('灰色模式', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.GRAY_MODE, e);
|
|
||||||
},
|
|
||||||
def: grayMode,
|
|
||||||
}),
|
|
||||||
renderSwitchItem('色弱模式', {
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.COLOR_WEAK, e);
|
|
||||||
},
|
|
||||||
def: colorWeak,
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderSelectItem(text: string, config?: SelectConfig) {
|
function renderSelectItem(text: string, config?: SelectConfig) {
|
||||||
const { handler, def, disabled = false, options } = config || {};
|
const { handler, def, disabled = false, options } = config || {};
|
||||||
@@ -449,50 +512,6 @@ export default defineComponent({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderTheme() {
|
|
||||||
const { headerBgColor, menuBgColor } = unref(getProjectConfigRef);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Divider>{() => '顶栏主题'}</Divider>
|
|
||||||
{renderThemeItem(HEADER_PRESET_BG_COLOR_LIST, {
|
|
||||||
def: headerBgColor,
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.HEADER_THEME, e);
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
<Divider>{() => '菜单主题'}</Divider>
|
|
||||||
{renderThemeItem(SIDE_BAR_BG_COLOR_LIST, {
|
|
||||||
def: menuBgColor,
|
|
||||||
handler: (e) => {
|
|
||||||
baseHandler(HandlerEnum.MENU_THEME, e);
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderThemeItem(colorList: string[], opt: ThemeOptions) {
|
|
||||||
const { def, handler } = opt;
|
|
||||||
return (
|
|
||||||
<div class={`setting-drawer__theme-item`}>
|
|
||||||
{colorList.map((item) => {
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
onClick={() => handler && handler(item)}
|
|
||||||
key={item}
|
|
||||||
class={[def === item ? 'active' : '']}
|
|
||||||
style={{
|
|
||||||
background: item,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CheckOutlined class="icon" />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
|
<BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer">
|
||||||
{{
|
{{
|
||||||
@@ -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({
|
|||||||
<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>
|
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
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 = [
|
|||||||
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,
|
||||||
|
},
|
||||||
|
];
|
@@ -1,5 +1,4 @@
|
|||||||
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
|
|||||||
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
|
|||||||
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 @@
|
|||||||
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 },
|
||||||
|
@@ -1,77 +0,0 @@
|
|||||||
import './index.less';
|
|
||||||
|
|
||||||
import { computed, defineComponent, ref, unref } from 'vue';
|
|
||||||
|
|
||||||
import { Layout } from 'ant-design-vue';
|
|
||||||
import LayoutMenu from '/@/layouts/default/menu/LayoutMenu';
|
|
||||||
|
|
||||||
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
|
||||||
|
|
||||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
|
||||||
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'LayoutSideBar',
|
|
||||||
setup() {
|
|
||||||
const dragBarRef = ref<Nullable<HTMLDivElement>>(null);
|
|
||||||
const sideRef = ref<Nullable<HTMLDivElement>>(null);
|
|
||||||
|
|
||||||
const { getCollapsed, getMenuWidth, getSplit, getTheme } = useMenuSetting();
|
|
||||||
|
|
||||||
const { getTriggerAttr, getTriggerSlot } = useTrigger();
|
|
||||||
|
|
||||||
const { renderDragLine } = useDragLine(sideRef, dragBarRef);
|
|
||||||
|
|
||||||
const {
|
|
||||||
getCollapsedWidth,
|
|
||||||
onBreakpointChange,
|
|
||||||
onCollapseChange,
|
|
||||||
onSiderClick,
|
|
||||||
} = useSiderEvent();
|
|
||||||
|
|
||||||
const getMode = computed(() => {
|
|
||||||
return unref(getSplit) ? MenuModeEnum.INLINE : null;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getSplitType = computed(() => {
|
|
||||||
return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE;
|
|
||||||
});
|
|
||||||
|
|
||||||
function renderDefault() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<LayoutMenu
|
|
||||||
theme={unref(getTheme)}
|
|
||||||
menuMode={unref(getMode)}
|
|
||||||
splitType={unref(getSplitType)}
|
|
||||||
/>
|
|
||||||
{renderDragLine()}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
return (
|
|
||||||
<Layout.Sider
|
|
||||||
ref={sideRef}
|
|
||||||
class="layout-sidebar"
|
|
||||||
breakpoint="md"
|
|
||||||
collapsible
|
|
||||||
width={unref(getMenuWidth)}
|
|
||||||
collapsed={unref(getCollapsed)}
|
|
||||||
collapsedWidth={unref(getCollapsedWidth)}
|
|
||||||
theme={unref(getTheme)}
|
|
||||||
onClick={onSiderClick}
|
|
||||||
onCollapse={onCollapseChange}
|
|
||||||
onBreakpoint={onBreakpointChange}
|
|
||||||
{...unref(getTriggerAttr)}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
...unref(getTriggerSlot),
|
|
||||||
default: () => renderDefault(),
|
|
||||||
}}
|
|
||||||
</Layout.Sider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,7 +1,14 @@
|
|||||||
@import (reference) '../../../design/index.less';
|
@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 @@
|
|||||||
|
|
||||||
&: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 {
|
||||||
|
150
src/layouts/default/sider/index.tsx
Normal file
150
src/layouts/default/sider/index.tsx
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import './index.less';
|
||||||
|
|
||||||
|
import { computed, defineComponent, ref, unref, watch, nextTick } from 'vue';
|
||||||
|
|
||||||
|
import { Layout } from 'ant-design-vue';
|
||||||
|
import LayoutMenu from '../menu';
|
||||||
|
|
||||||
|
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||||
|
|
||||||
|
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||||
|
import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting';
|
||||||
|
import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider';
|
||||||
|
import { useLayoutContext } from '../useLayoutContext';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'LayoutSideBar',
|
||||||
|
setup() {
|
||||||
|
const topRef = ref(0);
|
||||||
|
const dragBarRef = ref<ElRef>(null);
|
||||||
|
const sideRef = ref<ElRef>(null);
|
||||||
|
|
||||||
|
const {
|
||||||
|
getCollapsed,
|
||||||
|
getMenuWidth,
|
||||||
|
getSplit,
|
||||||
|
getMenuTheme,
|
||||||
|
getRealWidth,
|
||||||
|
getMenuHidden,
|
||||||
|
getMenuFixed,
|
||||||
|
} = useMenuSetting();
|
||||||
|
|
||||||
|
const { getShowFullHeaderRef, getUnFixedAndFull } = useHeaderSetting();
|
||||||
|
|
||||||
|
const injectValue = useLayoutContext();
|
||||||
|
|
||||||
|
const { getTriggerAttr, getTriggerSlot } = useTrigger();
|
||||||
|
|
||||||
|
const { renderDragLine } = useDragLine(sideRef, dragBarRef);
|
||||||
|
|
||||||
|
const {
|
||||||
|
getCollapsedWidth,
|
||||||
|
onBreakpointChange,
|
||||||
|
onCollapseChange,
|
||||||
|
onSiderClick,
|
||||||
|
} = useSiderEvent();
|
||||||
|
|
||||||
|
const getMode = computed(() => {
|
||||||
|
return unref(getSplit) ? MenuModeEnum.INLINE : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getSplitType = computed(() => {
|
||||||
|
return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE;
|
||||||
|
});
|
||||||
|
|
||||||
|
const showClassSideBarRef = computed(() => {
|
||||||
|
return unref(getSplit) ? unref(getMenuHidden) : true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getSiderClass = computed(() => {
|
||||||
|
return {
|
||||||
|
'layout-sidebar': true,
|
||||||
|
fixed: unref(getMenuFixed),
|
||||||
|
hidden: !unref(showClassSideBarRef),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getSiderStyle = computed(() => {
|
||||||
|
const top = `${unref(topRef)}px`;
|
||||||
|
if (!unref(getMenuFixed)) {
|
||||||
|
return { top };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
top,
|
||||||
|
height: `calc(100% - ${top})`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => getShowFullHeaderRef.value,
|
||||||
|
() => {
|
||||||
|
topRef.value = 0;
|
||||||
|
if (unref(getUnFixedAndFull)) return;
|
||||||
|
nextTick(() => {
|
||||||
|
const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el;
|
||||||
|
if (!fullHeaderEl) return;
|
||||||
|
topRef.value = fullHeaderEl.offsetHeight;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const getHiddenDomStyle = computed(() => {
|
||||||
|
const width = `${unref(getRealWidth)}px`;
|
||||||
|
return {
|
||||||
|
width: width,
|
||||||
|
overflow: 'hidden',
|
||||||
|
flex: `0 0 ${width}`,
|
||||||
|
'max-width': width,
|
||||||
|
'min-width': width,
|
||||||
|
transition: 'all 0.2s',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderDefault() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LayoutMenu
|
||||||
|
theme={unref(getMenuTheme)}
|
||||||
|
menuMode={unref(getMode)}
|
||||||
|
splitType={unref(getSplitType)}
|
||||||
|
/>
|
||||||
|
{renderDragLine()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{unref(getMenuFixed) && (
|
||||||
|
<div style={unref(getHiddenDomStyle)} class={{ hidden: !unref(showClassSideBarRef) }} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Layout.Sider
|
||||||
|
ref={sideRef}
|
||||||
|
breakpoint="md"
|
||||||
|
collapsible
|
||||||
|
class={unref(getSiderClass)}
|
||||||
|
style={unref(getSiderStyle)}
|
||||||
|
width={unref(getMenuWidth)}
|
||||||
|
collapsed={unref(getCollapsed)}
|
||||||
|
collapsedWidth={unref(getCollapsedWidth)}
|
||||||
|
theme={unref(getMenuTheme)}
|
||||||
|
onClick={onSiderClick}
|
||||||
|
onCollapse={onCollapseChange}
|
||||||
|
onBreakpoint={onBreakpointChange}
|
||||||
|
{...unref(getTriggerAttr)}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
...unref(getTriggerSlot),
|
||||||
|
default: () => renderDefault(),
|
||||||
|
}}
|
||||||
|
</Layout.Sider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
@@ -16,7 +16,7 @@ export function useSiderEvent() {
|
|||||||
const brokenRef = ref(false);
|
const 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() {
|
|||||||
|
|
||||||
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 };
|
||||||
|
16
src/layouts/default/useLayoutContext.ts
Normal file
16
src/layouts/default/useLayoutContext.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { InjectionKey, Ref } from 'vue';
|
||||||
|
import { createContext, useContext } from '/@/hooks/core/useContext';
|
||||||
|
|
||||||
|
export interface LayoutContextProps {
|
||||||
|
fullHeaderRef: Ref<ComponentRef>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const layoutContextInjectKey: InjectionKey<LayoutContextProps> = Symbol();
|
||||||
|
|
||||||
|
export function createLayoutContext(context: LayoutContextProps) {
|
||||||
|
return createContext<LayoutContextProps>(context, layoutContextInjectKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useLayoutContext() {
|
||||||
|
return useContext<LayoutContextProps>(layoutContextInjectKey);
|
||||||
|
}
|
@@ -12,7 +12,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
|
|||||||
|
|
||||||
export function useFrameKeepAlive() {
|
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() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
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({
|
|||||||
|
|
||||||
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 = {
|
|||||||
// 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 = {
|
|||||||
// 是否显示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 = {
|
|||||||
|
|
||||||
// 菜单配置
|
// 菜单配置
|
||||||
menuSetting: {
|
menuSetting: {
|
||||||
|
// sidebar menu bg color
|
||||||
|
bgColor: '#273352',
|
||||||
|
|
||||||
|
fixed: true,
|
||||||
// 菜单折叠
|
// 菜单折叠
|
||||||
collapsed: false,
|
collapsed: false,
|
||||||
// 折叠菜单时候是否显示菜单名
|
// 折叠菜单时候是否显示菜单名
|
||||||
@@ -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 @@
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
// 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) {
|
||||||
|
12
src/types/config.d.ts
vendored
12
src/types/config.d.ts
vendored
@@ -4,6 +4,8 @@ import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from
|
|||||||
import type { LocaleType } from '/@/locales/types';
|
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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 {
|
|||||||
contentMode: ContentEnum;
|
contentMode: ContentEnum;
|
||||||
// 是否显示logo
|
// 是否显示logo
|
||||||
showLogo: boolean;
|
showLogo: boolean;
|
||||||
|
showFooter: boolean;
|
||||||
headerSetting: HeaderSetting;
|
headerSetting: HeaderSetting;
|
||||||
// 菜单类型
|
// 菜单类型
|
||||||
// menuType: MenuTypeEnum;
|
// menuType: MenuTypeEnum;
|
||||||
|
8
src/types/global.d.ts
vendored
8
src/types/global.d.ts
vendored
@@ -55,3 +55,11 @@ declare type TargetContext = '_self' | '_blank';
|
|||||||
declare type TimeoutHandle = ReturnType<typeof setTimeout>;
|
declare type 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>;
|
||||||
|
20
yarn.lock
20
yarn.lock
@@ -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:
|
|||||||
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"
|
||||||
|
Reference in New Issue
Block a user