Commit 0692b4798c0f3391a2cb583e30dcca5345aba407
1 parent
25d43a5f
refactor: refactor layout
Showing
50 changed files
with
1148 additions
and
817 deletions
CHANGELOG.zh_CN.md
1 | ## Wip | 1 | ## Wip |
2 | 2 | ||
3 | +### ✨ Refactor | ||
4 | + | ||
5 | +- 重构整体 layout。更改代码实现方式。代码更精简 | ||
6 | + | ||
3 | ### ✨ Features | 7 | ### ✨ Features |
4 | 8 | ||
5 | - 缓存可以配置是否加密 | 9 | - 缓存可以配置是否加密 |
@@ -7,6 +11,7 @@ | @@ -7,6 +11,7 @@ | ||
7 | ### 🎫 Chores | 11 | ### 🎫 Chores |
8 | 12 | ||
9 | - 移除 messageSetting 配置 | 13 | - 移除 messageSetting 配置 |
14 | +- 暂时删除 `@vueuse/core`.等稳定后在集成。目前不太稳定。 | ||
10 | 15 | ||
11 | ## 2.0.0-rc.11 (2020-11-18) | 16 | ## 2.0.0-rc.11 (2020-11-18) |
12 | 17 |
build/vite/plugin/transform/globby/index.ts
@@ -154,15 +154,17 @@ const globTransform = function (config: SharedConfig): Transform { | @@ -154,15 +154,17 @@ const globTransform = function (config: SharedConfig): Transform { | ||
154 | 154 | ||
155 | const groups: Array<string>[] = []; | 155 | const groups: Array<string>[] = []; |
156 | const replaceFiles = files.map((f, i) => { | 156 | const replaceFiles = files.map((f, i) => { |
157 | - const fileNameWithAlias = resolver.fileToRequest(f); | ||
158 | - | ||
159 | - const file = bareExporter + fileNameWithAlias + bareExporter; | 157 | + const filePath = resolver.fileToRequest(f); |
158 | + const file = bareExporter + filePath + bareExporter; | ||
160 | 159 | ||
161 | if (isLocale) { | 160 | if (isLocale) { |
162 | const globrexRes = globrex(globPath, { extended: true, globstar: true }); | 161 | const globrexRes = globrex(globPath, { extended: true, globstar: true }); |
163 | 162 | ||
164 | // Get segments for files like an en/system ch/modules for: | 163 | // Get segments for files like an en/system ch/modules for: |
165 | // ['en', 'system'] ['ch', 'modules'] | 164 | // ['en', 'system'] ['ch', 'modules'] |
165 | + | ||
166 | + // TODO The window system and mac system path are inconsistent? | ||
167 | + const fileNameWithAlias = filePath.replace(/^(\/src\/)/, '/@/'); | ||
166 | const matchedGroups = globrexRes.regex.exec(fileNameWithAlias); | 168 | const matchedGroups = globrexRes.regex.exec(fileNameWithAlias); |
167 | 169 | ||
168 | if (matchedGroups && matchedGroups.length) { | 170 | if (matchedGroups && matchedGroups.length) { |
package.json
@@ -22,7 +22,6 @@ | @@ -22,7 +22,6 @@ | ||
22 | }, | 22 | }, |
23 | "dependencies": { | 23 | "dependencies": { |
24 | "@iconify/iconify": "^2.0.0-rc.2", | 24 | "@iconify/iconify": "^2.0.0-rc.2", |
25 | - "@vueuse/core": "^4.0.0-rc.3", | ||
26 | "ant-design-vue": "2.0.0-beta.15", | 25 | "ant-design-vue": "2.0.0-beta.15", |
27 | "apexcharts": "3.22.0", | 26 | "apexcharts": "3.22.0", |
28 | "axios": "^0.21.0", | 27 | "axios": "^0.21.0", |
src/components/Application/src/AppLogo.vue
1 | <template> | 1 | <template> |
2 | - <div class="app-logo anticon" :class="theme" @click="handleGoHome"> | 2 | + <div |
3 | + class="app-logo anticon" | ||
4 | + :class="{ theme, 'collapsed-show-title': getCollapsedShowTitle }" | ||
5 | + @click="handleGoHome" | ||
6 | + > | ||
3 | <img src="/@/assets/images/logo.png" /> | 7 | <img src="/@/assets/images/logo.png" /> |
4 | - <div class="app-logo__title ml-2 ellipsis">{{ globSetting.title }}</div> | 8 | + <div class="app-logo__title ml-2 ellipsis" v-show="showTitle">{{ globSetting.title }}</div> |
5 | </div> | 9 | </div> |
6 | </template> | 10 | </template> |
7 | <script lang="ts"> | 11 | <script lang="ts"> |
@@ -10,6 +14,7 @@ | @@ -10,6 +14,7 @@ | ||
10 | 14 | ||
11 | import { useGlobSetting } from '/@/hooks/setting'; | 15 | import { useGlobSetting } from '/@/hooks/setting'; |
12 | import { useGo } from '/@/hooks/web/usePage'; | 16 | import { useGo } from '/@/hooks/web/usePage'; |
17 | + import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | ||
13 | 18 | ||
14 | import { PageEnum } from '/@/enums/pageEnum'; | 19 | import { PageEnum } from '/@/enums/pageEnum'; |
15 | 20 | ||
@@ -22,8 +27,13 @@ | @@ -22,8 +27,13 @@ | ||
22 | theme: { | 27 | theme: { |
23 | type: String as PropType<string>, | 28 | type: String as PropType<string>, |
24 | }, | 29 | }, |
30 | + showTitle: { | ||
31 | + type: Boolean, | ||
32 | + default: true, | ||
33 | + }, | ||
25 | }, | 34 | }, |
26 | setup() { | 35 | setup() { |
36 | + const { getCollapsedShowTitle } = useMenuSetting(); | ||
27 | const globSetting = useGlobSetting(); | 37 | const globSetting = useGlobSetting(); |
28 | const go = useGo(); | 38 | const go = useGo(); |
29 | 39 | ||
@@ -34,6 +44,7 @@ | @@ -34,6 +44,7 @@ | ||
34 | return { | 44 | return { |
35 | handleGoHome, | 45 | handleGoHome, |
36 | globSetting, | 46 | globSetting, |
47 | + getCollapsedShowTitle, | ||
37 | }; | 48 | }; |
38 | }, | 49 | }, |
39 | }); | 50 | }); |
@@ -44,9 +55,13 @@ | @@ -44,9 +55,13 @@ | ||
44 | .app-logo { | 55 | .app-logo { |
45 | display: flex; | 56 | display: flex; |
46 | align-items: center; | 57 | align-items: center; |
47 | - padding-left: 16px; | 58 | + padding-left: 10px; |
48 | cursor: pointer; | 59 | cursor: pointer; |
49 | 60 | ||
61 | + &.collapsed-show-title { | ||
62 | + padding-left: 20px; | ||
63 | + } | ||
64 | + | ||
50 | &.light { | 65 | &.light { |
51 | border-bottom: 1px solid @border-color-base; | 66 | border-bottom: 1px solid @border-color-base; |
52 | } | 67 | } |
@@ -64,6 +79,7 @@ | @@ -64,6 +79,7 @@ | ||
64 | font-weight: 700; | 79 | font-weight: 700; |
65 | opacity: 0; | 80 | opacity: 0; |
66 | transition: all 0.5s; | 81 | transition: all 0.5s; |
82 | + | ||
67 | .respond-to(medium,{ | 83 | .respond-to(medium,{ |
68 | opacity: 1; | 84 | opacity: 1; |
69 | }); | 85 | }); |
src/components/Drawer/src/BasicDrawer.tsx
@@ -49,7 +49,7 @@ export default defineComponent({ | @@ -49,7 +49,7 @@ export default defineComponent({ | ||
49 | ? `${opt.wrapClassName} ${prefixCls}__detail` | 49 | ? `${opt.wrapClassName} ${prefixCls}__detail` |
50 | : `${prefixCls}__detail`; | 50 | : `${prefixCls}__detail`; |
51 | if (!opt.getContainer) { | 51 | if (!opt.getContainer) { |
52 | - opt.getContainer = `.default-layout__main`; | 52 | + opt.getContainer = '.layout-content'; |
53 | } | 53 | } |
54 | } | 54 | } |
55 | return opt; | 55 | return opt; |
src/components/Menu/src/BasicMenu.tsx
@@ -80,7 +80,7 @@ export default defineComponent({ | @@ -80,7 +80,7 @@ export default defineComponent({ | ||
80 | offset += 46; | 80 | offset += 46; |
81 | } | 81 | } |
82 | return { | 82 | return { |
83 | - height: `calc(100% - ${offset - 12}px)`, | 83 | + height: `calc(100% - ${offset}px)`, |
84 | position: 'relative', | 84 | position: 'relative', |
85 | overflowY: 'auto', | 85 | overflowY: 'auto', |
86 | }; | 86 | }; |
src/components/Modal/src/BasicModal.tsx
@@ -219,11 +219,7 @@ export default defineComponent({ | @@ -219,11 +219,7 @@ export default defineComponent({ | ||
219 | emit('register', modalMethods, uuid); | 219 | emit('register', modalMethods, uuid); |
220 | 220 | ||
221 | return () => ( | 221 | return () => ( |
222 | - <Modal | ||
223 | - onCancel={handleCancel} | ||
224 | - getContainer={() => document.querySelector('.default-layout__main')} | ||
225 | - {...{ ...attrs, ...props, ...unref(getProps) }} | ||
226 | - > | 222 | + <Modal onCancel={handleCancel} {...{ ...attrs, ...props, ...unref(getProps) }}> |
227 | {{ | 223 | {{ |
228 | footer: () => renderFooter(), | 224 | footer: () => renderFooter(), |
229 | closeIcon: () => renderClose(), | 225 | closeIcon: () => renderClose(), |
src/components/Modal/src/useModal.ts
@@ -33,6 +33,7 @@ export function useModal(): UseModalReturnType { | @@ -33,6 +33,7 @@ export function useModal(): UseModalReturnType { | ||
33 | 33 | ||
34 | modalRef.value = modalMethod; | 34 | modalRef.value = modalMethod; |
35 | } | 35 | } |
36 | + | ||
36 | const getInstance = () => { | 37 | const getInstance = () => { |
37 | const instance = unref(modalRef); | 38 | const instance = unref(modalRef); |
38 | if (!instance) { | 39 | if (!instance) { |
@@ -50,6 +51,7 @@ export function useModal(): UseModalReturnType { | @@ -50,6 +51,7 @@ export function useModal(): UseModalReturnType { | ||
50 | getInstance().setModalProps({ | 51 | getInstance().setModalProps({ |
51 | visible: visible, | 52 | visible: visible, |
52 | }); | 53 | }); |
54 | + | ||
53 | if (data) { | 55 | if (data) { |
54 | dataTransferRef[unref(uidRef)] = openOnSet | 56 | dataTransferRef[unref(uidRef)] = openOnSet |
55 | ? { | 57 | ? { |
src/components/Table/src/hooks/useTableScroll.ts
@@ -43,7 +43,6 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe | @@ -43,7 +43,6 @@ export function useTableScroll(refProps: ComputedRef<BasicTableProps>, tableElRe | ||
43 | const tableEl: Element = table.$el; | 43 | const tableEl: Element = table.$el; |
44 | if (!tableEl) return; | 44 | if (!tableEl) return; |
45 | const headEl = tableEl.querySelector('.ant-table-thead '); | 45 | const headEl = tableEl.querySelector('.ant-table-thead '); |
46 | - // const layoutMain: Element | null = document.querySelector('.default-layout__main '); | ||
47 | if (!headEl) return; | 46 | if (!headEl) return; |
48 | 47 | ||
49 | // 表格距离底部高度 | 48 | // 表格距离底部高度 |
src/design/index.less
@@ -35,7 +35,7 @@ html, | @@ -35,7 +35,7 @@ html, | ||
35 | body { | 35 | body { |
36 | width: 100%; | 36 | width: 100%; |
37 | height: 100%; | 37 | height: 100%; |
38 | - overflow: hidden; | 38 | + overflow-x: hidden; |
39 | 39 | ||
40 | &.color-weak { | 40 | &.color-weak { |
41 | filter: invert(80%); | 41 | filter: invert(80%); |
@@ -160,9 +160,7 @@ object { | @@ -160,9 +160,7 @@ object { | ||
160 | vertical-align: baseline !important; | 160 | vertical-align: baseline !important; |
161 | } | 161 | } |
162 | 162 | ||
163 | -#app, | ||
164 | -#app > div, | ||
165 | -.ant-layout { | 163 | +#app { |
166 | width: 100%; | 164 | width: 100%; |
167 | height: 100%; | 165 | height: 100%; |
168 | } | 166 | } |
@@ -170,8 +168,8 @@ object { | @@ -170,8 +168,8 @@ object { | ||
170 | .ant-layout { | 168 | .ant-layout { |
171 | background: #f0f2f5; | 169 | background: #f0f2f5; |
172 | 170 | ||
173 | - &-content { | ||
174 | - position: relative; | ||
175 | - overflow: hidden; | ||
176 | - } | 171 | + // &-content { |
172 | + // position: relative; | ||
173 | + // overflow: hidden; | ||
174 | + // } | ||
177 | } | 175 | } |
src/design/reset.less
src/hooks/core/useContext.ts
0 → 100644
1 | +import { InjectionKey, provide, inject, reactive, readonly } from 'vue'; | ||
2 | + | ||
3 | +export const createContext = <T>( | ||
4 | + context: any, | ||
5 | + contextInjectKey: InjectionKey<T> = Symbol(), | ||
6 | + _readonly = true | ||
7 | +) => { | ||
8 | + const state = reactive({ | ||
9 | + ...context, | ||
10 | + }); | ||
11 | + const provideData = _readonly ? readonly(state) : state; | ||
12 | + provide(contextInjectKey, provideData); | ||
13 | +}; | ||
14 | + | ||
15 | +export const useContext = <T>( | ||
16 | + contextInjectKey: InjectionKey<T> = Symbol(), | ||
17 | + defaultValue?: any, | ||
18 | + _readonly = true | ||
19 | +): T => { | ||
20 | + const state = inject(contextInjectKey, defaultValue || {}); | ||
21 | + return _readonly ? readonly(state) : state; | ||
22 | +}; |
src/hooks/setting/useHeaderSetting.ts
@@ -7,20 +7,50 @@ import { appStore } from '/@/store/modules/app'; | @@ -7,20 +7,50 @@ import { appStore } from '/@/store/modules/app'; | ||
7 | import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | 7 | import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; |
8 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | 8 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
9 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; | 9 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
10 | +import { useFullContent } from '/@/hooks/web/useFullContent'; | ||
10 | 11 | ||
11 | import { MenuModeEnum } from '/@/enums/menuEnum'; | 12 | import { MenuModeEnum } from '/@/enums/menuEnum'; |
12 | 13 | ||
13 | export function useHeaderSetting() { | 14 | export function useHeaderSetting() { |
14 | - const { getShow: getShowMultipleTab } = useMultipleTabSetting(); | ||
15 | - const { getMode, getSplit, getShowHeaderTrigger, getIsSidebarType } = useMenuSetting(); | 15 | + const { getFullContent } = useFullContent(); |
16 | + const { getShowMultipleTab } = useMultipleTabSetting(); | ||
17 | + const { | ||
18 | + getMenuMode, | ||
19 | + getSplit, | ||
20 | + getShowHeaderTrigger, | ||
21 | + getIsSidebarType, | ||
22 | + getIsTopMenu, | ||
23 | + } = useMenuSetting(); | ||
16 | const { getShowBreadCrumb, getShowLogo } = useRootSetting(); | 24 | const { getShowBreadCrumb, getShowLogo } = useRootSetting(); |
17 | 25 | ||
26 | + const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader)); | ||
27 | + | ||
28 | + const getShowFullHeaderRef = computed(() => { | ||
29 | + return ( | ||
30 | + !unref(getFullContent) && | ||
31 | + unref(getShowMixHeaderRef) && | ||
32 | + unref(getShowHeader) && | ||
33 | + !unref(getIsTopMenu) | ||
34 | + ); | ||
35 | + }); | ||
36 | + | ||
37 | + const getShowInsetHeaderRef = computed(() => { | ||
38 | + const need = !unref(getFullContent) && unref(getShowHeader); | ||
39 | + return (need && !unref(getShowMixHeaderRef)) || (need && unref(getIsTopMenu)); | ||
40 | + }); | ||
41 | + | ||
18 | // Get header configuration | 42 | // Get header configuration |
19 | const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting); | 43 | const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting); |
20 | 44 | ||
21 | const getShowDoc = computed(() => unref(getHeaderSetting).showDoc); | 45 | const getShowDoc = computed(() => unref(getHeaderSetting).showDoc); |
22 | 46 | ||
23 | - const getTheme = computed(() => unref(getHeaderSetting).theme); | 47 | + const getHeaderTheme = computed(() => unref(getHeaderSetting).theme); |
48 | + | ||
49 | + const getShowHeader = computed(() => unref(getHeaderSetting).show); | ||
50 | + | ||
51 | + const getFixed = computed(() => unref(getHeaderSetting).fixed); | ||
52 | + | ||
53 | + const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor); | ||
24 | 54 | ||
25 | const getShowRedo = computed(() => unref(getHeaderSetting).showRedo && unref(getShowMultipleTab)); | 55 | const getShowRedo = computed(() => unref(getHeaderSetting).showRedo && unref(getShowMultipleTab)); |
26 | 56 | ||
@@ -30,9 +60,11 @@ export function useHeaderSetting() { | @@ -30,9 +60,11 @@ export function useHeaderSetting() { | ||
30 | 60 | ||
31 | const getShowNotice = computed(() => unref(getHeaderSetting).showNotice); | 61 | const getShowNotice = computed(() => unref(getHeaderSetting).showNotice); |
32 | 62 | ||
63 | + const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef)); | ||
64 | + | ||
33 | const getShowBread = computed(() => { | 65 | const getShowBread = computed(() => { |
34 | return ( | 66 | return ( |
35 | - unref(getMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit) | 67 | + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit) |
36 | ); | 68 | ); |
37 | }); | 69 | }); |
38 | 70 | ||
@@ -55,7 +87,7 @@ export function useHeaderSetting() { | @@ -55,7 +87,7 @@ export function useHeaderSetting() { | ||
55 | getHeaderSetting, | 87 | getHeaderSetting, |
56 | 88 | ||
57 | getShowDoc, | 89 | getShowDoc, |
58 | - getTheme, | 90 | + getHeaderTheme, |
59 | getShowRedo, | 91 | getShowRedo, |
60 | getUseLockPage, | 92 | getUseLockPage, |
61 | getShowFullScreen, | 93 | getShowFullScreen, |
@@ -63,5 +95,12 @@ export function useHeaderSetting() { | @@ -63,5 +95,12 @@ export function useHeaderSetting() { | ||
63 | getShowBread, | 95 | getShowBread, |
64 | getShowContent, | 96 | getShowContent, |
65 | getShowHeaderLogo, | 97 | getShowHeaderLogo, |
98 | + getShowHeader, | ||
99 | + getFixed, | ||
100 | + getShowMixHeaderRef, | ||
101 | + getShowFullHeaderRef, | ||
102 | + getShowInsetHeaderRef, | ||
103 | + getUnFixedAndFull, | ||
104 | + getHeaderBgColor, | ||
66 | }; | 105 | }; |
67 | } | 106 | } |
src/hooks/setting/useMenuSetting.ts
@@ -11,24 +11,28 @@ export function useMenuSetting() { | @@ -11,24 +11,28 @@ export function useMenuSetting() { | ||
11 | // Get menu configuration | 11 | // Get menu configuration |
12 | const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting); | 12 | const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting); |
13 | 13 | ||
14 | - const getMiniWidth = computed(() => unref(getMenuSetting).menuWidth); | ||
15 | - | ||
16 | const getCollapsed = computed(() => unref(getMenuSetting).collapsed); | 14 | const getCollapsed = computed(() => unref(getMenuSetting).collapsed); |
17 | 15 | ||
18 | - const getType = computed(() => unref(getMenuSetting).type); | 16 | + const getMenuType = computed(() => unref(getMenuSetting).type); |
17 | + | ||
18 | + const getMenuMode = computed(() => unref(getMenuSetting).mode); | ||
19 | 19 | ||
20 | - const getMode = computed(() => unref(getMenuSetting).mode); | 20 | + const getMenuFixed = computed(() => unref(getMenuSetting).fixed); |
21 | 21 | ||
22 | - const getShow = computed(() => unref(getMenuSetting).show); | 22 | + const getShowMenu = computed(() => unref(getMenuSetting).show); |
23 | + | ||
24 | + const getMenuHidden = computed(() => unref(getMenuSetting).hidden); | ||
23 | 25 | ||
24 | const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth); | 26 | const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth); |
25 | 27 | ||
26 | const getTrigger = computed(() => unref(getMenuSetting).trigger); | 28 | const getTrigger = computed(() => unref(getMenuSetting).trigger); |
27 | 29 | ||
28 | - const getTheme = computed(() => unref(getMenuSetting).theme); | 30 | + const getMenuTheme = computed(() => unref(getMenuSetting).theme); |
29 | 31 | ||
30 | const getSplit = computed(() => unref(getMenuSetting).split); | 32 | const getSplit = computed(() => unref(getMenuSetting).split); |
31 | 33 | ||
34 | + const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor); | ||
35 | + | ||
32 | const getHasDrag = computed(() => unref(getMenuSetting).hasDrag); | 36 | const getHasDrag = computed(() => unref(getMenuSetting).hasDrag); |
33 | 37 | ||
34 | const getAccordion = computed(() => unref(getMenuSetting).accordion); | 38 | const getAccordion = computed(() => unref(getMenuSetting).accordion); |
@@ -39,17 +43,19 @@ export function useMenuSetting() { | @@ -39,17 +43,19 @@ export function useMenuSetting() { | ||
39 | 43 | ||
40 | const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign); | 44 | const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign); |
41 | 45 | ||
42 | - const getIsSidebarType = computed(() => unref(getType) === MenuTypeEnum.SIDEBAR); | 46 | + const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR); |
47 | + | ||
48 | + const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU); | ||
43 | 49 | ||
44 | const getShowTopMenu = computed(() => { | 50 | const getShowTopMenu = computed(() => { |
45 | - return unref(getMode) === MenuModeEnum.HORIZONTAL || unref(getSplit); | 51 | + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit); |
46 | }); | 52 | }); |
47 | 53 | ||
48 | const getShowHeaderTrigger = computed(() => { | 54 | const getShowHeaderTrigger = computed(() => { |
49 | if ( | 55 | if ( |
50 | - unref(getType) === MenuTypeEnum.TOP_MENU || | ||
51 | - !unref(getShow) || | ||
52 | - !unref(getMenuSetting).hidden | 56 | + unref(getMenuType) === MenuTypeEnum.TOP_MENU || |
57 | + !unref(getShowMenu) || | ||
58 | + !unref(getMenuHidden) | ||
53 | ) { | 59 | ) { |
54 | return false; | 60 | return false; |
55 | } | 61 | } |
@@ -60,12 +66,16 @@ export function useMenuSetting() { | @@ -60,12 +66,16 @@ export function useMenuSetting() { | ||
60 | const getShowSearch = computed(() => { | 66 | const getShowSearch = computed(() => { |
61 | return ( | 67 | return ( |
62 | unref(getMenuSetting).showSearch && | 68 | unref(getMenuSetting).showSearch && |
63 | - !(unref(getType) === MenuTypeEnum.MIX && unref(getMode) === MenuModeEnum.HORIZONTAL) | 69 | + !(unref(getMenuType) === MenuTypeEnum.MIX && unref(getMenuMode) === MenuModeEnum.HORIZONTAL) |
64 | ); | 70 | ); |
65 | }); | 71 | }); |
66 | 72 | ||
67 | const getIsHorizontal = computed(() => { | 73 | const getIsHorizontal = computed(() => { |
68 | - return unref(getMode) === MenuModeEnum.HORIZONTAL; | 74 | + return unref(getMenuMode) === MenuModeEnum.HORIZONTAL; |
75 | + }); | ||
76 | + | ||
77 | + const getRealWidth = computed(() => { | ||
78 | + return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth); | ||
69 | }); | 79 | }); |
70 | 80 | ||
71 | const getMiniWidthNumber = computed(() => { | 81 | const getMiniWidthNumber = computed(() => { |
@@ -74,8 +84,8 @@ export function useMenuSetting() { | @@ -74,8 +84,8 @@ export function useMenuSetting() { | ||
74 | }); | 84 | }); |
75 | 85 | ||
76 | const getCalcContentWidth = computed(() => { | 86 | const getCalcContentWidth = computed(() => { |
77 | - const width = unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMiniWidth); | ||
78 | - return `calc(100% - ${width}px)`; | 87 | + const width = unref(getIsTopMenu) || !unref(getShowMenu) ? 0 : unref(getRealWidth); |
88 | + return `calc(100% - ${unref(width)}px)`; | ||
79 | }); | 89 | }); |
80 | 90 | ||
81 | // Set menu configuration | 91 | // Set menu configuration |
@@ -94,18 +104,19 @@ export function useMenuSetting() { | @@ -94,18 +104,19 @@ export function useMenuSetting() { | ||
94 | 104 | ||
95 | toggleCollapsed, | 105 | toggleCollapsed, |
96 | 106 | ||
107 | + getMenuFixed, | ||
97 | getMenuSetting, | 108 | getMenuSetting, |
98 | - getMiniWidth, | ||
99 | - getType, | ||
100 | - getMode, | ||
101 | - getShow, | 109 | + getRealWidth, |
110 | + getMenuType, | ||
111 | + getMenuMode, | ||
112 | + getShowMenu, | ||
102 | getCollapsed, | 113 | getCollapsed, |
103 | getMiniWidthNumber, | 114 | getMiniWidthNumber, |
104 | getCalcContentWidth, | 115 | getCalcContentWidth, |
105 | getMenuWidth, | 116 | getMenuWidth, |
106 | getTrigger, | 117 | getTrigger, |
107 | getSplit, | 118 | getSplit, |
108 | - getTheme, | 119 | + getMenuTheme, |
109 | getHasDrag, | 120 | getHasDrag, |
110 | getIsHorizontal, | 121 | getIsHorizontal, |
111 | getShowSearch, | 122 | getShowSearch, |
@@ -116,5 +127,8 @@ export function useMenuSetting() { | @@ -116,5 +127,8 @@ export function useMenuSetting() { | ||
116 | getShowTopMenu, | 127 | getShowTopMenu, |
117 | getShowHeaderTrigger, | 128 | getShowHeaderTrigger, |
118 | getTopMenuAlign, | 129 | getTopMenuAlign, |
130 | + getMenuHidden, | ||
131 | + getIsTopMenu, | ||
132 | + getMenuBgColor, | ||
119 | }; | 133 | }; |
120 | } | 134 | } |
src/hooks/setting/useMultipleTabSetting.ts
@@ -9,7 +9,9 @@ export function useMultipleTabSetting() { | @@ -9,7 +9,9 @@ export function useMultipleTabSetting() { | ||
9 | 9 | ||
10 | const getMax = computed(() => unref(getMultipleTabSetting).max); | 10 | const getMax = computed(() => unref(getMultipleTabSetting).max); |
11 | 11 | ||
12 | - const getShow = computed(() => unref(getMultipleTabSetting).show); | 12 | + const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show); |
13 | + | ||
14 | + const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick); | ||
13 | 15 | ||
14 | function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) { | 16 | function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) { |
15 | appStore.commitProjectConfigState({ multiTabsSetting }); | 17 | appStore.commitProjectConfigState({ multiTabsSetting }); |
@@ -20,6 +22,7 @@ export function useMultipleTabSetting() { | @@ -20,6 +22,7 @@ export function useMultipleTabSetting() { | ||
20 | 22 | ||
21 | getMultipleTabSetting, | 23 | getMultipleTabSetting, |
22 | getMax, | 24 | getMax, |
23 | - getShow, | 25 | + getShowMultipleTab, |
26 | + getShowQuick, | ||
24 | }; | 27 | }; |
25 | } | 28 | } |
src/hooks/setting/useRootSetting.ts
@@ -3,6 +3,7 @@ import type { ProjectConfig } from '/@/types/config'; | @@ -3,6 +3,7 @@ import type { ProjectConfig } from '/@/types/config'; | ||
3 | import { computed, unref } from 'vue'; | 3 | import { computed, unref } from 'vue'; |
4 | 4 | ||
5 | import { appStore } from '/@/store/modules/app'; | 5 | import { appStore } from '/@/store/modules/app'; |
6 | +import { ContentEnum } from '/@/enums/appEnum'; | ||
6 | 7 | ||
7 | type RootSetting = Omit< | 8 | type RootSetting = Omit< |
8 | ProjectConfig, | 9 | ProjectConfig, |
@@ -13,6 +14,8 @@ export function useRootSetting() { | @@ -13,6 +14,8 @@ export function useRootSetting() { | ||
13 | 14 | ||
14 | const getOpenPageLoading = computed(() => unref(getRootSetting).openPageLoading); | 15 | const getOpenPageLoading = computed(() => unref(getRootSetting).openPageLoading); |
15 | 16 | ||
17 | + const getPageLoading = computed(() => appStore.getPageLoading); | ||
18 | + | ||
16 | const getOpenRouterTransition = computed(() => unref(getRootSetting).openRouterTransition); | 19 | const getOpenRouterTransition = computed(() => unref(getRootSetting).openRouterTransition); |
17 | 20 | ||
18 | const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive); | 21 | const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive); |
@@ -25,12 +28,30 @@ export function useRootSetting() { | @@ -25,12 +28,30 @@ export function useRootSetting() { | ||
25 | 28 | ||
26 | const getShowLogo = computed(() => unref(getRootSetting).showLogo); | 29 | const getShowLogo = computed(() => unref(getRootSetting).showLogo); |
27 | 30 | ||
31 | + const getContentMode = computed(() => unref(getRootSetting).contentMode); | ||
32 | + | ||
33 | + const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop); | ||
34 | + | ||
35 | + const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton); | ||
36 | + | ||
28 | const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle); | 37 | const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle); |
29 | 38 | ||
39 | + const getShowFooter = computed(() => unref(getRootSetting).showFooter); | ||
40 | + | ||
30 | const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb); | 41 | const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb); |
31 | 42 | ||
32 | const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon); | 43 | const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon); |
33 | 44 | ||
45 | + const getFullContent = computed(() => unref(getRootSetting).fullContent); | ||
46 | + | ||
47 | + const getColorWeak = computed(() => unref(getRootSetting).colorWeak); | ||
48 | + | ||
49 | + const getGrayMode = computed(() => unref(getRootSetting).grayMode); | ||
50 | + | ||
51 | + const getLayoutContentMode = computed(() => | ||
52 | + unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED | ||
53 | + ); | ||
54 | + | ||
34 | function setRootSetting(setting: RootSetting) { | 55 | function setRootSetting(setting: RootSetting) { |
35 | appStore.commitProjectConfigState(setting); | 56 | appStore.commitProjectConfigState(setting); |
36 | } | 57 | } |
@@ -38,7 +59,12 @@ export function useRootSetting() { | @@ -38,7 +59,12 @@ export function useRootSetting() { | ||
38 | return { | 59 | return { |
39 | setRootSetting, | 60 | setRootSetting, |
40 | 61 | ||
62 | + getFullContent, | ||
63 | + getColorWeak, | ||
64 | + getGrayMode, | ||
41 | getRootSetting, | 65 | getRootSetting, |
66 | + getLayoutContentMode, | ||
67 | + getPageLoading, | ||
42 | getOpenPageLoading, | 68 | getOpenPageLoading, |
43 | getOpenRouterTransition, | 69 | getOpenRouterTransition, |
44 | getOpenKeepAlive, | 70 | getOpenKeepAlive, |
@@ -49,5 +75,9 @@ export function useRootSetting() { | @@ -49,5 +75,9 @@ export function useRootSetting() { | ||
49 | getUseErrorHandle, | 75 | getUseErrorHandle, |
50 | getShowBreadCrumb, | 76 | getShowBreadCrumb, |
51 | getShowBreadCrumbIcon, | 77 | getShowBreadCrumbIcon, |
78 | + getUseOpenBackTop, | ||
79 | + getShowSettingButton, | ||
80 | + getShowFooter, | ||
81 | + getContentMode, | ||
52 | }; | 82 | }; |
53 | } | 83 | } |
src/layouts/default/LayoutContent.tsx deleted
100644 → 0
1 | -import { computed, defineComponent, unref } from 'vue'; | ||
2 | -import { Layout } from 'ant-design-vue'; | ||
3 | -import { FullLoading } from '/@/components/Loading/index'; | ||
4 | - | ||
5 | -import { RouterView } from 'vue-router'; | ||
6 | - | ||
7 | -import { ContentEnum } from '/@/enums/appEnum'; | ||
8 | -import { appStore } from '/@/store/modules/app'; | ||
9 | -export default defineComponent({ | ||
10 | - name: 'DefaultLayoutContent', | ||
11 | - setup() { | ||
12 | - const getProjectConfigRef = computed(() => { | ||
13 | - return appStore.getProjectConfig; | ||
14 | - }); | ||
15 | - | ||
16 | - return () => { | ||
17 | - const { contentMode, openPageLoading } = unref(getProjectConfigRef); | ||
18 | - const { getPageLoading } = appStore; | ||
19 | - const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed'; | ||
20 | - return ( | ||
21 | - <div class={[`default-layout__main`]}> | ||
22 | - {openPageLoading && ( | ||
23 | - <FullLoading class={[`default-layout__loading`, !getPageLoading && 'hidden']} /> | ||
24 | - )} | ||
25 | - <Layout.Content class={`layout-content ${wrapClass} `}> | ||
26 | - {() => <RouterView />} | ||
27 | - </Layout.Content> | ||
28 | - </div> | ||
29 | - ); | ||
30 | - }; | ||
31 | - }, | ||
32 | -}); |
src/layouts/default/LayoutTrigger.tsx
1 | -import type { PropType } from 'vue'; | 1 | +import type { PropType, FunctionalComponent } from 'vue'; |
2 | 2 | ||
3 | import { defineComponent, unref } from 'vue'; | 3 | import { defineComponent, unref } from 'vue'; |
4 | import { | 4 | import { |
@@ -10,6 +10,22 @@ import { | @@ -10,6 +10,22 @@ import { | ||
10 | 10 | ||
11 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | 11 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
12 | 12 | ||
13 | +const SiderTrigger: FunctionalComponent = () => { | ||
14 | + const { getCollapsed } = useMenuSetting(); | ||
15 | + return unref(getCollapsed) ? <DoubleRightOutlined /> : <DoubleLeftOutlined />; | ||
16 | +}; | ||
17 | + | ||
18 | +const HeaderTrigger: FunctionalComponent<{ | ||
19 | + theme?: string; | ||
20 | +}> = (props) => { | ||
21 | + const { toggleCollapsed, getCollapsed } = useMenuSetting(); | ||
22 | + return ( | ||
23 | + <span class={['layout-trigger', props.theme]} onClick={toggleCollapsed}> | ||
24 | + {unref(getCollapsed) ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />} | ||
25 | + </span> | ||
26 | + ); | ||
27 | +}; | ||
28 | + | ||
13 | export default defineComponent({ | 29 | export default defineComponent({ |
14 | name: 'LayoutTrigger', | 30 | name: 'LayoutTrigger', |
15 | props: { | 31 | props: { |
@@ -22,20 +38,8 @@ export default defineComponent({ | @@ -22,20 +38,8 @@ export default defineComponent({ | ||
22 | }, | 38 | }, |
23 | }, | 39 | }, |
24 | setup(props) { | 40 | setup(props) { |
25 | - const { toggleCollapsed, getCollapsed } = useMenuSetting(); | ||
26 | - | ||
27 | return () => { | 41 | return () => { |
28 | - const siderTrigger = unref(getCollapsed) ? <DoubleRightOutlined /> : <DoubleLeftOutlined />; | ||
29 | - | ||
30 | - if (props.sider) { | ||
31 | - return siderTrigger; | ||
32 | - } | ||
33 | - | ||
34 | - return ( | ||
35 | - <span class={['layout-trigger', props.theme]} onClick={toggleCollapsed}> | ||
36 | - {unref(getCollapsed) ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />} | ||
37 | - </span> | ||
38 | - ); | 42 | + return props.sider ? <SiderTrigger /> : <HeaderTrigger theme={props.theme} />; |
39 | }; | 43 | }; |
40 | }, | 44 | }, |
41 | }); | 45 | }); |
src/layouts/default/content/index.less
0 → 100644
1 | +@import (reference) '../../../design/index.less'; | ||
2 | + | ||
3 | +.layout-content { | ||
4 | + position: relative; | ||
5 | + flex: 1 1 auto; | ||
6 | + min-height: 0; | ||
7 | + | ||
8 | + &.fixed { | ||
9 | + width: 1200px; | ||
10 | + margin: 0 auto; | ||
11 | + } | ||
12 | + | ||
13 | + &__loading { | ||
14 | + position: fixed; | ||
15 | + z-index: @page-loading-z-index; | ||
16 | + | ||
17 | + > .basic-loading { | ||
18 | + margin-bottom: 20%; | ||
19 | + } | ||
20 | + } | ||
21 | +} |
src/layouts/default/content/index.tsx
0 → 100644
1 | +import './index.less'; | ||
2 | + | ||
3 | +import { defineComponent, unref } from 'vue'; | ||
4 | +import { FullLoading } from '/@/components/Loading/index'; | ||
5 | + | ||
6 | +import { RouterView } from 'vue-router'; | ||
7 | + | ||
8 | +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; | ||
9 | + | ||
10 | +export default defineComponent({ | ||
11 | + name: 'LayoutContent', | ||
12 | + setup() { | ||
13 | + const { getOpenPageLoading, getLayoutContentMode, getPageLoading } = useRootSetting(); | ||
14 | + | ||
15 | + return () => { | ||
16 | + return ( | ||
17 | + <div class={['layout-content', unref(getLayoutContentMode)]}> | ||
18 | + {unref(getOpenPageLoading) && ( | ||
19 | + <FullLoading class={[`layout-content__loading`, { hidden: !unref(getPageLoading) }]} /> | ||
20 | + )} | ||
21 | + <RouterView /> | ||
22 | + </div> | ||
23 | + ); | ||
24 | + }; | ||
25 | + }, | ||
26 | +}); |
src/layouts/default/footer/index.less
0 → 100644
1 | +@normal-color: rgba(0, 0, 0, 0.45); | ||
2 | + | ||
3 | +@hover-color: rgba(0, 0, 0, 0.85); | ||
4 | + | ||
5 | +.layout-footer { | ||
6 | + color: @normal-color; | ||
7 | + text-align: center; | ||
8 | + | ||
9 | + &__links { | ||
10 | + margin-bottom: 8px; | ||
11 | + | ||
12 | + a { | ||
13 | + color: @normal-color; | ||
14 | + | ||
15 | + &:hover { | ||
16 | + color: @hover-color; | ||
17 | + } | ||
18 | + } | ||
19 | + | ||
20 | + .github { | ||
21 | + margin: 0 30px; | ||
22 | + | ||
23 | + &:hover { | ||
24 | + color: @hover-color; | ||
25 | + } | ||
26 | + } | ||
27 | + } | ||
28 | +} |
src/layouts/default/footer/index.tsx
0 → 100644
1 | +import './index.less'; | ||
2 | + | ||
3 | +import { defineComponent } from 'vue'; | ||
4 | +import { Layout } from 'ant-design-vue'; | ||
5 | + | ||
6 | +import { GithubFilled } from '@ant-design/icons-vue'; | ||
7 | + | ||
8 | +import { DOC_URL, GITHUB_URL, SITE_URL } from '/@/settings/siteSetting'; | ||
9 | +import { openWindow } from '/@/utils'; | ||
10 | + | ||
11 | +export default defineComponent({ | ||
12 | + name: 'LayoutContent', | ||
13 | + setup() { | ||
14 | + return () => { | ||
15 | + return ( | ||
16 | + <Layout.Footer class="layout-footer"> | ||
17 | + {() => ( | ||
18 | + <> | ||
19 | + <div class="layout-footer__links"> | ||
20 | + <a onClick={() => openWindow(SITE_URL)}>在线预览</a> | ||
21 | + <GithubFilled onClick={() => openWindow(GITHUB_URL)} class="github" /> | ||
22 | + <a onClick={() => openWindow(DOC_URL)}>在线文档</a> | ||
23 | + </div> | ||
24 | + <div>Copyright ©2020 Vben Admin</div> | ||
25 | + </> | ||
26 | + )} | ||
27 | + </Layout.Footer> | ||
28 | + ); | ||
29 | + }; | ||
30 | + }, | ||
31 | +}); |
src/layouts/default/header/LayoutHeader.tsx
1 | import './index.less'; | 1 | import './index.less'; |
2 | 2 | ||
3 | +import type { FunctionalComponent } from 'vue'; | ||
4 | + | ||
3 | import { defineComponent, unref, computed, ref, nextTick } from 'vue'; | 5 | import { defineComponent, unref, computed, ref, nextTick } from 'vue'; |
4 | 6 | ||
5 | import { Layout, Tooltip, Badge } from 'ant-design-vue'; | 7 | import { Layout, Tooltip, Badge } from 'ant-design-vue'; |
6 | import { AppLogo } from '/@/components/Application'; | 8 | import { AppLogo } from '/@/components/Application'; |
7 | import UserDropdown from './UserDropdown'; | 9 | import UserDropdown from './UserDropdown'; |
8 | -import LayoutMenu from '/@/layouts/default/menu/LayoutMenu'; | 10 | +import LayoutMenu from '../menu'; |
9 | import LayoutBreadcrumb from './LayoutBreadcrumb'; | 11 | import LayoutBreadcrumb from './LayoutBreadcrumb'; |
10 | -import LockAction from './LockActionItem'; | 12 | +import LockAction from '../lock/LockAction'; |
11 | import LayoutTrigger from '../LayoutTrigger'; | 13 | import LayoutTrigger from '../LayoutTrigger'; |
12 | import NoticeAction from './notice/NoticeActionItem.vue'; | 14 | import NoticeAction from './notice/NoticeActionItem.vue'; |
13 | import { | 15 | import { |
@@ -34,9 +36,30 @@ import { PageEnum } from '/@/enums/pageEnum'; | @@ -34,9 +36,30 @@ import { PageEnum } from '/@/enums/pageEnum'; | ||
34 | import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; | 36 | import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; |
35 | import { Component } from '/@/components/types'; | 37 | import { Component } from '/@/components/types'; |
36 | 38 | ||
39 | +interface TooltipItemProps { | ||
40 | + title: string; | ||
41 | +} | ||
42 | + | ||
43 | +const TooltipItem: FunctionalComponent<TooltipItemProps> = (props, { slots }) => { | ||
44 | + return ( | ||
45 | + <Tooltip> | ||
46 | + {{ | ||
47 | + title: () => props.title, | ||
48 | + default: () => slots.default?.(), | ||
49 | + }} | ||
50 | + </Tooltip> | ||
51 | + ); | ||
52 | +}; | ||
53 | + | ||
37 | export default defineComponent({ | 54 | export default defineComponent({ |
38 | name: 'LayoutHeader', | 55 | name: 'LayoutHeader', |
39 | - setup() { | 56 | + props: { |
57 | + fixed: { | ||
58 | + type: Boolean, | ||
59 | + default: false, | ||
60 | + }, | ||
61 | + }, | ||
62 | + setup(props) { | ||
40 | let logoEl: Element | null; | 63 | let logoEl: Element | null; |
41 | 64 | ||
42 | const logoWidthRef = ref(200); | 65 | const logoWidthRef = ref(200); |
@@ -48,7 +71,7 @@ export default defineComponent({ | @@ -48,7 +71,7 @@ export default defineComponent({ | ||
48 | const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting(); | 71 | const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting(); |
49 | 72 | ||
50 | const { | 73 | const { |
51 | - getTheme, | 74 | + getHeaderTheme, |
52 | getShowRedo, | 75 | getShowRedo, |
53 | getUseLockPage, | 76 | getUseLockPage, |
54 | getShowFullScreen, | 77 | getShowFullScreen, |
@@ -69,8 +92,7 @@ export default defineComponent({ | @@ -69,8 +92,7 @@ export default defineComponent({ | ||
69 | let width = 0; | 92 | let width = 0; |
70 | if (!logoEl) { | 93 | if (!logoEl) { |
71 | logoEl = logoRef.value.$el; | 94 | logoEl = logoRef.value.$el; |
72 | - } | ||
73 | - if (logoEl) { | 95 | + } else { |
74 | width += logoEl.clientWidth; | 96 | width += logoEl.clientWidth; |
75 | } | 97 | } |
76 | logoWidthRef.value = width + 80; | 98 | logoWidthRef.value = width + 80; |
@@ -81,7 +103,7 @@ export default defineComponent({ | @@ -81,7 +103,7 @@ export default defineComponent({ | ||
81 | ); | 103 | ); |
82 | 104 | ||
83 | const headerClass = computed(() => { | 105 | const headerClass = computed(() => { |
84 | - const theme = unref(getTheme); | 106 | + const theme = unref(getHeaderTheme); |
85 | return theme ? `layout-header__header--${theme}` : ''; | 107 | return theme ? `layout-header__header--${theme}` : ''; |
86 | }); | 108 | }); |
87 | 109 | ||
@@ -99,9 +121,6 @@ export default defineComponent({ | @@ -99,9 +121,6 @@ export default defineComponent({ | ||
99 | }); | 121 | }); |
100 | } | 122 | } |
101 | 123 | ||
102 | - /** | ||
103 | - * @description: 锁定屏幕 | ||
104 | - */ | ||
105 | function handleLockPage() { | 124 | function handleLockPage() { |
106 | openModal(true); | 125 | openModal(true); |
107 | } | 126 | } |
@@ -111,13 +130,13 @@ export default defineComponent({ | @@ -111,13 +130,13 @@ export default defineComponent({ | ||
111 | return ( | 130 | return ( |
112 | <div class="layout-header__content "> | 131 | <div class="layout-header__content "> |
113 | {unref(getShowHeaderLogo) && ( | 132 | {unref(getShowHeaderLogo) && ( |
114 | - <AppLogo class={`layout-header__logo`} ref={logoRef} theme={unref(getTheme)} /> | 133 | + <AppLogo class={`layout-header__logo`} ref={logoRef} theme={unref(getHeaderTheme)} /> |
115 | )} | 134 | )} |
116 | 135 | ||
117 | {unref(getShowContent) && ( | 136 | {unref(getShowContent) && ( |
118 | <div class="layout-header__left"> | 137 | <div class="layout-header__left"> |
119 | {unref(getShowHeaderTrigger) && ( | 138 | {unref(getShowHeaderTrigger) && ( |
120 | - <LayoutTrigger theme={unref(getTheme)} sider={false} /> | 139 | + <LayoutTrigger theme={unref(getHeaderTheme)} sider={false} /> |
121 | )} | 140 | )} |
122 | {unref(getShowBread) && <LayoutBreadcrumb showIcon={unref(getShowBreadCrumbIcon)} />} | 141 | {unref(getShowBread) && <LayoutBreadcrumb showIcon={unref(getShowBreadCrumbIcon)} />} |
123 | </div> | 142 | </div> |
@@ -128,7 +147,7 @@ export default defineComponent({ | @@ -128,7 +147,7 @@ export default defineComponent({ | ||
128 | <LayoutMenu | 147 | <LayoutMenu |
129 | isHorizontal={true} | 148 | isHorizontal={true} |
130 | class={`justify-${unref(getTopMenuAlign)}`} | 149 | class={`justify-${unref(getTopMenuAlign)}`} |
131 | - theme={unref(getTheme)} | 150 | + theme={unref(getHeaderTheme)} |
132 | splitType={unref(getSplitType)} | 151 | splitType={unref(getSplitType)} |
133 | menuMode={unref(getMenuMode)} | 152 | menuMode={unref(getMenuMode)} |
134 | showSearch={false} | 153 | showSearch={false} |
@@ -151,64 +170,47 @@ export default defineComponent({ | @@ -151,64 +170,47 @@ export default defineComponent({ | ||
151 | return ( | 170 | return ( |
152 | <div class={`layout-header__action`}> | 171 | <div class={`layout-header__action`}> |
153 | {unref(getUseErrorHandle) && ( | 172 | {unref(getUseErrorHandle) && ( |
154 | - <Tooltip> | ||
155 | - {{ | ||
156 | - title: () => '错误日志', | ||
157 | - default: () => ( | ||
158 | - <Badge | ||
159 | - count={errorStore.getErrorListCountState} | ||
160 | - offset={[0, 10]} | ||
161 | - dot | ||
162 | - overflowCount={99} | ||
163 | - > | ||
164 | - {() => renderActionDefault(BugOutlined, handleToErrorList)} | ||
165 | - </Badge> | ||
166 | - ), | ||
167 | - }} | ||
168 | - </Tooltip> | 173 | + <TooltipItem title="错误日志"> |
174 | + {() => ( | ||
175 | + <Badge | ||
176 | + count={errorStore.getErrorListCountState} | ||
177 | + offset={[0, 10]} | ||
178 | + dot | ||
179 | + overflowCount={99} | ||
180 | + > | ||
181 | + {() => renderActionDefault(BugOutlined, handleToErrorList)} | ||
182 | + </Badge> | ||
183 | + )} | ||
184 | + </TooltipItem> | ||
169 | )} | 185 | )} |
170 | 186 | ||
171 | {unref(getUseLockPage) && ( | 187 | {unref(getUseLockPage) && ( |
172 | - <Tooltip> | ||
173 | - {{ | ||
174 | - title: () => '锁定屏幕', | ||
175 | - default: () => renderActionDefault(LockOutlined, handleLockPage), | ||
176 | - }} | ||
177 | - </Tooltip> | 188 | + <TooltipItem title="锁定屏幕"> |
189 | + {() => renderActionDefault(LockOutlined, handleLockPage)} | ||
190 | + </TooltipItem> | ||
178 | )} | 191 | )} |
179 | 192 | ||
180 | {unref(getShowNotice) && ( | 193 | {unref(getShowNotice) && ( |
181 | - <Tooltip> | ||
182 | - {{ | ||
183 | - title: () => '消息通知', | ||
184 | - default: () => <NoticeAction />, | ||
185 | - }} | ||
186 | - </Tooltip> | 194 | + <TooltipItem title="消息通知">{() => <NoticeAction />}</TooltipItem> |
187 | )} | 195 | )} |
188 | 196 | ||
189 | {unref(getShowRedo) && ( | 197 | {unref(getShowRedo) && ( |
190 | - <Tooltip> | ||
191 | - {{ | ||
192 | - title: () => '刷新', | ||
193 | - default: () => renderActionDefault(RedoOutlined, refreshPage), | ||
194 | - }} | ||
195 | - </Tooltip> | 198 | + <TooltipItem title="刷新"> |
199 | + {() => renderActionDefault(RedoOutlined, refreshPage)} | ||
200 | + </TooltipItem> | ||
196 | )} | 201 | )} |
197 | 202 | ||
198 | {unref(getShowFullScreen) && ( | 203 | {unref(getShowFullScreen) && ( |
199 | - <Tooltip> | ||
200 | - {{ | ||
201 | - title: () => (unref(isFullscreenRef) ? '退出全屏' : '全屏'), | ||
202 | - default: () => { | ||
203 | - const Icon = !unref(isFullscreenRef) ? ( | ||
204 | - <FullscreenOutlined /> | ||
205 | - ) : ( | ||
206 | - <FullscreenExitOutlined /> | ||
207 | - ); | ||
208 | - return renderActionDefault(Icon, toggleFullscreen); | ||
209 | - }, | 204 | + <TooltipItem title={unref(isFullscreenRef) ? '退出全屏' : '全屏'}> |
205 | + {() => { | ||
206 | + const Icon = !unref(isFullscreenRef) ? ( | ||
207 | + <FullscreenOutlined /> | ||
208 | + ) : ( | ||
209 | + <FullscreenExitOutlined /> | ||
210 | + ); | ||
211 | + return renderActionDefault(Icon, toggleFullscreen); | ||
210 | }} | 212 | }} |
211 | - </Tooltip> | 213 | + </TooltipItem> |
212 | )} | 214 | )} |
213 | <UserDropdown class={`layout-header__user-dropdown`} /> | 215 | <UserDropdown class={`layout-header__user-dropdown`} /> |
214 | </div> | 216 | </div> |
@@ -227,7 +229,9 @@ export default defineComponent({ | @@ -227,7 +229,9 @@ export default defineComponent({ | ||
227 | 229 | ||
228 | return () => { | 230 | return () => { |
229 | return ( | 231 | return ( |
230 | - <Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}> | 232 | + <Layout.Header |
233 | + class={['layout-header', 'flex p-0 px-4 ', unref(headerClass), { fixed: props.fixed }]} | ||
234 | + > | ||
231 | {() => renderHeaderDefault()} | 235 | {() => renderHeaderDefault()} |
232 | </Layout.Header> | 236 | </Layout.Header> |
233 | ); | 237 | ); |
src/layouts/default/header/LayoutMultipleHeader.less
0 → 100644
src/layouts/default/header/LayoutMultipleHeader.tsx
0 → 100644
1 | +import './LayoutMultipleHeader.less'; | ||
2 | + | ||
3 | +import { defineComponent, unref, computed, ref, watch, nextTick, CSSProperties } from 'vue'; | ||
4 | + | ||
5 | +import LayoutHeader from './LayoutHeader'; | ||
6 | +import MultipleTabs from '../multitabs/index'; | ||
7 | + | ||
8 | +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; | ||
9 | +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | ||
10 | +import { useFullContent } from '/@/hooks/web/useFullContent'; | ||
11 | +import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | ||
12 | +import { useLayoutContext } from '../useLayoutContext'; | ||
13 | + | ||
14 | +export default defineComponent({ | ||
15 | + name: 'LayoutMultipleHeader', | ||
16 | + setup() { | ||
17 | + const placeholderHeightRef = ref(0); | ||
18 | + const fullHeaderHeightRef = ref(0); | ||
19 | + const headerElRef = ref<ComponentRef>(null); | ||
20 | + const tabElRef = ref<ComponentRef>(null); | ||
21 | + | ||
22 | + const injectValue = useLayoutContext(); | ||
23 | + | ||
24 | + const { getCalcContentWidth } = useMenuSetting(); | ||
25 | + | ||
26 | + const { | ||
27 | + getFixed, | ||
28 | + getShowInsetHeaderRef, | ||
29 | + getShowFullHeaderRef, | ||
30 | + getShowHeader, | ||
31 | + getUnFixedAndFull, | ||
32 | + } = useHeaderSetting(); | ||
33 | + | ||
34 | + const { getFullContent } = useFullContent(); | ||
35 | + | ||
36 | + const { getShowMultipleTab } = useMultipleTabSetting(); | ||
37 | + | ||
38 | + const showTabsRef = computed(() => { | ||
39 | + return unref(getShowMultipleTab) && !unref(getFullContent); | ||
40 | + }); | ||
41 | + | ||
42 | + const getPlaceholderDomStyle = computed(() => { | ||
43 | + return { | ||
44 | + height: `${unref(placeholderHeightRef)}px`, | ||
45 | + }; | ||
46 | + }); | ||
47 | + | ||
48 | + const getIsShowPlaceholderDom = computed(() => { | ||
49 | + return unref(getFixed) || unref(getShowFullHeaderRef); | ||
50 | + }); | ||
51 | + | ||
52 | + const getWrapStyle = computed(() => { | ||
53 | + const style: CSSProperties = {}; | ||
54 | + if (unref(getFixed)) { | ||
55 | + style.width = unref(getCalcContentWidth); | ||
56 | + } | ||
57 | + if (unref(getShowFullHeaderRef)) { | ||
58 | + style.top = `${unref(fullHeaderHeightRef)}px`; | ||
59 | + } | ||
60 | + return style; | ||
61 | + }); | ||
62 | + | ||
63 | + const getIsFixed = computed(() => { | ||
64 | + return unref(getFixed) || unref(getShowFullHeaderRef); | ||
65 | + }); | ||
66 | + | ||
67 | + watch( | ||
68 | + () => [ | ||
69 | + unref(getFixed), | ||
70 | + unref(getShowFullHeaderRef), | ||
71 | + unref(getShowHeader), | ||
72 | + unref(getShowMultipleTab), | ||
73 | + ], | ||
74 | + () => { | ||
75 | + if (unref(getUnFixedAndFull)) return; | ||
76 | + nextTick(() => { | ||
77 | + const headerEl = unref(headerElRef)?.$el; | ||
78 | + const tabEl = unref(tabElRef)?.$el; | ||
79 | + const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el; | ||
80 | + | ||
81 | + let height = 0; | ||
82 | + if (headerEl && !unref(getShowFullHeaderRef)) { | ||
83 | + height += headerEl.offsetHeight; | ||
84 | + } | ||
85 | + | ||
86 | + if (tabEl) { | ||
87 | + height += tabEl.offsetHeight; | ||
88 | + } | ||
89 | + | ||
90 | + if (fullHeaderEl && unref(getShowFullHeaderRef)) { | ||
91 | + const fullHeaderHeight = fullHeaderEl.offsetHeight; | ||
92 | + height += fullHeaderHeight; | ||
93 | + fullHeaderHeightRef.value = fullHeaderHeight; | ||
94 | + } | ||
95 | + placeholderHeightRef.value = height; | ||
96 | + }); | ||
97 | + }, | ||
98 | + { | ||
99 | + immediate: true, | ||
100 | + } | ||
101 | + ); | ||
102 | + | ||
103 | + return () => { | ||
104 | + return ( | ||
105 | + <> | ||
106 | + {unref(getIsShowPlaceholderDom) && <div style={unref(getPlaceholderDomStyle)} />} | ||
107 | + <div | ||
108 | + style={unref(getWrapStyle)} | ||
109 | + class={['multiple-tab-header', { fixed: unref(getIsFixed) }]} | ||
110 | + > | ||
111 | + {unref(getShowInsetHeaderRef) && <LayoutHeader ref={headerElRef} />} | ||
112 | + {unref(showTabsRef) && <MultipleTabs ref={tabElRef} />} | ||
113 | + </div> | ||
114 | + </> | ||
115 | + ); | ||
116 | + }; | ||
117 | + }, | ||
118 | +}); |
src/layouts/default/header/UserDropdown.tsx
@@ -15,15 +15,31 @@ import { DOC_URL } from '/@/settings/siteSetting'; | @@ -15,15 +15,31 @@ import { DOC_URL } from '/@/settings/siteSetting'; | ||
15 | import { openWindow } from '/@/utils'; | 15 | import { openWindow } from '/@/utils'; |
16 | 16 | ||
17 | import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; | 17 | import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; |
18 | +import { FunctionalComponent } from 'vue'; | ||
18 | 19 | ||
19 | -interface RenderItemParams { | 20 | +type MenuEvent = 'loginOut' | 'doc'; |
21 | +interface MenuItemProps { | ||
20 | icon: string; | 22 | icon: string; |
21 | text: string; | 23 | text: string; |
22 | - key: string; | 24 | + key: MenuEvent; |
23 | } | 25 | } |
24 | 26 | ||
25 | const prefixCls = 'user-dropdown'; | 27 | const prefixCls = 'user-dropdown'; |
26 | 28 | ||
29 | +const MenuItem: FunctionalComponent<MenuItemProps> = (props) => { | ||
30 | + const { key, icon, text } = props; | ||
31 | + return ( | ||
32 | + <Menu.Item key={key}> | ||
33 | + {() => ( | ||
34 | + <span class="flex items-center"> | ||
35 | + <Icon icon={icon} class="mr-1" /> | ||
36 | + <span>{text}</span> | ||
37 | + </span> | ||
38 | + )} | ||
39 | + </Menu.Item> | ||
40 | + ); | ||
41 | +}; | ||
42 | + | ||
27 | export default defineComponent({ | 43 | export default defineComponent({ |
28 | name: 'UserDropdown', | 44 | name: 'UserDropdown', |
29 | setup() { | 45 | setup() { |
@@ -44,27 +60,17 @@ export default defineComponent({ | @@ -44,27 +60,17 @@ export default defineComponent({ | ||
44 | openWindow(DOC_URL); | 60 | openWindow(DOC_URL); |
45 | } | 61 | } |
46 | 62 | ||
47 | - function handleMenuClick(e: any) { | ||
48 | - if (e.key === 'loginOut') { | ||
49 | - handleLoginOut(); | ||
50 | - } else if (e.key === 'doc') { | ||
51 | - openDoc(); | 63 | + function handleMenuClick(e: { key: MenuEvent }) { |
64 | + switch (e.key) { | ||
65 | + case 'loginOut': | ||
66 | + handleLoginOut(); | ||
67 | + break; | ||
68 | + case 'doc': | ||
69 | + openDoc(); | ||
70 | + break; | ||
52 | } | 71 | } |
53 | } | 72 | } |
54 | 73 | ||
55 | - function renderItem({ icon, text, key }: RenderItemParams) { | ||
56 | - return ( | ||
57 | - <Menu.Item key={key}> | ||
58 | - {() => ( | ||
59 | - <span class="flex items-center"> | ||
60 | - <Icon icon={icon} class="mr-1" /> | ||
61 | - <span>{text}</span> | ||
62 | - </span> | ||
63 | - )} | ||
64 | - </Menu.Item> | ||
65 | - ); | ||
66 | - } | ||
67 | - | ||
68 | function renderSlotsDefault() { | 74 | function renderSlotsDefault() { |
69 | const { realName } = unref(getUserInfo); | 75 | const { realName } = unref(getUserInfo); |
70 | return ( | 76 | return ( |
@@ -83,13 +89,9 @@ export default defineComponent({ | @@ -83,13 +89,9 @@ export default defineComponent({ | ||
83 | <Menu onClick={handleMenuClick}> | 89 | <Menu onClick={handleMenuClick}> |
84 | {() => ( | 90 | {() => ( |
85 | <> | 91 | <> |
86 | - {showDoc && renderItem({ key: 'doc', text: '文档', icon: 'gg:loadbar-doc' })} | 92 | + {showDoc && <MenuItem key="doc" text="文档" icon="gg:loadbar-doc" />} |
87 | {showDoc && <Divider />} | 93 | {showDoc && <Divider />} |
88 | - {renderItem({ | ||
89 | - key: 'loginOut', | ||
90 | - text: '退出系统', | ||
91 | - icon: 'ant-design:poweroff-outlined', | ||
92 | - })} | 94 | + <MenuItem key="loginOut" text="退出系统" icon="ant-design:poweroff-outlined" /> |
93 | </> | 95 | </> |
94 | )} | 96 | )} |
95 | </Menu> | 97 | </Menu> |
src/layouts/default/header/index.less
@@ -10,13 +10,21 @@ | @@ -10,13 +10,21 @@ | ||
10 | align-items: center; | 10 | align-items: center; |
11 | justify-content: space-between; | 11 | justify-content: space-between; |
12 | 12 | ||
13 | + &.fixed { | ||
14 | + position: fixed; | ||
15 | + top: 0; | ||
16 | + left: 0; | ||
17 | + z-index: 1000; | ||
18 | + width: 100%; | ||
19 | + } | ||
20 | + | ||
13 | &__left { | 21 | &__left { |
14 | display: flex; | 22 | display: flex; |
15 | // flex-grow: 1; | 23 | // flex-grow: 1; |
16 | align-items: center; | 24 | align-items: center; |
17 | 25 | ||
18 | .layout-trigger { | 26 | .layout-trigger { |
19 | - padding: 4px 10px 0 16px; | 27 | + padding: 1px 10px 0 16px; |
20 | cursor: pointer; | 28 | cursor: pointer; |
21 | 29 | ||
22 | .anticon { | 30 | .anticon { |
@@ -150,6 +158,7 @@ | @@ -150,6 +158,7 @@ | ||
150 | } | 158 | } |
151 | 159 | ||
152 | &__inner, | 160 | &__inner, |
161 | + &__inner.is-link, | ||
153 | &__separator { | 162 | &__separator { |
154 | color: @white; | 163 | color: @white; |
155 | } | 164 | } |
src/layouts/default/index.less
1 | @import (reference) '../../design/index.less'; | 1 | @import (reference) '../../design/index.less'; |
2 | 2 | ||
3 | .default-layout { | 3 | .default-layout { |
4 | - &__content { | ||
5 | - position: relative; | 4 | + display: flex; |
5 | + flex-direction: column; | ||
6 | + width: 100%; | ||
7 | + min-height: 100%; | ||
6 | 8 | ||
7 | - &.fixed { | ||
8 | - overflow: hidden; | ||
9 | - } | ||
10 | - } | ||
11 | - | ||
12 | - &__loading { | ||
13 | - position: absolute; | ||
14 | - z-index: @page-loading-z-index; | ||
15 | - } | ||
16 | - | ||
17 | - &__main { | ||
18 | - position: relative; | ||
19 | - height: 100%; | ||
20 | - | ||
21 | - &.fixed { | ||
22 | - overflow-x: hidden; | ||
23 | - overflow-y: auto; | ||
24 | - } | ||
25 | - | ||
26 | - &.fixed.lock { | ||
27 | - overflow: hidden; | ||
28 | - } | ||
29 | - } | ||
30 | - | ||
31 | - .layout-content { | ||
32 | - position: relative; | ||
33 | - | ||
34 | - &.fixed { | ||
35 | - width: 1200px; | ||
36 | - margin: 0 auto; | ||
37 | - } | 9 | + > .ant-layout { |
10 | + min-height: 100%; | ||
38 | } | 11 | } |
39 | } | 12 | } |
src/layouts/default/index.tsx
1 | -import { defineComponent, unref, computed } from 'vue'; | 1 | +import './index.less'; |
2 | + | ||
3 | +import { defineComponent, unref, computed, ref } from 'vue'; | ||
2 | import { Layout, BackTop } from 'ant-design-vue'; | 4 | import { Layout, BackTop } from 'ant-design-vue'; |
3 | import LayoutHeader from './header/LayoutHeader'; | 5 | import LayoutHeader from './header/LayoutHeader'; |
4 | 6 | ||
5 | -import { appStore } from '/@/store/modules/app'; | ||
6 | -import LayoutContent from './LayoutContent'; | ||
7 | -import LayoutSideBar from './sider/LayoutSideBar'; | 7 | +import LayoutContent from './content'; |
8 | +import LayoutFooter from './footer'; | ||
9 | +import LayoutLockPage from './lock'; | ||
10 | +import LayoutSideBar from './sider'; | ||
8 | import SettingBtn from './setting/index.vue'; | 11 | import SettingBtn from './setting/index.vue'; |
9 | -import MultipleTabs from './multitabs/index'; | 12 | +import LayoutMultipleHeader from './header/LayoutMultipleHeader'; |
10 | 13 | ||
11 | -import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; | 14 | +import { MenuModeEnum } from '/@/enums/menuEnum'; |
15 | + | ||
16 | +import { useRouter } from 'vue-router'; | ||
12 | import { useFullContent } from '/@/hooks/web/useFullContent'; | 17 | import { useFullContent } from '/@/hooks/web/useFullContent'; |
18 | +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; | ||
19 | +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | ||
20 | +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; | ||
21 | +import { createLayoutContext } from './useLayoutContext'; | ||
13 | 22 | ||
14 | -import LockPage from '/@/views/sys/lock/index.vue'; | ||
15 | import { registerGlobComp } from '/@/components/registerGlobComp'; | 23 | import { registerGlobComp } from '/@/components/registerGlobComp'; |
16 | 24 | ||
17 | -import './index.less'; | ||
18 | export default defineComponent({ | 25 | export default defineComponent({ |
19 | name: 'DefaultLayout', | 26 | name: 'DefaultLayout', |
20 | setup() { | 27 | setup() { |
28 | + const { currentRoute } = useRouter(); | ||
29 | + const headerRef = ref<ComponentRef>(null); | ||
30 | + | ||
31 | + createLayoutContext({ fullHeaderRef: headerRef }); | ||
32 | + | ||
21 | // ! Only register global components here | 33 | // ! Only register global components here |
22 | // ! Can reduce the size of the first screen code | 34 | // ! Can reduce the size of the first screen code |
23 | // default layout It is loaded after login. So it won’t be packaged to the first screen | 35 | // default layout It is loaded after login. So it won’t be packaged to the first screen |
24 | registerGlobComp(); | 36 | registerGlobComp(); |
25 | 37 | ||
26 | - const { getFullContent } = useFullContent(); | ||
27 | - | ||
28 | - const getProjectConfigRef = computed(() => appStore.getProjectConfig); | 38 | + const { getShowFullHeaderRef } = useHeaderSetting(); |
29 | 39 | ||
30 | - const getLockMainScrollStateRef = computed(() => appStore.getLockMainScrollState); | 40 | + const { getUseOpenBackTop, getShowSettingButton, getShowFooter } = useRootSetting(); |
31 | 41 | ||
32 | - const showHeaderRef = computed(() => { | ||
33 | - const { | ||
34 | - headerSetting: { show }, | ||
35 | - } = unref(getProjectConfigRef); | ||
36 | - return show; | ||
37 | - }); | 42 | + const { getShowMenu, getMenuMode, getSplit } = useMenuSetting(); |
38 | 43 | ||
39 | - const showMixHeaderRef = computed(() => { | ||
40 | - const { | ||
41 | - menuSetting: { type }, | ||
42 | - } = unref(getProjectConfigRef); | ||
43 | - return type !== MenuTypeEnum.SIDEBAR && unref(showHeaderRef); | ||
44 | - }); | 44 | + const { getFullContent } = useFullContent(); |
45 | 45 | ||
46 | - const getIsLockRef = computed(() => { | ||
47 | - const { getLockInfo } = appStore; | ||
48 | - const { isLock } = getLockInfo; | ||
49 | - return isLock; | 46 | + const getShowLayoutFooter = computed(() => { |
47 | + return unref(getShowFooter) && !unref(currentRoute).meta?.hiddenFooter; | ||
50 | }); | 48 | }); |
51 | 49 | ||
52 | const showSideBarRef = computed(() => { | 50 | const showSideBarRef = computed(() => { |
53 | - const { | ||
54 | - menuSetting: { show, mode, split }, | ||
55 | - } = unref(getProjectConfigRef); | ||
56 | - return split || (show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent)); | ||
57 | - }); | ||
58 | - | ||
59 | - const showFullHeaderRef = computed(() => { | ||
60 | - return !unref(getFullContent) && unref(showMixHeaderRef) && unref(showHeaderRef); | ||
61 | - }); | ||
62 | - | ||
63 | - const showInsetHeaderRef = computed(() => { | ||
64 | - return !unref(getFullContent) && !unref(showMixHeaderRef) && unref(showHeaderRef); | ||
65 | - }); | ||
66 | - | ||
67 | - const fixedHeaderClsRef = computed(() => { | ||
68 | - const { | ||
69 | - headerSetting: { fixed }, | ||
70 | - } = unref(getProjectConfigRef); | ||
71 | - const fixedHeaderCls = fixed | ||
72 | - ? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '') | ||
73 | - : ''; | ||
74 | - return fixedHeaderCls; | ||
75 | - }); | ||
76 | - | ||
77 | - const showTabsRef = computed(() => { | ||
78 | - const { | ||
79 | - multiTabsSetting: { show }, | ||
80 | - } = unref(getProjectConfigRef); | ||
81 | - return show && !unref(getFullContent); | ||
82 | - }); | ||
83 | - | ||
84 | - const showClassSideBarRef = computed(() => { | ||
85 | - const { | ||
86 | - menuSetting: { split, hidden }, | ||
87 | - } = unref(getProjectConfigRef); | ||
88 | - return split ? hidden : true; | 51 | + return ( |
52 | + unref(getSplit) || | ||
53 | + (unref(getShowMenu) && | ||
54 | + unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && | ||
55 | + !unref(getFullContent)) | ||
56 | + ); | ||
89 | }); | 57 | }); |
90 | 58 | ||
91 | - function getTarget(): any { | ||
92 | - const { | ||
93 | - headerSetting: { fixed }, | ||
94 | - } = unref(getProjectConfigRef); | ||
95 | - return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`); | 59 | + function renderFeatures() { |
60 | + return ( | ||
61 | + <> | ||
62 | + <LayoutLockPage /> | ||
63 | + {/* back top */} | ||
64 | + {unref(getUseOpenBackTop) && <BackTop target={() => document.body} />} | ||
65 | + {/* open setting drawer */} | ||
66 | + {unref(getShowSettingButton) && <SettingBtn />} | ||
67 | + </> | ||
68 | + ); | ||
96 | } | 69 | } |
97 | 70 | ||
98 | return () => { | 71 | return () => { |
99 | - const { useOpenBackTop, showSettingButton } = unref(getProjectConfigRef); | ||
100 | return ( | 72 | return ( |
101 | - <Layout class="default-layout relative"> | 73 | + <Layout class="default-layout"> |
102 | {() => ( | 74 | {() => ( |
103 | <> | 75 | <> |
104 | - {/* lock page */} | ||
105 | - {unref(getIsLockRef) && <LockPage />} | ||
106 | - {/* back top */} | ||
107 | - {useOpenBackTop && <BackTop target={getTarget} />} | ||
108 | - {/* open setting drawer */} | ||
109 | - {showSettingButton && <SettingBtn />} | 76 | + {renderFeatures()} |
110 | 77 | ||
111 | - {unref(showFullHeaderRef) && <LayoutHeader />} | 78 | + {unref(getShowFullHeaderRef) && <LayoutHeader fixed={true} ref={headerRef} />} |
112 | 79 | ||
113 | <Layout> | 80 | <Layout> |
114 | {() => ( | 81 | {() => ( |
115 | <> | 82 | <> |
116 | - {unref(showSideBarRef) && ( | ||
117 | - <LayoutSideBar class={unref(showClassSideBarRef) ? '' : 'hidden'} /> | ||
118 | - )} | ||
119 | - <Layout class={[`default-layout__content`, unref(fixedHeaderClsRef)]}> | 83 | + {unref(showSideBarRef) && <LayoutSideBar />} |
84 | + <Layout> | ||
120 | {() => ( | 85 | {() => ( |
121 | <> | 86 | <> |
122 | - {unref(showInsetHeaderRef) && <LayoutHeader />} | ||
123 | - | ||
124 | - {unref(showTabsRef) && <MultipleTabs />} | ||
125 | - | ||
126 | - <LayoutContent class={unref(fixedHeaderClsRef)} /> | 87 | + <LayoutMultipleHeader /> |
88 | + <LayoutContent /> | ||
89 | + {unref(getShowLayoutFooter) && <LayoutFooter />} | ||
127 | </> | 90 | </> |
128 | )} | 91 | )} |
129 | </Layout> | 92 | </Layout> |
src/layouts/default/header/LockActionItem.less renamed to src/layouts/default/lock/LockAction.less
src/layouts/default/header/LockActionItem.tsx renamed to src/layouts/default/lock/LockAction.tsx
src/layouts/default/lock/index.tsx
0 → 100644
1 | +import { defineComponent, unref, computed } from 'vue'; | ||
2 | +import { appStore } from '/@/store/modules/app'; | ||
3 | +import LockPage from '/@/views/sys/lock/index.vue'; | ||
4 | + | ||
5 | +export default defineComponent({ | ||
6 | + name: 'LayoutLockPage', | ||
7 | + setup() { | ||
8 | + const getIsLockRef = computed(() => { | ||
9 | + const { getLockInfo } = appStore; | ||
10 | + const { isLock } = getLockInfo; | ||
11 | + return isLock; | ||
12 | + }); | ||
13 | + return () => { | ||
14 | + return unref(getIsLockRef) ? <LockPage /> : null; | ||
15 | + }; | ||
16 | + }, | ||
17 | +}); |
src/layouts/default/menu/LayoutMenu.tsx renamed to src/layouts/default/menu/index.tsx
@@ -17,7 +17,7 @@ import { useSplitMenu } from './useLayoutMenu'; | @@ -17,7 +17,7 @@ import { useSplitMenu } from './useLayoutMenu'; | ||
17 | import { openWindow } from '/@/utils'; | 17 | import { openWindow } from '/@/utils'; |
18 | 18 | ||
19 | export default defineComponent({ | 19 | export default defineComponent({ |
20 | - name: 'DefaultLayoutMenu', | 20 | + name: 'LayoutMenu', |
21 | props: { | 21 | props: { |
22 | theme: { | 22 | theme: { |
23 | type: String as PropType<string>, | 23 | type: String as PropType<string>, |
@@ -50,12 +50,12 @@ export default defineComponent({ | @@ -50,12 +50,12 @@ export default defineComponent({ | ||
50 | const { | 50 | const { |
51 | setMenuSetting, | 51 | setMenuSetting, |
52 | getShowSearch, | 52 | getShowSearch, |
53 | - getMode, | ||
54 | - getType, | 53 | + getMenuMode, |
54 | + getMenuType, | ||
55 | getCollapsedShowTitle, | 55 | getCollapsedShowTitle, |
56 | getCollapsedShowSearch, | 56 | getCollapsedShowSearch, |
57 | getIsSidebarType, | 57 | getIsSidebarType, |
58 | - getTheme, | 58 | + getMenuTheme, |
59 | getCollapsed, | 59 | getCollapsed, |
60 | getAccordion, | 60 | getAccordion, |
61 | } = useMenuSetting(); | 61 | } = useMenuSetting(); |
@@ -66,9 +66,9 @@ export default defineComponent({ | @@ -66,9 +66,9 @@ export default defineComponent({ | ||
66 | 66 | ||
67 | const showLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType)); | 67 | const showLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType)); |
68 | 68 | ||
69 | - const getMenuMode = computed(() => props.menuMode || unref(getMode)); | 69 | + const getComputedMenuMode = computed(() => props.menuMode || unref(getMenuMode)); |
70 | 70 | ||
71 | - const getMenuTheme = computed(() => props.theme || unref(getTheme)); | 71 | + const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme)); |
72 | 72 | ||
73 | const appendClass = computed(() => props.splitType === MenuSplitTyeEnum.TOP); | 73 | const appendClass = computed(() => props.splitType === MenuSplitTyeEnum.TOP); |
74 | 74 | ||
@@ -111,8 +111,8 @@ export default defineComponent({ | @@ -111,8 +111,8 @@ export default defineComponent({ | ||
111 | return ( | 111 | return ( |
112 | <AppLogo | 112 | <AppLogo |
113 | showTitle={!unref(getCollapsed)} | 113 | showTitle={!unref(getCollapsed)} |
114 | - class={[`layout-menu__logo`, unref(getMenuTheme)]} | ||
115 | - theme={unref(getMenuTheme)} | 114 | + class={[`layout-menu__logo`, unref(getComputedMenuTheme)]} |
115 | + theme={unref(getComputedMenuTheme)} | ||
116 | /> | 116 | /> |
117 | ); | 117 | ); |
118 | } | 118 | } |
@@ -124,10 +124,10 @@ export default defineComponent({ | @@ -124,10 +124,10 @@ export default defineComponent({ | ||
124 | beforeClickFn={beforeMenuClickFn} | 124 | beforeClickFn={beforeMenuClickFn} |
125 | isHorizontal={props.isHorizontal} | 125 | isHorizontal={props.isHorizontal} |
126 | appendClass={unref(appendClass)} | 126 | appendClass={unref(appendClass)} |
127 | - type={unref(getType)} | ||
128 | - mode={unref(getMenuMode)} | 127 | + type={unref(getMenuType)} |
128 | + mode={unref(getComputedMenuMode)} | ||
129 | collapsedShowTitle={unref(getCollapsedShowTitle)} | 129 | collapsedShowTitle={unref(getCollapsedShowTitle)} |
130 | - theme={unref(getMenuTheme)} | 130 | + theme={unref(getComputedMenuTheme)} |
131 | showLogo={unref(showLogo)} | 131 | showLogo={unref(showLogo)} |
132 | search={unref(showSearch)} | 132 | search={unref(showSearch)} |
133 | items={unref(menusRef)} | 133 | items={unref(menusRef)} |
src/layouts/default/multitabs/TabContent.tsx
@@ -6,7 +6,6 @@ import { TabItem, tabStore } from '/@/store/modules/tab'; | @@ -6,7 +6,6 @@ import { TabItem, tabStore } from '/@/store/modules/tab'; | ||
6 | import { getScaleAction, TabContentProps } from './tab.data'; | 6 | import { getScaleAction, TabContentProps } from './tab.data'; |
7 | 7 | ||
8 | import { Dropdown } from '/@/components/Dropdown/index'; | 8 | import { Dropdown } from '/@/components/Dropdown/index'; |
9 | -import Icon from '/@/components/Icon/index'; | ||
10 | import { RightOutlined } from '@ant-design/icons-vue'; | 9 | import { RightOutlined } from '@ant-design/icons-vue'; |
11 | import { appStore } from '/@/store/modules/app'; | 10 | import { appStore } from '/@/store/modules/app'; |
12 | 11 | ||
@@ -57,18 +56,11 @@ export default defineComponent({ | @@ -57,18 +56,11 @@ export default defineComponent({ | ||
57 | /** | 56 | /** |
58 | * @description: 渲染图标 | 57 | * @description: 渲染图标 |
59 | */ | 58 | */ |
60 | - function renderIcon() { | ||
61 | - const { tabItem } = props; | ||
62 | - if (!tabItem) return; | ||
63 | - const icon = tabItem.meta && tabItem.meta.icon; | ||
64 | - if (!icon || !unref(getProjectConfigRef).multiTabsSetting.showIcon) return null; | ||
65 | - return <Icon icon={icon} class="align-middle " style={{ marginBottom: '2px' }} />; | ||
66 | - } | 59 | + |
67 | function renderTabContent() { | 60 | function renderTabContent() { |
68 | const { tabItem: { meta } = {} } = props; | 61 | const { tabItem: { meta } = {} } = props; |
69 | return ( | 62 | return ( |
70 | <div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}> | 63 | <div class={`multiple-tabs-content__content `} onContextmenu={handleContextMenu}> |
71 | - {renderIcon()} | ||
72 | <span class="ml-1">{meta && meta.title}</span> | 64 | <span class="ml-1">{meta && meta.title}</span> |
73 | </div> | 65 | </div> |
74 | ); | 66 | ); |
src/layouts/default/setting/SettingDrawer.tsx
1 | -import { defineComponent, computed, unref, ref } from 'vue'; | 1 | +import type { ProjectConfig } from '/@/types/config'; |
2 | + | ||
3 | +import defaultSetting from '/@/settings/projectSetting'; | ||
4 | + | ||
5 | +import { defineComponent, computed, unref, FunctionalComponent } from 'vue'; | ||
2 | import { BasicDrawer } from '/@/components/Drawer/index'; | 6 | import { BasicDrawer } from '/@/components/Drawer/index'; |
3 | import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue'; | 7 | import { Divider, Switch, Tooltip, InputNumber, Select } from 'ant-design-vue'; |
4 | import Button from '/@/components/Button/index.vue'; | 8 | import Button from '/@/components/Button/index.vue'; |
5 | -import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; | ||
6 | import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue'; | 9 | import { CopyOutlined, RedoOutlined, CheckOutlined } from '@ant-design/icons-vue'; |
10 | + | ||
11 | +import { MenuTypeEnum } from '/@/enums/menuEnum'; | ||
7 | import { appStore } from '/@/store/modules/app'; | 12 | import { appStore } from '/@/store/modules/app'; |
8 | -import { ProjectConfig } from '/@/types/config'; | ||
9 | 13 | ||
10 | import { useMessage } from '/@/hooks/web/useMessage'; | 14 | import { useMessage } from '/@/hooks/web/useMessage'; |
11 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; | 15 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
16 | +import { useRootSetting } from '/@/hooks/setting/useRootSetting'; | ||
17 | +import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | ||
18 | +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; | ||
19 | +import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | ||
12 | 20 | ||
13 | -import defaultSetting from '/@/settings/projectSetting'; | ||
14 | - | ||
15 | -import mixImg from '/@/assets/images/layout/menu-mix.svg'; | ||
16 | -import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg'; | ||
17 | -import menuTopImg from '/@/assets/images/layout/menu-top.svg'; | ||
18 | import { updateColorWeak, updateGrayMode } from '/@/setup/theme'; | 21 | import { updateColorWeak, updateGrayMode } from '/@/setup/theme'; |
22 | + | ||
19 | import { baseHandler } from './handler'; | 23 | import { baseHandler } from './handler'; |
24 | + | ||
20 | import { | 25 | import { |
21 | HandlerEnum, | 26 | HandlerEnum, |
22 | contentModeOptions, | 27 | contentModeOptions, |
23 | topMenuAlignOptions, | 28 | topMenuAlignOptions, |
24 | menuTriggerOptions, | 29 | menuTriggerOptions, |
25 | routerTransitionOptions, | 30 | routerTransitionOptions, |
26 | -} from './const'; | 31 | + menuTypeList, |
32 | +} from './enum'; | ||
33 | + | ||
27 | import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting'; | 34 | import { HEADER_PRESET_BG_COLOR_LIST, SIDE_BAR_BG_COLOR_LIST } from '/@/settings/colorSetting'; |
28 | 35 | ||
29 | interface SwitchOptions { | 36 | interface SwitchOptions { |
@@ -40,215 +47,280 @@ interface SelectConfig { | @@ -40,215 +47,280 @@ interface SelectConfig { | ||
40 | handler?: Fn; | 47 | handler?: Fn; |
41 | } | 48 | } |
42 | 49 | ||
43 | -interface ThemeOptions { | ||
44 | - def?: string; | ||
45 | - handler?: Fn; | 50 | +interface ThemePickerProps { |
51 | + colorList: string[]; | ||
52 | + handler: Fn; | ||
53 | + def: string; | ||
46 | } | 54 | } |
47 | 55 | ||
56 | +const { createSuccessModal, createMessage } = useMessage(); | ||
57 | + | ||
58 | +/** | ||
59 | + * Menu type Picker comp | ||
60 | + */ | ||
61 | +const MenuTypePicker: FunctionalComponent = () => { | ||
62 | + const { getIsHorizontal, getMenuType } = useMenuSetting(); | ||
63 | + return ( | ||
64 | + <div class={`setting-drawer__siderbar`}> | ||
65 | + {menuTypeList.map((item) => { | ||
66 | + const { title, type: ItemType, mode, src } = item; | ||
67 | + return ( | ||
68 | + <Tooltip title={title} placement="bottom" key={title}> | ||
69 | + {{ | ||
70 | + default: () => ( | ||
71 | + <div | ||
72 | + onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, { | ||
73 | + mode: mode, | ||
74 | + type: ItemType, | ||
75 | + split: unref(getIsHorizontal) ? false : undefined, | ||
76 | + })} | ||
77 | + > | ||
78 | + <CheckOutlined | ||
79 | + class={['check-icon', unref(getMenuType) === ItemType ? 'active' : '']} | ||
80 | + /> | ||
81 | + <img src={src} /> | ||
82 | + </div> | ||
83 | + ), | ||
84 | + }} | ||
85 | + </Tooltip> | ||
86 | + ); | ||
87 | + })} | ||
88 | + </div> | ||
89 | + ); | ||
90 | +}; | ||
91 | + | ||
92 | +const ThemePicker: FunctionalComponent<ThemePickerProps> = (props) => { | ||
93 | + return ( | ||
94 | + <div class={`setting-drawer__theme-item`}> | ||
95 | + {props.colorList.map((color) => { | ||
96 | + return ( | ||
97 | + <span | ||
98 | + onClick={() => props.handler?.(color)} | ||
99 | + key={color} | ||
100 | + class={[props.def === color ? 'active' : '']} | ||
101 | + style={{ | ||
102 | + background: color, | ||
103 | + }} | ||
104 | + > | ||
105 | + <CheckOutlined class="icon" /> | ||
106 | + </span> | ||
107 | + ); | ||
108 | + })} | ||
109 | + </div> | ||
110 | + ); | ||
111 | +}; | ||
112 | + | ||
113 | +/** | ||
114 | + * FooterButton component | ||
115 | + */ | ||
116 | +const FooterButton: FunctionalComponent = () => { | ||
117 | + const { getRootSetting } = useRootSetting(); | ||
118 | + function handleCopy() { | ||
119 | + const { isSuccessRef } = useCopyToClipboard(JSON.stringify(unref(getRootSetting), null, 2)); | ||
120 | + unref(isSuccessRef) && | ||
121 | + createSuccessModal({ | ||
122 | + title: '操作成功', | ||
123 | + content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!', | ||
124 | + }); | ||
125 | + } | ||
126 | + function handleResetSetting() { | ||
127 | + try { | ||
128 | + appStore.commitProjectConfigState(defaultSetting); | ||
129 | + const { colorWeak, grayMode } = defaultSetting; | ||
130 | + // updateTheme(themeColor); | ||
131 | + updateColorWeak(colorWeak); | ||
132 | + updateGrayMode(grayMode); | ||
133 | + createMessage.success('重置成功!'); | ||
134 | + } catch (error) { | ||
135 | + createMessage.error(error); | ||
136 | + } | ||
137 | + } | ||
138 | + | ||
139 | + function handleClearAndRedo() { | ||
140 | + localStorage.clear(); | ||
141 | + appStore.resumeAllState(); | ||
142 | + location.reload(); | ||
143 | + } | ||
144 | + | ||
145 | + return ( | ||
146 | + <div class="setting-drawer__footer"> | ||
147 | + <Button type="primary" block onClick={handleCopy}> | ||
148 | + {() => ( | ||
149 | + <> | ||
150 | + <CopyOutlined class="mr-2" /> | ||
151 | + 拷贝 | ||
152 | + </> | ||
153 | + )} | ||
154 | + </Button> | ||
155 | + <Button block class="mt-2" onClick={handleResetSetting} color="warning"> | ||
156 | + {() => ( | ||
157 | + <> | ||
158 | + <RedoOutlined class="mr-2" /> | ||
159 | + 重置 | ||
160 | + </> | ||
161 | + )} | ||
162 | + </Button> | ||
163 | + <Button block class="mt-2" onClick={handleClearAndRedo} color="error"> | ||
164 | + {() => ( | ||
165 | + <> | ||
166 | + <RedoOutlined class="mr-2" /> | ||
167 | + 清空缓存并返回登录页 | ||
168 | + </> | ||
169 | + )} | ||
170 | + </Button> | ||
171 | + </div> | ||
172 | + ); | ||
173 | +}; | ||
174 | + | ||
48 | export default defineComponent({ | 175 | export default defineComponent({ |
49 | name: 'SettingDrawer', | 176 | name: 'SettingDrawer', |
50 | setup(_, { attrs }) { | 177 | setup(_, { attrs }) { |
51 | - const { createSuccessModal, createMessage } = useMessage(); | 178 | + const { |
179 | + getContentMode, | ||
180 | + getRouterTransition, | ||
181 | + getOpenRouterTransition, | ||
182 | + getOpenPageLoading, | ||
183 | + getShowFooter, | ||
184 | + getShowBreadCrumb, | ||
185 | + getShowBreadCrumbIcon, | ||
186 | + getShowLogo, | ||
187 | + getFullContent, | ||
188 | + getColorWeak, | ||
189 | + getGrayMode, | ||
190 | + } = useRootSetting(); | ||
52 | 191 | ||
53 | - const getProjectConfigRef = computed(() => { | ||
54 | - return appStore.getProjectConfig; | ||
55 | - }); | 192 | + const { |
193 | + getIsHorizontal, | ||
194 | + getShowMenu, | ||
195 | + getMenuType, | ||
196 | + getTrigger, | ||
197 | + getCollapsedShowTitle, | ||
198 | + getMenuFixed, | ||
199 | + getCollapsed, | ||
200 | + getShowSearch, | ||
201 | + getHasDrag, | ||
202 | + getTopMenuAlign, | ||
203 | + getAccordion, | ||
204 | + getMenuWidth, | ||
205 | + getMenuBgColor, | ||
206 | + getIsTopMenu, | ||
207 | + getSplit, | ||
208 | + } = useMenuSetting(); | ||
56 | 209 | ||
57 | - const getIsHorizontalRef = computed(() => { | ||
58 | - return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL; | ||
59 | - }); | 210 | + const { getShowHeader, getFixed: getHeaderFixed, getHeaderBgColor } = useHeaderSetting(); |
60 | 211 | ||
61 | - const getShowHeaderRef = computed(() => { | ||
62 | - return unref(getProjectConfigRef).headerSetting.show; | ||
63 | - }); | 212 | + const { getShowMultipleTab, getShowQuick } = useMultipleTabSetting(); |
64 | 213 | ||
65 | const getShowMenuRef = computed(() => { | 214 | const getShowMenuRef = computed(() => { |
66 | - return unref(getProjectConfigRef).menuSetting.show && !unref(getIsHorizontalRef); | 215 | + return unref(getShowMenu) && !unref(getIsHorizontal); |
67 | }); | 216 | }); |
68 | 217 | ||
69 | - const getShowTabsRef = computed(() => { | ||
70 | - return unref(getProjectConfigRef).multiTabsSetting.show; | ||
71 | - }); | ||
72 | - | ||
73 | - function handleCopy() { | ||
74 | - const { isSuccessRef } = useCopyToClipboard( | ||
75 | - JSON.stringify(unref(getProjectConfigRef), null, 2) | 218 | + function renderSidebar() { |
219 | + return ( | ||
220 | + <> | ||
221 | + <MenuTypePicker /> | ||
222 | + {renderSwitchItem('分割菜单', { | ||
223 | + handler: (e) => { | ||
224 | + baseHandler(HandlerEnum.MENU_SPLIT, e); | ||
225 | + }, | ||
226 | + def: unref(getSplit), | ||
227 | + disabled: !unref(getShowMenuRef) || unref(getMenuType) !== MenuTypeEnum.MIX, | ||
228 | + })} | ||
229 | + </> | ||
76 | ); | 230 | ); |
77 | - unref(isSuccessRef) && | ||
78 | - createSuccessModal({ | ||
79 | - title: '操作成功', | ||
80 | - content: '复制成功,请到 src/settings/projectSetting.ts 中修改配置!', | ||
81 | - }); | ||
82 | } | 231 | } |
83 | 232 | ||
84 | - function handleResetSetting() { | ||
85 | - try { | ||
86 | - appStore.commitProjectConfigState(defaultSetting); | ||
87 | - const { colorWeak, grayMode } = defaultSetting; | ||
88 | - // updateTheme(themeColor); | ||
89 | - updateColorWeak(colorWeak); | ||
90 | - updateGrayMode(grayMode); | ||
91 | - createMessage.success('重置成功!'); | ||
92 | - } catch (error) { | ||
93 | - createMessage.error(error); | ||
94 | - } | ||
95 | - } | ||
96 | - | ||
97 | - function handleClearAndRedo() { | ||
98 | - localStorage.clear(); | ||
99 | - appStore.resumeAllState(); | ||
100 | - location.reload(); | 233 | + function renderTheme() { |
234 | + return ( | ||
235 | + <> | ||
236 | + <Divider>{() => '顶栏主题'}</Divider> | ||
237 | + <ThemePicker | ||
238 | + colorList={HEADER_PRESET_BG_COLOR_LIST} | ||
239 | + def={unref(getHeaderBgColor)} | ||
240 | + handler={(e) => { | ||
241 | + baseHandler(HandlerEnum.HEADER_THEME, e); | ||
242 | + }} | ||
243 | + /> | ||
244 | + <Divider>{() => '菜单主题'}</Divider> | ||
245 | + <ThemePicker | ||
246 | + colorList={SIDE_BAR_BG_COLOR_LIST} | ||
247 | + def={unref(getMenuBgColor)} | ||
248 | + handler={(e) => { | ||
249 | + baseHandler(HandlerEnum.MENU_THEME, e); | ||
250 | + }} | ||
251 | + /> | ||
252 | + </> | ||
253 | + ); | ||
101 | } | 254 | } |
102 | 255 | ||
103 | - function renderSidebar() { | ||
104 | - const { | ||
105 | - menuSetting: { type, split }, | ||
106 | - } = unref(getProjectConfigRef); | ||
107 | - | ||
108 | - const typeList = ref([ | ||
109 | - { | ||
110 | - title: '左侧菜单模式', | ||
111 | - mode: MenuModeEnum.INLINE, | ||
112 | - type: MenuTypeEnum.SIDEBAR, | ||
113 | - src: sidebarImg, | ||
114 | - }, | ||
115 | - { | ||
116 | - title: '混合模式', | ||
117 | - mode: MenuModeEnum.INLINE, | ||
118 | - type: MenuTypeEnum.MIX, | ||
119 | - src: mixImg, | ||
120 | - }, | ||
121 | - | ||
122 | - { | ||
123 | - title: '顶部菜单模式', | ||
124 | - mode: MenuModeEnum.HORIZONTAL, | ||
125 | - type: MenuTypeEnum.TOP_MENU, | ||
126 | - src: menuTopImg, | ||
127 | - }, | ||
128 | - ]); | ||
129 | - return [ | ||
130 | - <div class={`setting-drawer__siderbar`}> | ||
131 | - {unref(typeList).map((item) => { | ||
132 | - const { title, type: ItemType, mode, src } = item; | ||
133 | - return ( | ||
134 | - <Tooltip title={title} placement="bottom" key={title}> | ||
135 | - {{ | ||
136 | - default: () => ( | ||
137 | - <div | ||
138 | - onClick={baseHandler.bind(null, HandlerEnum.CHANGE_LAYOUT, { | ||
139 | - mode: mode, | ||
140 | - type: ItemType, | ||
141 | - split: unref(getIsHorizontalRef) ? false : undefined, | ||
142 | - })} | ||
143 | - > | ||
144 | - <CheckOutlined class={['check-icon', type === ItemType ? 'active' : '']} /> | ||
145 | - <img src={src} /> | ||
146 | - </div> | ||
147 | - ), | ||
148 | - }} | ||
149 | - </Tooltip> | ||
150 | - ); | ||
151 | - })} | ||
152 | - </div>, | ||
153 | - renderSwitchItem('分割菜单', { | ||
154 | - handler: (e) => { | ||
155 | - baseHandler(HandlerEnum.MENU_SPLIT, e); | ||
156 | - }, | ||
157 | - def: split, | ||
158 | - disabled: !unref(getShowMenuRef) || type !== MenuTypeEnum.MIX, | ||
159 | - }), | ||
160 | - // renderSelectItem('顶栏主题', { | ||
161 | - // handler: (e) => { | ||
162 | - // baseHandler(HandlerEnum.HEADER_THEME, e); | ||
163 | - // }, | ||
164 | - // def: headerTheme, | ||
165 | - // options: themeOptions, | ||
166 | - // disabled: !unref(getShowHeaderRef), | ||
167 | - // }), | ||
168 | - // renderSelectItem('菜单主题', { | ||
169 | - // handler: (e) => { | ||
170 | - // baseHandler(HandlerEnum.MENU_THEME, e); | ||
171 | - // }, | ||
172 | - // def: menuTheme, | ||
173 | - // options: themeOptions, | ||
174 | - // disabled: !unref(getShowMenuRef), | ||
175 | - // }), | ||
176 | - ]; | ||
177 | - } | ||
178 | /** | 256 | /** |
179 | * @description: | 257 | * @description: |
180 | */ | 258 | */ |
181 | function renderFeatures() { | 259 | function renderFeatures() { |
182 | - const { | ||
183 | - contentMode, | ||
184 | - headerSetting: { fixed }, | ||
185 | - menuSetting: { | ||
186 | - hasDrag, | ||
187 | - collapsed, | ||
188 | - showSearch, | ||
189 | - menuWidth, | ||
190 | - topMenuAlign, | ||
191 | - collapsedShowTitle, | ||
192 | - trigger, | ||
193 | - accordion, | ||
194 | - } = {}, | ||
195 | - } = appStore.getProjectConfig; | ||
196 | return [ | 260 | return [ |
197 | renderSwitchItem('侧边菜单拖拽', { | 261 | renderSwitchItem('侧边菜单拖拽', { |
198 | handler: (e) => { | 262 | handler: (e) => { |
199 | baseHandler(HandlerEnum.MENU_HAS_DRAG, e); | 263 | baseHandler(HandlerEnum.MENU_HAS_DRAG, e); |
200 | }, | 264 | }, |
201 | - def: hasDrag, | 265 | + def: unref(getHasDrag), |
202 | disabled: !unref(getShowMenuRef), | 266 | disabled: !unref(getShowMenuRef), |
203 | }), | 267 | }), |
204 | renderSwitchItem('侧边菜单搜索', { | 268 | renderSwitchItem('侧边菜单搜索', { |
205 | handler: (e) => { | 269 | handler: (e) => { |
206 | baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e); | 270 | baseHandler(HandlerEnum.MENU_SHOW_SEARCH, e); |
207 | }, | 271 | }, |
208 | - def: showSearch, | 272 | + def: unref(getShowSearch), |
209 | disabled: !unref(getShowMenuRef), | 273 | disabled: !unref(getShowMenuRef), |
210 | }), | 274 | }), |
211 | renderSwitchItem('侧边菜单手风琴模式', { | 275 | renderSwitchItem('侧边菜单手风琴模式', { |
212 | handler: (e) => { | 276 | handler: (e) => { |
213 | baseHandler(HandlerEnum.MENU_ACCORDION, e); | 277 | baseHandler(HandlerEnum.MENU_ACCORDION, e); |
214 | }, | 278 | }, |
215 | - def: accordion, | 279 | + def: unref(getAccordion), |
216 | disabled: !unref(getShowMenuRef), | 280 | disabled: !unref(getShowMenuRef), |
217 | }), | 281 | }), |
218 | renderSwitchItem('折叠菜单', { | 282 | renderSwitchItem('折叠菜单', { |
219 | handler: (e) => { | 283 | handler: (e) => { |
220 | baseHandler(HandlerEnum.MENU_COLLAPSED, e); | 284 | baseHandler(HandlerEnum.MENU_COLLAPSED, e); |
221 | }, | 285 | }, |
222 | - def: collapsed, | 286 | + def: unref(getCollapsed), |
223 | disabled: !unref(getShowMenuRef), | 287 | disabled: !unref(getShowMenuRef), |
224 | }), | 288 | }), |
225 | renderSwitchItem('折叠菜单显示名称', { | 289 | renderSwitchItem('折叠菜单显示名称', { |
226 | handler: (e) => { | 290 | handler: (e) => { |
227 | baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e); | 291 | baseHandler(HandlerEnum.MENU_COLLAPSED_SHOW_TITLE, e); |
228 | }, | 292 | }, |
229 | - def: collapsedShowTitle, | ||
230 | - disabled: !unref(getShowMenuRef) || !collapsed, | 293 | + def: unref(getCollapsedShowTitle), |
294 | + disabled: !unref(getShowMenuRef) || !unref(getCollapsed), | ||
231 | }), | 295 | }), |
232 | renderSwitchItem('固定header', { | 296 | renderSwitchItem('固定header', { |
233 | handler: (e) => { | 297 | handler: (e) => { |
234 | baseHandler(HandlerEnum.HEADER_FIXED, e); | 298 | baseHandler(HandlerEnum.HEADER_FIXED, e); |
235 | }, | 299 | }, |
236 | - def: fixed, | ||
237 | - disabled: !unref(getShowHeaderRef), | 300 | + def: unref(getHeaderFixed), |
301 | + disabled: !unref(getShowHeader), | ||
302 | + }), | ||
303 | + renderSwitchItem('固定Siderbar', { | ||
304 | + handler: (e) => { | ||
305 | + baseHandler(HandlerEnum.MENU_FIXED, e); | ||
306 | + }, | ||
307 | + def: unref(getMenuFixed), | ||
308 | + disabled: !unref(getShowMenuRef), | ||
238 | }), | 309 | }), |
239 | renderSelectItem('顶部菜单布局', { | 310 | renderSelectItem('顶部菜单布局', { |
240 | handler: (e) => { | 311 | handler: (e) => { |
241 | baseHandler(HandlerEnum.MENU_TOP_ALIGN, e); | 312 | baseHandler(HandlerEnum.MENU_TOP_ALIGN, e); |
242 | }, | 313 | }, |
243 | - def: topMenuAlign, | 314 | + def: unref(getTopMenuAlign), |
244 | options: topMenuAlignOptions, | 315 | options: topMenuAlignOptions, |
245 | - disabled: !unref(getShowHeaderRef), | 316 | + disabled: !unref(getShowHeader) || (!unref(getIsTopMenu) && !unref(getSplit)), |
246 | }), | 317 | }), |
247 | renderSelectItem('菜单折叠按钮', { | 318 | renderSelectItem('菜单折叠按钮', { |
248 | handler: (e) => { | 319 | handler: (e) => { |
249 | baseHandler(HandlerEnum.MENU_TRIGGER, e); | 320 | baseHandler(HandlerEnum.MENU_TRIGGER, e); |
250 | }, | 321 | }, |
251 | - def: trigger, | 322 | + disabled: !unref(getShowMenuRef), |
323 | + def: unref(getTrigger), | ||
252 | options: menuTriggerOptions, | 324 | options: menuTriggerOptions, |
253 | }), | 325 | }), |
254 | 326 | ||
@@ -256,7 +328,7 @@ export default defineComponent({ | @@ -256,7 +328,7 @@ export default defineComponent({ | ||
256 | handler: (e) => { | 328 | handler: (e) => { |
257 | baseHandler(HandlerEnum.CONTENT_MODE, e); | 329 | baseHandler(HandlerEnum.CONTENT_MODE, e); |
258 | }, | 330 | }, |
259 | - def: contentMode, | 331 | + def: unref(getContentMode), |
260 | options: contentModeOptions, | 332 | options: contentModeOptions, |
261 | }), | 333 | }), |
262 | <div class={`setting-drawer__cell-item`}> | 334 | <div class={`setting-drawer__cell-item`}> |
@@ -286,7 +358,7 @@ export default defineComponent({ | @@ -286,7 +358,7 @@ export default defineComponent({ | ||
286 | min={100} | 358 | min={100} |
287 | step={10} | 359 | step={10} |
288 | disabled={!unref(getShowMenuRef)} | 360 | disabled={!unref(getShowMenuRef)} |
289 | - defaultValue={menuWidth} | 361 | + defaultValue={unref(getMenuWidth)} |
290 | formatter={(value: string) => `${parseInt(value)}px`} | 362 | formatter={(value: string) => `${parseInt(value)}px`} |
291 | onChange={(e: any) => { | 363 | onChange={(e: any) => { |
292 | baseHandler(HandlerEnum.MENU_WIDTH, e); | 364 | baseHandler(HandlerEnum.MENU_WIDTH, e); |
@@ -295,121 +367,112 @@ export default defineComponent({ | @@ -295,121 +367,112 @@ export default defineComponent({ | ||
295 | </div>, | 367 | </div>, |
296 | ]; | 368 | ]; |
297 | } | 369 | } |
298 | - function renderTransition() { | ||
299 | - const { routerTransition, openRouterTransition, openPageLoading } = appStore.getProjectConfig; | ||
300 | 370 | ||
301 | - return ( | ||
302 | - <> | ||
303 | - {renderSwitchItem('页面切换loading', { | ||
304 | - handler: (e) => { | ||
305 | - baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e); | ||
306 | - }, | ||
307 | - def: openPageLoading, | ||
308 | - })} | ||
309 | - {renderSwitchItem('切换动画', { | ||
310 | - handler: (e) => { | ||
311 | - baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e); | ||
312 | - }, | ||
313 | - def: openRouterTransition, | ||
314 | - })} | ||
315 | - {renderSelectItem('路由动画', { | ||
316 | - handler: (e) => { | ||
317 | - baseHandler(HandlerEnum.ROUTER_TRANSITION, e); | ||
318 | - }, | ||
319 | - def: routerTransition, | ||
320 | - options: routerTransitionOptions, | ||
321 | - disabled: !openRouterTransition, | ||
322 | - })} | ||
323 | - </> | ||
324 | - ); | ||
325 | - } | ||
326 | function renderContent() { | 371 | function renderContent() { |
327 | - const { | ||
328 | - grayMode, | ||
329 | - colorWeak, | ||
330 | - fullContent, | ||
331 | - showLogo, | ||
332 | - headerSetting: { show: showHeader }, | ||
333 | - menuSetting: { show: showMenu }, | ||
334 | - multiTabsSetting: { show: showMultiple, showQuick, showIcon: showTabIcon }, | ||
335 | - showBreadCrumb, | ||
336 | - showBreadCrumbIcon, | ||
337 | - } = unref(getProjectConfigRef); | ||
338 | return [ | 372 | return [ |
339 | renderSwitchItem('面包屑', { | 373 | renderSwitchItem('面包屑', { |
340 | handler: (e) => { | 374 | handler: (e) => { |
341 | baseHandler(HandlerEnum.SHOW_BREADCRUMB, e); | 375 | baseHandler(HandlerEnum.SHOW_BREADCRUMB, e); |
342 | }, | 376 | }, |
343 | - def: showBreadCrumb, | ||
344 | - disabled: !unref(getShowHeaderRef), | 377 | + def: unref(getShowBreadCrumb), |
378 | + disabled: !unref(getShowHeader), | ||
345 | }), | 379 | }), |
346 | renderSwitchItem('面包屑图标', { | 380 | renderSwitchItem('面包屑图标', { |
347 | handler: (e) => { | 381 | handler: (e) => { |
348 | baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e); | 382 | baseHandler(HandlerEnum.SHOW_BREADCRUMB_ICON, e); |
349 | }, | 383 | }, |
350 | - def: showBreadCrumbIcon, | ||
351 | - disabled: !unref(getShowHeaderRef), | 384 | + def: unref(getShowBreadCrumbIcon), |
385 | + disabled: !unref(getShowHeader), | ||
352 | }), | 386 | }), |
353 | renderSwitchItem('标签页', { | 387 | renderSwitchItem('标签页', { |
354 | handler: (e) => { | 388 | handler: (e) => { |
355 | baseHandler(HandlerEnum.TABS_SHOW, e); | 389 | baseHandler(HandlerEnum.TABS_SHOW, e); |
356 | }, | 390 | }, |
357 | - def: showMultiple, | 391 | + def: unref(getShowMultipleTab), |
358 | }), | 392 | }), |
359 | renderSwitchItem('标签页快捷按钮', { | 393 | renderSwitchItem('标签页快捷按钮', { |
360 | handler: (e) => { | 394 | handler: (e) => { |
361 | baseHandler(HandlerEnum.TABS_SHOW_QUICK, e); | 395 | baseHandler(HandlerEnum.TABS_SHOW_QUICK, e); |
362 | }, | 396 | }, |
363 | - def: showQuick, | ||
364 | - disabled: !unref(getShowTabsRef), | ||
365 | - }), | ||
366 | - renderSwitchItem('标签页图标', { | ||
367 | - handler: (e) => { | ||
368 | - baseHandler(HandlerEnum.TABS_SHOW_ICON, e); | ||
369 | - }, | ||
370 | - def: showTabIcon, | ||
371 | - disabled: !unref(getShowTabsRef), | 397 | + def: unref(getShowQuick), |
398 | + disabled: !unref(getShowMultipleTab), | ||
372 | }), | 399 | }), |
400 | + | ||
373 | renderSwitchItem('左侧菜单', { | 401 | renderSwitchItem('左侧菜单', { |
374 | handler: (e) => { | 402 | handler: (e) => { |
375 | baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e); | 403 | baseHandler(HandlerEnum.MENU_SHOW_SIDEBAR, e); |
376 | }, | 404 | }, |
377 | - def: showMenu, | ||
378 | - disabled: unref(getIsHorizontalRef), | 405 | + def: unref(getShowMenu), |
406 | + disabled: unref(getIsHorizontal), | ||
379 | }), | 407 | }), |
380 | renderSwitchItem('顶栏', { | 408 | renderSwitchItem('顶栏', { |
381 | handler: (e) => { | 409 | handler: (e) => { |
382 | baseHandler(HandlerEnum.HEADER_SHOW, e); | 410 | baseHandler(HandlerEnum.HEADER_SHOW, e); |
383 | }, | 411 | }, |
384 | - def: showHeader, | 412 | + def: unref(getShowHeader), |
385 | }), | 413 | }), |
386 | renderSwitchItem('Logo', { | 414 | renderSwitchItem('Logo', { |
387 | handler: (e) => { | 415 | handler: (e) => { |
388 | baseHandler(HandlerEnum.SHOW_LOGO, e); | 416 | baseHandler(HandlerEnum.SHOW_LOGO, e); |
389 | }, | 417 | }, |
390 | - def: showLogo, | 418 | + def: unref(getShowLogo), |
419 | + }), | ||
420 | + renderSwitchItem('页脚', { | ||
421 | + handler: (e) => { | ||
422 | + baseHandler(HandlerEnum.SHOW_FOOTER, e); | ||
423 | + }, | ||
424 | + def: unref(getShowFooter), | ||
391 | }), | 425 | }), |
392 | renderSwitchItem('全屏内容', { | 426 | renderSwitchItem('全屏内容', { |
393 | handler: (e) => { | 427 | handler: (e) => { |
394 | baseHandler(HandlerEnum.FULL_CONTENT, e); | 428 | baseHandler(HandlerEnum.FULL_CONTENT, e); |
395 | }, | 429 | }, |
396 | - def: fullContent, | 430 | + def: unref(getFullContent), |
397 | }), | 431 | }), |
398 | renderSwitchItem('灰色模式', { | 432 | renderSwitchItem('灰色模式', { |
399 | handler: (e) => { | 433 | handler: (e) => { |
400 | baseHandler(HandlerEnum.GRAY_MODE, e); | 434 | baseHandler(HandlerEnum.GRAY_MODE, e); |
401 | }, | 435 | }, |
402 | - def: grayMode, | 436 | + def: unref(getGrayMode), |
403 | }), | 437 | }), |
404 | renderSwitchItem('色弱模式', { | 438 | renderSwitchItem('色弱模式', { |
405 | handler: (e) => { | 439 | handler: (e) => { |
406 | baseHandler(HandlerEnum.COLOR_WEAK, e); | 440 | baseHandler(HandlerEnum.COLOR_WEAK, e); |
407 | }, | 441 | }, |
408 | - def: colorWeak, | 442 | + def: unref(getColorWeak), |
409 | }), | 443 | }), |
410 | ]; | 444 | ]; |
411 | } | 445 | } |
412 | 446 | ||
447 | + function renderTransition() { | ||
448 | + return ( | ||
449 | + <> | ||
450 | + {renderSwitchItem('页面切换loading', { | ||
451 | + handler: (e) => { | ||
452 | + baseHandler(HandlerEnum.OPEN_PAGE_LOADING, e); | ||
453 | + }, | ||
454 | + def: unref(getOpenPageLoading), | ||
455 | + })} | ||
456 | + | ||
457 | + {renderSwitchItem('切换动画', { | ||
458 | + handler: (e) => { | ||
459 | + baseHandler(HandlerEnum.OPEN_ROUTE_TRANSITION, e); | ||
460 | + }, | ||
461 | + def: unref(getOpenRouterTransition), | ||
462 | + })} | ||
463 | + | ||
464 | + {renderSelectItem('路由动画', { | ||
465 | + handler: (e) => { | ||
466 | + baseHandler(HandlerEnum.ROUTER_TRANSITION, e); | ||
467 | + }, | ||
468 | + def: unref(getRouterTransition), | ||
469 | + options: routerTransitionOptions, | ||
470 | + disabled: !unref(getOpenRouterTransition), | ||
471 | + })} | ||
472 | + </> | ||
473 | + ); | ||
474 | + } | ||
475 | + | ||
413 | function renderSelectItem(text: string, config?: SelectConfig) { | 476 | function renderSelectItem(text: string, config?: SelectConfig) { |
414 | const { handler, def, disabled = false, options } = config || {}; | 477 | const { handler, def, disabled = false, options } = config || {}; |
415 | const opt = def ? { value: def, defaultValue: def } : {}; | 478 | const opt = def ? { value: def, defaultValue: def } : {}; |
@@ -449,50 +512,6 @@ export default defineComponent({ | @@ -449,50 +512,6 @@ export default defineComponent({ | ||
449 | ); | 512 | ); |
450 | } | 513 | } |
451 | 514 | ||
452 | - function renderTheme() { | ||
453 | - const { headerBgColor, menuBgColor } = unref(getProjectConfigRef); | ||
454 | - return ( | ||
455 | - <> | ||
456 | - <Divider>{() => '顶栏主题'}</Divider> | ||
457 | - {renderThemeItem(HEADER_PRESET_BG_COLOR_LIST, { | ||
458 | - def: headerBgColor, | ||
459 | - handler: (e) => { | ||
460 | - baseHandler(HandlerEnum.HEADER_THEME, e); | ||
461 | - }, | ||
462 | - })} | ||
463 | - <Divider>{() => '菜单主题'}</Divider> | ||
464 | - {renderThemeItem(SIDE_BAR_BG_COLOR_LIST, { | ||
465 | - def: menuBgColor, | ||
466 | - handler: (e) => { | ||
467 | - baseHandler(HandlerEnum.MENU_THEME, e); | ||
468 | - }, | ||
469 | - })} | ||
470 | - </> | ||
471 | - ); | ||
472 | - } | ||
473 | - | ||
474 | - function renderThemeItem(colorList: string[], opt: ThemeOptions) { | ||
475 | - const { def, handler } = opt; | ||
476 | - return ( | ||
477 | - <div class={`setting-drawer__theme-item`}> | ||
478 | - {colorList.map((item) => { | ||
479 | - return ( | ||
480 | - <span | ||
481 | - onClick={() => handler && handler(item)} | ||
482 | - key={item} | ||
483 | - class={[def === item ? 'active' : '']} | ||
484 | - style={{ | ||
485 | - background: item, | ||
486 | - }} | ||
487 | - > | ||
488 | - <CheckOutlined class="icon" /> | ||
489 | - </span> | ||
490 | - ); | ||
491 | - })} | ||
492 | - </div> | ||
493 | - ); | ||
494 | - } | ||
495 | - | ||
496 | return () => ( | 515 | return () => ( |
497 | <BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer"> | 516 | <BasicDrawer {...attrs} title="项目配置" width={300} wrapClassName="setting-drawer"> |
498 | {{ | 517 | {{ |
@@ -500,9 +519,7 @@ export default defineComponent({ | @@ -500,9 +519,7 @@ export default defineComponent({ | ||
500 | <> | 519 | <> |
501 | <Divider>{() => '导航栏模式'}</Divider> | 520 | <Divider>{() => '导航栏模式'}</Divider> |
502 | {renderSidebar()} | 521 | {renderSidebar()} |
503 | - | ||
504 | {renderTheme()} | 522 | {renderTheme()} |
505 | - | ||
506 | <Divider>{() => '界面功能'}</Divider> | 523 | <Divider>{() => '界面功能'}</Divider> |
507 | {renderFeatures()} | 524 | {renderFeatures()} |
508 | <Divider>{() => '界面显示'}</Divider> | 525 | <Divider>{() => '界面显示'}</Divider> |
@@ -510,32 +527,7 @@ export default defineComponent({ | @@ -510,32 +527,7 @@ export default defineComponent({ | ||
510 | <Divider>{() => '切换动画'}</Divider> | 527 | <Divider>{() => '切换动画'}</Divider> |
511 | {renderTransition()} | 528 | {renderTransition()} |
512 | <Divider /> | 529 | <Divider /> |
513 | - <div class="setting-drawer__footer"> | ||
514 | - <Button type="primary" block onClick={handleCopy}> | ||
515 | - {() => ( | ||
516 | - <> | ||
517 | - <CopyOutlined class="mr-2" /> | ||
518 | - 拷贝 | ||
519 | - </> | ||
520 | - )} | ||
521 | - </Button> | ||
522 | - <Button block class="mt-2" onClick={handleResetSetting} color="warning"> | ||
523 | - {() => ( | ||
524 | - <> | ||
525 | - <RedoOutlined class="mr-2" /> | ||
526 | - 重置 | ||
527 | - </> | ||
528 | - )} | ||
529 | - </Button> | ||
530 | - <Button block class="mt-2" onClick={handleClearAndRedo} color="error"> | ||
531 | - {() => ( | ||
532 | - <> | ||
533 | - <RedoOutlined class="mr-2" /> | ||
534 | - 清空缓存并返回登录页 | ||
535 | - </> | ||
536 | - )} | ||
537 | - </Button> | ||
538 | - </div> | 530 | + <FooterButton /> |
539 | </> | 531 | </> |
540 | ), | 532 | ), |
541 | }} | 533 | }} |
src/layouts/default/setting/const.ts renamed to src/layouts/default/setting/enum.ts
1 | import { ContentEnum, RouterTransitionEnum, ThemeEnum } from '/@/enums/appEnum'; | 1 | import { ContentEnum, RouterTransitionEnum, ThemeEnum } from '/@/enums/appEnum'; |
2 | -import { TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum'; | 2 | +import { MenuModeEnum, MenuTypeEnum, TopMenuAlignEnum, TriggerEnum } from '/@/enums/menuEnum'; |
3 | + | ||
4 | +import mixImg from '/@/assets/images/layout/menu-mix.svg'; | ||
5 | +import sidebarImg from '/@/assets/images/layout/menu-sidebar.svg'; | ||
6 | +import menuTopImg from '/@/assets/images/layout/menu-top.svg'; | ||
3 | 7 | ||
4 | export enum HandlerEnum { | 8 | export enum HandlerEnum { |
5 | CHANGE_LAYOUT, | 9 | CHANGE_LAYOUT, |
@@ -15,6 +19,7 @@ export enum HandlerEnum { | @@ -15,6 +19,7 @@ export enum HandlerEnum { | ||
15 | MENU_THEME, | 19 | MENU_THEME, |
16 | MENU_SPLIT, | 20 | MENU_SPLIT, |
17 | MENU_SHOW_SEARCH, | 21 | MENU_SHOW_SEARCH, |
22 | + MENU_FIXED, | ||
18 | 23 | ||
19 | // header | 24 | // header |
20 | HEADER_SHOW, | 25 | HEADER_SHOW, |
@@ -23,7 +28,6 @@ export enum HandlerEnum { | @@ -23,7 +28,6 @@ export enum HandlerEnum { | ||
23 | 28 | ||
24 | TABS_SHOW_QUICK, | 29 | TABS_SHOW_QUICK, |
25 | TABS_SHOW, | 30 | TABS_SHOW, |
26 | - TABS_SHOW_ICON, | ||
27 | 31 | ||
28 | OPEN_PAGE_LOADING, | 32 | OPEN_PAGE_LOADING, |
29 | OPEN_ROUTE_TRANSITION, | 33 | OPEN_ROUTE_TRANSITION, |
@@ -36,6 +40,7 @@ export enum HandlerEnum { | @@ -36,6 +40,7 @@ export enum HandlerEnum { | ||
36 | GRAY_MODE, | 40 | GRAY_MODE, |
37 | COLOR_WEAK, | 41 | COLOR_WEAK, |
38 | SHOW_LOGO, | 42 | SHOW_LOGO, |
43 | + SHOW_FOOTER, | ||
39 | } | 44 | } |
40 | 45 | ||
41 | export const themeOptions = [ | 46 | export const themeOptions = [ |
@@ -102,3 +107,25 @@ export const routerTransitionOptions = [ | @@ -102,3 +107,25 @@ export const routerTransitionOptions = [ | ||
102 | value: item, | 107 | value: item, |
103 | }; | 108 | }; |
104 | }); | 109 | }); |
110 | + | ||
111 | +export const menuTypeList = [ | ||
112 | + { | ||
113 | + title: '左侧菜单模式', | ||
114 | + mode: MenuModeEnum.INLINE, | ||
115 | + type: MenuTypeEnum.SIDEBAR, | ||
116 | + src: sidebarImg, | ||
117 | + }, | ||
118 | + { | ||
119 | + title: '混合模式', | ||
120 | + mode: MenuModeEnum.INLINE, | ||
121 | + type: MenuTypeEnum.MIX, | ||
122 | + src: mixImg, | ||
123 | + }, | ||
124 | + | ||
125 | + { | ||
126 | + title: '顶部菜单模式', | ||
127 | + mode: MenuModeEnum.HORIZONTAL, | ||
128 | + type: MenuTypeEnum.TOP_MENU, | ||
129 | + src: menuTopImg, | ||
130 | + }, | ||
131 | +]; |
src/layouts/default/setting/handler.ts
1 | -import { HandlerEnum } from './const'; | ||
2 | -// import { MenuThemeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; | 1 | +import { HandlerEnum } from './enum'; |
3 | import { | 2 | import { |
4 | updateColorWeak, | 3 | updateColorWeak, |
5 | updateGrayMode, | 4 | updateGrayMode, |
@@ -19,12 +18,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf | @@ -19,12 +18,7 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf | ||
19 | case HandlerEnum.CHANGE_LAYOUT: | 18 | case HandlerEnum.CHANGE_LAYOUT: |
20 | const { mode, type, split } = value; | 19 | const { mode, type, split } = value; |
21 | const splitOpt = split === undefined ? { split } : {}; | 20 | const splitOpt = split === undefined ? { split } : {}; |
22 | - // let headerSetting = {}; | ||
23 | - // if (type === MenuTypeEnum.TOP_MENU) { | ||
24 | - // headerSetting = { | ||
25 | - // theme: MenuThemeEnum.DARK, | ||
26 | - // }; | ||
27 | - // } | 21 | + |
28 | return { | 22 | return { |
29 | menuSetting: { | 23 | menuSetting: { |
30 | mode, | 24 | mode, |
@@ -33,159 +27,103 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf | @@ -33,159 +27,103 @@ export function handler(event: HandlerEnum, value: any): DeepPartial<ProjectConf | ||
33 | show: true, | 27 | show: true, |
34 | ...splitOpt, | 28 | ...splitOpt, |
35 | }, | 29 | }, |
36 | - // headerSetting, | ||
37 | }; | 30 | }; |
38 | 31 | ||
39 | case HandlerEnum.MENU_HAS_DRAG: | 32 | case HandlerEnum.MENU_HAS_DRAG: |
40 | - return { | ||
41 | - menuSetting: { | ||
42 | - hasDrag: value, | ||
43 | - }, | ||
44 | - }; | 33 | + return { menuSetting: { hasDrag: value } }; |
45 | 34 | ||
46 | case HandlerEnum.MENU_ACCORDION: | 35 | case HandlerEnum.MENU_ACCORDION: |
47 | - return { | ||
48 | - menuSetting: { | ||
49 | - accordion: value, | ||
50 | - }, | ||
51 | - }; | 36 | + return { menuSetting: { accordion: value } }; |
37 | + | ||
52 | case HandlerEnum.MENU_TRIGGER: | 38 | case HandlerEnum.MENU_TRIGGER: |
53 | - return { | ||
54 | - menuSetting: { | ||
55 | - trigger: value, | ||
56 | - }, | ||
57 | - }; | 39 | + return { menuSetting: { trigger: value } }; |
40 | + | ||
58 | case HandlerEnum.MENU_TOP_ALIGN: | 41 | case HandlerEnum.MENU_TOP_ALIGN: |
59 | - return { | ||
60 | - menuSetting: { | ||
61 | - topMenuAlign: value, | ||
62 | - }, | ||
63 | - }; | 42 | + return { menuSetting: { topMenuAlign: value } }; |
43 | + | ||
64 | case HandlerEnum.MENU_COLLAPSED: | 44 | case HandlerEnum.MENU_COLLAPSED: |
65 | - return { | ||
66 | - menuSetting: { | ||
67 | - collapsed: value, | ||
68 | - }, | ||
69 | - }; | 45 | + return { menuSetting: { collapsed: value } }; |
46 | + | ||
70 | case HandlerEnum.MENU_WIDTH: | 47 | case HandlerEnum.MENU_WIDTH: |
71 | - return { | ||
72 | - menuSetting: { | ||
73 | - menuWidth: value, | ||
74 | - }, | ||
75 | - }; | 48 | + return { menuSetting: { menuWidth: value } }; |
49 | + | ||
76 | case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: | 50 | case HandlerEnum.MENU_COLLAPSED_SHOW_TITLE: |
77 | - return { | ||
78 | - menuSetting: { | ||
79 | - collapsedShowTitle: value, | ||
80 | - }, | ||
81 | - }; | 51 | + return { menuSetting: { collapsedShowTitle: value } }; |
52 | + | ||
82 | case HandlerEnum.MENU_SHOW_SIDEBAR: | 53 | case HandlerEnum.MENU_SHOW_SIDEBAR: |
83 | - return { | ||
84 | - menuSetting: { | ||
85 | - show: value, | ||
86 | - }, | ||
87 | - }; | 54 | + return { menuSetting: { show: value } }; |
55 | + | ||
88 | case HandlerEnum.MENU_THEME: | 56 | case HandlerEnum.MENU_THEME: |
89 | updateSidebarBgColor(value); | 57 | updateSidebarBgColor(value); |
90 | - return { | ||
91 | - menuBgColor: value, | ||
92 | - // menuSetting: { | ||
93 | - // theme: value, | ||
94 | - // }, | ||
95 | - }; | 58 | + return { menuSetting: { bgColor: value } }; |
59 | + | ||
96 | case HandlerEnum.MENU_SPLIT: | 60 | case HandlerEnum.MENU_SPLIT: |
97 | - return { | ||
98 | - menuSetting: { | ||
99 | - split: value, | ||
100 | - }, | ||
101 | - }; | 61 | + return { menuSetting: { split: value } }; |
62 | + | ||
63 | + case HandlerEnum.MENU_FIXED: | ||
64 | + return { menuSetting: { fixed: value } }; | ||
65 | + | ||
102 | case HandlerEnum.MENU_SHOW_SEARCH: | 66 | case HandlerEnum.MENU_SHOW_SEARCH: |
103 | - return { | ||
104 | - menuSetting: { | ||
105 | - showSearch: value, | ||
106 | - }, | ||
107 | - }; | 67 | + return { menuSetting: { showSearch: value } }; |
68 | + | ||
69 | + // ============root================== | ||
70 | + | ||
108 | case HandlerEnum.OPEN_PAGE_LOADING: | 71 | case HandlerEnum.OPEN_PAGE_LOADING: |
109 | - return { | ||
110 | - openPageLoading: value, | ||
111 | - }; | 72 | + appStore.commitPageLoadingState(false); |
73 | + return { openPageLoading: value }; | ||
74 | + | ||
112 | case HandlerEnum.OPEN_ROUTE_TRANSITION: | 75 | case HandlerEnum.OPEN_ROUTE_TRANSITION: |
113 | - return { | ||
114 | - openRouterTransition: value, | ||
115 | - }; | 76 | + return { openRouterTransition: value }; |
77 | + | ||
116 | case HandlerEnum.ROUTER_TRANSITION: | 78 | case HandlerEnum.ROUTER_TRANSITION: |
117 | - return { | ||
118 | - routerTransition: value, | ||
119 | - }; | 79 | + return { routerTransition: value }; |
80 | + | ||
120 | case HandlerEnum.LOCK_TIME: | 81 | case HandlerEnum.LOCK_TIME: |
121 | - return { | ||
122 | - lockTime: value, | ||
123 | - }; | 82 | + return { lockTime: value }; |
83 | + | ||
124 | case HandlerEnum.FULL_CONTENT: | 84 | case HandlerEnum.FULL_CONTENT: |
125 | - return { | ||
126 | - fullContent: value, | ||
127 | - }; | 85 | + return { fullContent: value }; |
86 | + | ||
128 | case HandlerEnum.CONTENT_MODE: | 87 | case HandlerEnum.CONTENT_MODE: |
129 | - return { | ||
130 | - contentMode: value, | ||
131 | - }; | 88 | + return { contentMode: value }; |
89 | + | ||
132 | case HandlerEnum.SHOW_BREADCRUMB: | 90 | case HandlerEnum.SHOW_BREADCRUMB: |
133 | - return { | ||
134 | - showBreadCrumb: value, | ||
135 | - }; | 91 | + return { showBreadCrumb: value }; |
92 | + | ||
136 | case HandlerEnum.SHOW_BREADCRUMB_ICON: | 93 | case HandlerEnum.SHOW_BREADCRUMB_ICON: |
137 | - return { | ||
138 | - showBreadCrumbIcon: value, | ||
139 | - }; | 94 | + return { showBreadCrumbIcon: value }; |
95 | + | ||
140 | case HandlerEnum.GRAY_MODE: | 96 | case HandlerEnum.GRAY_MODE: |
141 | updateGrayMode(value); | 97 | updateGrayMode(value); |
142 | - return { | ||
143 | - grayMode: value, | ||
144 | - }; | 98 | + return { grayMode: value }; |
99 | + | ||
100 | + case HandlerEnum.SHOW_FOOTER: | ||
101 | + return { showFooter: value }; | ||
102 | + | ||
145 | case HandlerEnum.COLOR_WEAK: | 103 | case HandlerEnum.COLOR_WEAK: |
146 | updateColorWeak(value); | 104 | updateColorWeak(value); |
147 | - return { | ||
148 | - colorWeak: value, | ||
149 | - }; | 105 | + return { colorWeak: value }; |
106 | + | ||
150 | case HandlerEnum.SHOW_LOGO: | 107 | case HandlerEnum.SHOW_LOGO: |
151 | - return { | ||
152 | - showLogo: value, | ||
153 | - }; | 108 | + return { showLogo: value }; |
109 | + | ||
110 | + // ============tabs================== | ||
154 | case HandlerEnum.TABS_SHOW_QUICK: | 111 | case HandlerEnum.TABS_SHOW_QUICK: |
155 | - return { | ||
156 | - multiTabsSetting: { | ||
157 | - showQuick: value, | ||
158 | - }, | ||
159 | - }; | ||
160 | - case HandlerEnum.TABS_SHOW_ICON: | ||
161 | - return { | ||
162 | - multiTabsSetting: { | ||
163 | - showIcon: value, | ||
164 | - }, | ||
165 | - }; | 112 | + return { multiTabsSetting: { showQuick: value } }; |
113 | + | ||
166 | case HandlerEnum.TABS_SHOW: | 114 | case HandlerEnum.TABS_SHOW: |
167 | - return { | ||
168 | - multiTabsSetting: { | ||
169 | - show: value, | ||
170 | - }, | ||
171 | - }; | 115 | + return { multiTabsSetting: { show: value } }; |
116 | + | ||
117 | + // ============header================== | ||
172 | case HandlerEnum.HEADER_THEME: | 118 | case HandlerEnum.HEADER_THEME: |
173 | updateHeaderBgColor(value); | 119 | updateHeaderBgColor(value); |
174 | - return { | ||
175 | - headerBgColor: value, | ||
176 | - }; | 120 | + return { headerSetting: { bgColor: value } }; |
121 | + | ||
177 | case HandlerEnum.HEADER_FIXED: | 122 | case HandlerEnum.HEADER_FIXED: |
178 | - return { | ||
179 | - headerSetting: { | ||
180 | - fixed: value, | ||
181 | - }, | ||
182 | - }; | 123 | + return { headerSetting: { fixed: value } }; |
124 | + | ||
183 | case HandlerEnum.HEADER_SHOW: | 125 | case HandlerEnum.HEADER_SHOW: |
184 | - return { | ||
185 | - headerSetting: { | ||
186 | - show: value, | ||
187 | - }, | ||
188 | - }; | 126 | + return { headerSetting: { show: value } }; |
189 | default: | 127 | default: |
190 | return {}; | 128 | return {}; |
191 | } | 129 | } |
src/layouts/default/setting/index.vue
@@ -10,7 +10,7 @@ | @@ -10,7 +10,7 @@ | ||
10 | import SettingDrawer from './SettingDrawer'; | 10 | import SettingDrawer from './SettingDrawer'; |
11 | 11 | ||
12 | import { useDrawer } from '/@/components/Drawer'; | 12 | import { useDrawer } from '/@/components/Drawer'; |
13 | - // | 13 | + |
14 | export default defineComponent({ | 14 | export default defineComponent({ |
15 | name: 'SettingBtn', | 15 | name: 'SettingBtn', |
16 | components: { SettingOutlined, SettingDrawer }, | 16 | components: { SettingOutlined, SettingDrawer }, |
src/layouts/default/sider/index.less
1 | @import (reference) '../../../design/index.less'; | 1 | @import (reference) '../../../design/index.less'; |
2 | 2 | ||
3 | .layout-sidebar { | 3 | .layout-sidebar { |
4 | - background-size: 100% 100%; | 4 | + overflow: hidden; |
5 | + | ||
6 | + &.fixed { | ||
7 | + position: fixed; | ||
8 | + top: 0; | ||
9 | + left: 0; | ||
10 | + height: 100%; | ||
11 | + } | ||
5 | 12 | ||
6 | &.ant-layout-sider-dark { | 13 | &.ant-layout-sider-dark { |
7 | background: @sider-dark-bg-color; | 14 | background: @sider-dark-bg-color; |
@@ -9,6 +16,7 @@ | @@ -9,6 +16,7 @@ | ||
9 | 16 | ||
10 | &:not(.ant-layout-sider-dark) { | 17 | &:not(.ant-layout-sider-dark) { |
11 | border-right: 1px solid @border-color-light; | 18 | border-right: 1px solid @border-color-light; |
19 | + box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05); | ||
12 | } | 20 | } |
13 | 21 | ||
14 | .ant-layout-sider-zero-width-trigger { | 22 | .ant-layout-sider-zero-width-trigger { |
src/layouts/default/sider/LayoutSideBar.tsx renamed to src/layouts/default/sider/index.tsx
1 | import './index.less'; | 1 | import './index.less'; |
2 | 2 | ||
3 | -import { computed, defineComponent, ref, unref } from 'vue'; | 3 | +import { computed, defineComponent, ref, unref, watch, nextTick } from 'vue'; |
4 | 4 | ||
5 | import { Layout } from 'ant-design-vue'; | 5 | import { Layout } from 'ant-design-vue'; |
6 | -import LayoutMenu from '/@/layouts/default/menu/LayoutMenu'; | 6 | +import LayoutMenu from '../menu'; |
7 | 7 | ||
8 | import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; | 8 | import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum'; |
9 | 9 | ||
10 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | 10 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
11 | +import { useHeaderSetting } from '/@/hooks/setting/useHeaderSetting'; | ||
11 | import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider'; | 12 | import { useTrigger, useDragLine, useSiderEvent } from './useLayoutSider'; |
13 | +import { useLayoutContext } from '../useLayoutContext'; | ||
12 | 14 | ||
13 | export default defineComponent({ | 15 | export default defineComponent({ |
14 | name: 'LayoutSideBar', | 16 | name: 'LayoutSideBar', |
15 | setup() { | 17 | setup() { |
16 | - const dragBarRef = ref<Nullable<HTMLDivElement>>(null); | ||
17 | - const sideRef = ref<Nullable<HTMLDivElement>>(null); | 18 | + const topRef = ref(0); |
19 | + const dragBarRef = ref<ElRef>(null); | ||
20 | + const sideRef = ref<ElRef>(null); | ||
18 | 21 | ||
19 | - const { getCollapsed, getMenuWidth, getSplit, getTheme } = useMenuSetting(); | 22 | + const { |
23 | + getCollapsed, | ||
24 | + getMenuWidth, | ||
25 | + getSplit, | ||
26 | + getMenuTheme, | ||
27 | + getRealWidth, | ||
28 | + getMenuHidden, | ||
29 | + getMenuFixed, | ||
30 | + } = useMenuSetting(); | ||
31 | + | ||
32 | + const { getShowFullHeaderRef, getUnFixedAndFull } = useHeaderSetting(); | ||
33 | + | ||
34 | + const injectValue = useLayoutContext(); | ||
20 | 35 | ||
21 | const { getTriggerAttr, getTriggerSlot } = useTrigger(); | 36 | const { getTriggerAttr, getTriggerSlot } = useTrigger(); |
22 | 37 | ||
@@ -37,11 +52,62 @@ export default defineComponent({ | @@ -37,11 +52,62 @@ export default defineComponent({ | ||
37 | return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE; | 52 | return unref(getSplit) ? MenuSplitTyeEnum.LEFT : MenuSplitTyeEnum.NONE; |
38 | }); | 53 | }); |
39 | 54 | ||
55 | + const showClassSideBarRef = computed(() => { | ||
56 | + return unref(getSplit) ? unref(getMenuHidden) : true; | ||
57 | + }); | ||
58 | + | ||
59 | + const getSiderClass = computed(() => { | ||
60 | + return { | ||
61 | + 'layout-sidebar': true, | ||
62 | + fixed: unref(getMenuFixed), | ||
63 | + hidden: !unref(showClassSideBarRef), | ||
64 | + }; | ||
65 | + }); | ||
66 | + | ||
67 | + const getSiderStyle = computed(() => { | ||
68 | + const top = `${unref(topRef)}px`; | ||
69 | + if (!unref(getMenuFixed)) { | ||
70 | + return { top }; | ||
71 | + } | ||
72 | + return { | ||
73 | + top, | ||
74 | + height: `calc(100% - ${top})`, | ||
75 | + }; | ||
76 | + }); | ||
77 | + | ||
78 | + watch( | ||
79 | + () => getShowFullHeaderRef.value, | ||
80 | + () => { | ||
81 | + topRef.value = 0; | ||
82 | + if (unref(getUnFixedAndFull)) return; | ||
83 | + nextTick(() => { | ||
84 | + const fullHeaderEl = unref(injectValue.fullHeaderRef)?.$el; | ||
85 | + if (!fullHeaderEl) return; | ||
86 | + topRef.value = fullHeaderEl.offsetHeight; | ||
87 | + }); | ||
88 | + }, | ||
89 | + { | ||
90 | + immediate: true, | ||
91 | + } | ||
92 | + ); | ||
93 | + | ||
94 | + const getHiddenDomStyle = computed(() => { | ||
95 | + const width = `${unref(getRealWidth)}px`; | ||
96 | + return { | ||
97 | + width: width, | ||
98 | + overflow: 'hidden', | ||
99 | + flex: `0 0 ${width}`, | ||
100 | + 'max-width': width, | ||
101 | + 'min-width': width, | ||
102 | + transition: 'all 0.2s', | ||
103 | + }; | ||
104 | + }); | ||
105 | + | ||
40 | function renderDefault() { | 106 | function renderDefault() { |
41 | return ( | 107 | return ( |
42 | <> | 108 | <> |
43 | <LayoutMenu | 109 | <LayoutMenu |
44 | - theme={unref(getTheme)} | 110 | + theme={unref(getMenuTheme)} |
45 | menuMode={unref(getMode)} | 111 | menuMode={unref(getMode)} |
46 | splitType={unref(getSplitType)} | 112 | splitType={unref(getSplitType)} |
47 | /> | 113 | /> |
@@ -52,25 +118,32 @@ export default defineComponent({ | @@ -52,25 +118,32 @@ export default defineComponent({ | ||
52 | 118 | ||
53 | return () => { | 119 | return () => { |
54 | return ( | 120 | return ( |
55 | - <Layout.Sider | ||
56 | - ref={sideRef} | ||
57 | - class="layout-sidebar" | ||
58 | - breakpoint="md" | ||
59 | - collapsible | ||
60 | - width={unref(getMenuWidth)} | ||
61 | - collapsed={unref(getCollapsed)} | ||
62 | - collapsedWidth={unref(getCollapsedWidth)} | ||
63 | - theme={unref(getTheme)} | ||
64 | - onClick={onSiderClick} | ||
65 | - onCollapse={onCollapseChange} | ||
66 | - onBreakpoint={onBreakpointChange} | ||
67 | - {...unref(getTriggerAttr)} | ||
68 | - > | ||
69 | - {{ | ||
70 | - ...unref(getTriggerSlot), | ||
71 | - default: () => renderDefault(), | ||
72 | - }} | ||
73 | - </Layout.Sider> | 121 | + <> |
122 | + {unref(getMenuFixed) && ( | ||
123 | + <div style={unref(getHiddenDomStyle)} class={{ hidden: !unref(showClassSideBarRef) }} /> | ||
124 | + )} | ||
125 | + | ||
126 | + <Layout.Sider | ||
127 | + ref={sideRef} | ||
128 | + breakpoint="md" | ||
129 | + collapsible | ||
130 | + class={unref(getSiderClass)} | ||
131 | + style={unref(getSiderStyle)} | ||
132 | + width={unref(getMenuWidth)} | ||
133 | + collapsed={unref(getCollapsed)} | ||
134 | + collapsedWidth={unref(getCollapsedWidth)} | ||
135 | + theme={unref(getMenuTheme)} | ||
136 | + onClick={onSiderClick} | ||
137 | + onCollapse={onCollapseChange} | ||
138 | + onBreakpoint={onBreakpointChange} | ||
139 | + {...unref(getTriggerAttr)} | ||
140 | + > | ||
141 | + {{ | ||
142 | + ...unref(getTriggerSlot), | ||
143 | + default: () => renderDefault(), | ||
144 | + }} | ||
145 | + </Layout.Sider> | ||
146 | + </> | ||
74 | ); | 147 | ); |
75 | }; | 148 | }; |
76 | }, | 149 | }, |
src/layouts/default/sider/useLayoutSider.tsx
@@ -16,7 +16,7 @@ export function useSiderEvent() { | @@ -16,7 +16,7 @@ export function useSiderEvent() { | ||
16 | const brokenRef = ref(false); | 16 | const brokenRef = ref(false); |
17 | const collapseRef = ref(true); | 17 | const collapseRef = ref(true); |
18 | 18 | ||
19 | - const { setMenuSetting, getCollapsed, getMiniWidthNumber, getShow } = useMenuSetting(); | 19 | + const { setMenuSetting, getCollapsed, getMiniWidthNumber, getShowMenu } = useMenuSetting(); |
20 | 20 | ||
21 | const getCollapsedWidth = computed(() => { | 21 | const getCollapsedWidth = computed(() => { |
22 | return unref(brokenRef) ? 0 : unref(getMiniWidthNumber); | 22 | return unref(brokenRef) ? 0 : unref(getMiniWidthNumber); |
@@ -38,7 +38,7 @@ export function useSiderEvent() { | @@ -38,7 +38,7 @@ export function useSiderEvent() { | ||
38 | 38 | ||
39 | function onSiderClick(e: ChangeEvent) { | 39 | function onSiderClick(e: ChangeEvent) { |
40 | if (!e || !e.target || e.target.className !== 'basic-menu__content') return; | 40 | if (!e || !e.target || e.target.className !== 'basic-menu__content') return; |
41 | - if (!unref(getCollapsed) || !unref(getShow)) return; | 41 | + if (!unref(getCollapsed) || !unref(getShowMenu)) return; |
42 | setMenuSetting({ collapsed: false }); | 42 | setMenuSetting({ collapsed: false }); |
43 | } | 43 | } |
44 | return { getCollapsedWidth, onCollapseChange, onBreakpointChange, onSiderClick }; | 44 | return { getCollapsedWidth, onCollapseChange, onBreakpointChange, onSiderClick }; |
src/layouts/default/useLayoutContext.ts
0 → 100644
1 | +import { InjectionKey, Ref } from 'vue'; | ||
2 | +import { createContext, useContext } from '/@/hooks/core/useContext'; | ||
3 | + | ||
4 | +export interface LayoutContextProps { | ||
5 | + fullHeaderRef: Ref<ComponentRef>; | ||
6 | +} | ||
7 | + | ||
8 | +const layoutContextInjectKey: InjectionKey<LayoutContextProps> = Symbol(); | ||
9 | + | ||
10 | +export function createLayoutContext(context: LayoutContextProps) { | ||
11 | + return createContext<LayoutContextProps>(context, layoutContextInjectKey); | ||
12 | +} | ||
13 | + | ||
14 | +export function useLayoutContext() { | ||
15 | + return useContext<LayoutContextProps>(layoutContextInjectKey); | ||
16 | +} |
src/layouts/iframe/useFrameKeepAlive.ts
@@ -12,7 +12,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | @@ -12,7 +12,7 @@ import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | ||
12 | 12 | ||
13 | export function useFrameKeepAlive() { | 13 | export function useFrameKeepAlive() { |
14 | const { currentRoute } = useRouter(); | 14 | const { currentRoute } = useRouter(); |
15 | - const { getShow } = useMultipleTabSetting(); | 15 | + const { getShowMultipleTab } = useMultipleTabSetting(); |
16 | 16 | ||
17 | const getFramePages = computed(() => { | 17 | const getFramePages = computed(() => { |
18 | const ret = | 18 | const ret = |
@@ -49,7 +49,7 @@ export function useFrameKeepAlive() { | @@ -49,7 +49,7 @@ export function useFrameKeepAlive() { | ||
49 | } | 49 | } |
50 | 50 | ||
51 | function hasRenderFrame(path: string) { | 51 | function hasRenderFrame(path: string) { |
52 | - return unref(getShow) ? unref(getOpenTabList).includes(path) : true; | 52 | + return unref(getShowMultipleTab) ? unref(getOpenTabList).includes(path) : true; |
53 | } | 53 | } |
54 | return { hasRenderFrame, getFramePages, showIframe, getAllFramePages }; | 54 | return { hasRenderFrame, getFramePages, showIframe, getAllFramePages }; |
55 | } | 55 | } |
src/layouts/page/index.tsx
@@ -20,7 +20,7 @@ interface DefaultContext { | @@ -20,7 +20,7 @@ interface DefaultContext { | ||
20 | export default defineComponent({ | 20 | export default defineComponent({ |
21 | name: 'PageLayout', | 21 | name: 'PageLayout', |
22 | setup() { | 22 | setup() { |
23 | - const { getShow } = useMenuSetting(); | 23 | + const { getShowMenu } = useMenuSetting(); |
24 | const { | 24 | const { |
25 | getOpenKeepAlive, | 25 | getOpenKeepAlive, |
26 | getRouterTransition, | 26 | getRouterTransition, |
@@ -32,7 +32,7 @@ export default defineComponent({ | @@ -32,7 +32,7 @@ export default defineComponent({ | ||
32 | 32 | ||
33 | const transitionEvent = useTransition(); | 33 | const transitionEvent = useTransition(); |
34 | 34 | ||
35 | - const openCacheRef = computed(() => unref(getOpenKeepAlive) && unref(getShow)); | 35 | + const openCacheRef = computed(() => unref(getOpenKeepAlive) && unref(getShowMenu)); |
36 | 36 | ||
37 | const getCacheTabsRef = computed(() => tabStore.getKeepAliveTabsState as string[]); | 37 | const getCacheTabsRef = computed(() => tabStore.getKeepAliveTabsState as string[]); |
38 | 38 |
src/settings/projectSetting.ts
@@ -21,12 +21,6 @@ const setting: ProjectConfig = { | @@ -21,12 +21,6 @@ const setting: ProjectConfig = { | ||
21 | // TODO 主题色 | 21 | // TODO 主题色 |
22 | themeColor: primaryColor, | 22 | themeColor: primaryColor, |
23 | 23 | ||
24 | - // header bg color | ||
25 | - headerBgColor: '#ffffff', | ||
26 | - | ||
27 | - // sidebar menu bg color | ||
28 | - menuBgColor: '#273352', | ||
29 | - | ||
30 | // Whether to show the configuration button | 24 | // Whether to show the configuration button |
31 | showSettingButton: true, | 25 | showSettingButton: true, |
32 | 26 | ||
@@ -48,8 +42,13 @@ const setting: ProjectConfig = { | @@ -48,8 +42,13 @@ const setting: ProjectConfig = { | ||
48 | // 是否显示logo | 42 | // 是否显示logo |
49 | showLogo: true, | 43 | showLogo: true, |
50 | 44 | ||
45 | + // 是否显示页脚 | ||
46 | + showFooter: true, | ||
47 | + | ||
51 | // 头部配置 | 48 | // 头部配置 |
52 | headerSetting: { | 49 | headerSetting: { |
50 | + // header bg color | ||
51 | + bgColor: '#ffffff', | ||
53 | fixed: true, | 52 | fixed: true, |
54 | // 是否显示顶部 | 53 | // 是否显示顶部 |
55 | show: true, | 54 | show: true, |
@@ -69,6 +68,10 @@ const setting: ProjectConfig = { | @@ -69,6 +68,10 @@ const setting: ProjectConfig = { | ||
69 | 68 | ||
70 | // 菜单配置 | 69 | // 菜单配置 |
71 | menuSetting: { | 70 | menuSetting: { |
71 | + // sidebar menu bg color | ||
72 | + bgColor: '#273352', | ||
73 | + | ||
74 | + fixed: true, | ||
72 | // 菜单折叠 | 75 | // 菜单折叠 |
73 | collapsed: false, | 76 | collapsed: false, |
74 | // 折叠菜单时候是否显示菜单名 | 77 | // 折叠菜单时候是否显示菜单名 |
@@ -107,8 +110,7 @@ const setting: ProjectConfig = { | @@ -107,8 +110,7 @@ const setting: ProjectConfig = { | ||
107 | show: true, | 110 | show: true, |
108 | // 开启快速操作 | 111 | // 开启快速操作 |
109 | showQuick: true, | 112 | showQuick: true, |
110 | - // 显示icon | ||
111 | - showIcon: false, | 113 | + |
112 | // 标签页缓存最大数量 | 114 | // 标签页缓存最大数量 |
113 | max: 12, | 115 | max: 12, |
114 | }, | 116 | }, |
src/settings/siteSetting.ts
@@ -2,3 +2,5 @@ | @@ -2,3 +2,5 @@ | ||
2 | export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin'; | 2 | export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin'; |
3 | // vue-vben-admin-next-doc | 3 | // vue-vben-admin-next-doc |
4 | export const DOC_URL = 'https://vvbin.cn/doc-next/'; | 4 | export const DOC_URL = 'https://vvbin.cn/doc-next/'; |
5 | +// site url | ||
6 | +export const SITE_URL = 'https://vvbin.cn/next/'; |
src/setup/App.ts
@@ -53,7 +53,12 @@ export function initAppConfigStore() { | @@ -53,7 +53,12 @@ export function initAppConfigStore() { | ||
53 | if (!projCfg) { | 53 | if (!projCfg) { |
54 | projCfg = projectSetting; | 54 | projCfg = projectSetting; |
55 | } | 55 | } |
56 | - const { colorWeak, grayMode, headerBgColor, menuBgColor } = projCfg; | 56 | + const { |
57 | + colorWeak, | ||
58 | + grayMode, | ||
59 | + headerSetting: { bgColor: headerBgColor }, | ||
60 | + menuSetting: { bgColor }, | ||
61 | + } = projCfg; | ||
57 | try { | 62 | try { |
58 | // if ( | 63 | // if ( |
59 | // themeColor !== primaryColor && | 64 | // themeColor !== primaryColor && |
@@ -63,7 +68,7 @@ export function initAppConfigStore() { | @@ -63,7 +68,7 @@ export function initAppConfigStore() { | ||
63 | // updateTheme(themeColor); | 68 | // updateTheme(themeColor); |
64 | // } | 69 | // } |
65 | headerBgColor && updateHeaderBgColor(headerBgColor); | 70 | headerBgColor && updateHeaderBgColor(headerBgColor); |
66 | - menuBgColor && updateSidebarBgColor(menuBgColor); | 71 | + bgColor && updateSidebarBgColor(bgColor); |
67 | grayMode && updateGrayMode(grayMode); | 72 | grayMode && updateGrayMode(grayMode); |
68 | colorWeak && updateColorWeak(colorWeak); | 73 | colorWeak && updateColorWeak(colorWeak); |
69 | } catch (error) { | 74 | } catch (error) { |
src/types/config.d.ts
@@ -4,6 +4,8 @@ import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from | @@ -4,6 +4,8 @@ import { ContentEnum, PermissionModeEnum, ThemeEnum, RouterTransitionEnum } from | ||
4 | import type { LocaleType } from '/@/locales/types'; | 4 | import type { LocaleType } from '/@/locales/types'; |
5 | 5 | ||
6 | export interface MenuSetting { | 6 | export interface MenuSetting { |
7 | + bgColor: string; | ||
8 | + fixed: boolean; | ||
7 | collapsed: boolean; | 9 | collapsed: boolean; |
8 | collapsedShowTitle: boolean; | 10 | collapsedShowTitle: boolean; |
9 | hasDrag: boolean; | 11 | hasDrag: boolean; |
@@ -26,13 +28,13 @@ export interface MultiTabsSetting { | @@ -26,13 +28,13 @@ export interface MultiTabsSetting { | ||
26 | show: boolean; | 28 | show: boolean; |
27 | // 开启快速操作 | 29 | // 开启快速操作 |
28 | showQuick: boolean; | 30 | showQuick: boolean; |
29 | - // 显示icon | ||
30 | - showIcon: boolean; | 31 | + |
31 | // 缓存最大数量 | 32 | // 缓存最大数量 |
32 | max: number; | 33 | max: number; |
33 | } | 34 | } |
34 | 35 | ||
35 | export interface HeaderSetting { | 36 | export interface HeaderSetting { |
37 | + bgColor: string; | ||
36 | fixed: boolean; | 38 | fixed: boolean; |
37 | show: boolean; | 39 | show: boolean; |
38 | theme: ThemeEnum; | 40 | theme: ThemeEnum; |
@@ -59,10 +61,7 @@ export interface LocaleSetting { | @@ -59,10 +61,7 @@ export interface LocaleSetting { | ||
59 | 61 | ||
60 | export interface ProjectConfig { | 62 | export interface ProjectConfig { |
61 | locale: LocaleSetting; | 63 | locale: LocaleSetting; |
62 | - // header背景色 | ||
63 | - headerBgColor: string; | ||
64 | - // 左侧菜单背景色 | ||
65 | - menuBgColor: string; | 64 | + |
66 | // 是否显示配置按钮 | 65 | // 是否显示配置按钮 |
67 | showSettingButton: boolean; | 66 | showSettingButton: boolean; |
68 | // 权限模式 | 67 | // 权限模式 |
@@ -79,6 +78,7 @@ export interface ProjectConfig { | @@ -79,6 +78,7 @@ export interface ProjectConfig { | ||
79 | contentMode: ContentEnum; | 78 | contentMode: ContentEnum; |
80 | // 是否显示logo | 79 | // 是否显示logo |
81 | showLogo: boolean; | 80 | showLogo: boolean; |
81 | + showFooter: boolean; | ||
82 | headerSetting: HeaderSetting; | 82 | headerSetting: HeaderSetting; |
83 | // 菜单类型 | 83 | // 菜单类型 |
84 | // menuType: MenuTypeEnum; | 84 | // menuType: MenuTypeEnum; |
src/types/global.d.ts
@@ -55,3 +55,11 @@ declare type TargetContext = '_self' | '_blank'; | @@ -55,3 +55,11 @@ declare type TargetContext = '_self' | '_blank'; | ||
55 | declare type TimeoutHandle = ReturnType<typeof setTimeout>; | 55 | declare type TimeoutHandle = ReturnType<typeof setTimeout>; |
56 | 56 | ||
57 | declare type IntervalHandle = ReturnType<typeof setInterval>; | 57 | declare type IntervalHandle = ReturnType<typeof setInterval>; |
58 | + | ||
59 | +declare interface ComponentElRef<T extends HTMLElement = HTMLDivElement> { | ||
60 | + $el: T; | ||
61 | +} | ||
62 | + | ||
63 | +declare type ComponentRef<T extends HTMLElement = HTMLDivElement> = ComponentElRef<T> | null; | ||
64 | + | ||
65 | +declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>; |
yarn.lock
@@ -1737,21 +1737,6 @@ | @@ -1737,21 +1737,6 @@ | ||
1737 | vscode-languageserver-textdocument "^1.0.1" | 1737 | vscode-languageserver-textdocument "^1.0.1" |
1738 | vscode-uri "^2.1.2" | 1738 | vscode-uri "^2.1.2" |
1739 | 1739 | ||
1740 | -"@vueuse/core@^4.0.0-rc.3": | ||
1741 | - version "4.0.0-rc.3" | ||
1742 | - resolved "https://registry.npmjs.org/@vueuse/core/-/core-4.0.0-rc.3.tgz#5381ca657e10df596cd7027fc5c96b2d4b3a090c" | ||
1743 | - integrity sha512-dQ/FZgo0z7kBFOvDWxuzaUrmuO8X1AlQk17e3PU1TVtG2Uu+mCvjPNbuvI2fjhTjl5rzPJawwoU2WZFj+nlFvw== | ||
1744 | - dependencies: | ||
1745 | - "@vueuse/shared" "4.0.0-rc.3" | ||
1746 | - vue-demi latest | ||
1747 | - | ||
1748 | -"@vueuse/shared@4.0.0-rc.3": | ||
1749 | - version "4.0.0-rc.3" | ||
1750 | - resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-4.0.0-rc.3.tgz#42fb56fed3779f3b8a17a82c16a364bad20d01b7" | ||
1751 | - integrity sha512-VY0x/XxpeTMHp/0FDiv1cgUUxkJGQl7liiM2AjR/J7+Ys/2Y2dijD5cAKViq9FGUPQQsOcLptMvMvUsDMoN4DA== | ||
1752 | - dependencies: | ||
1753 | - vue-demi latest | ||
1754 | - | ||
1755 | JSONStream@^1.0.4: | 1740 | JSONStream@^1.0.4: |
1756 | version "1.3.5" | 1741 | version "1.3.5" |
1757 | resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" | 1742 | resolved "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" |
@@ -8177,11 +8162,6 @@ vscode-uri@^2.1.2: | @@ -8177,11 +8162,6 @@ vscode-uri@^2.1.2: | ||
8177 | resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" | 8162 | resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" |
8178 | integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== | 8163 | integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== |
8179 | 8164 | ||
8180 | -vue-demi@latest: | ||
8181 | - version "0.4.3" | ||
8182 | - resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.4.3.tgz#6aaa9b52f02c32b4f9d4d11f02a1ae71031453c3" | ||
8183 | - integrity sha512-1DzLcZgHC9ZyFEYR4qZ83TdS1u9DglG8XVesBXqtbbmqFuO7sb8KG36kMfZCszieAweRDwAAVSAzjmEMG0+WwA== | ||
8184 | - | ||
8185 | vue-eslint-parser@^7.1.1: | 8165 | vue-eslint-parser@^7.1.1: |
8186 | version "7.1.1" | 8166 | version "7.1.1" |
8187 | resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3" | 8167 | resolved "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3" |