Commit 77028321816f00799cc3f70d3f0d6bde27c34522
1 parent
05980a81
perf: layout style optimization
Showing
27 changed files
with
200 additions
and
217 deletions
.env
CHANGELOG.zh_CN.md
src/assets/images/logo.png
src/components/Breadcrumb/Breadcrumb.vue
src/components/Menu/src/BasicMenu.tsx
... | ... | @@ -66,7 +66,7 @@ export default defineComponent({ |
66 | 66 | offset += 54; |
67 | 67 | } |
68 | 68 | return { |
69 | - height: `calc(100% - ${offset - 30}px)`, | |
69 | + height: `calc(100% - ${offset - 38}px)`, | |
70 | 70 | position: 'relative', |
71 | 71 | overflow: 'auto', |
72 | 72 | }; |
... | ... | @@ -147,6 +147,7 @@ export default defineComponent({ |
147 | 147 | } |
148 | 148 | |
149 | 149 | const showTitle = computed(() => { |
150 | + if (props.isTop) return true; | |
150 | 151 | if (!props.isAppMenu) return true; |
151 | 152 | if (!props.collapsedShowTitle) { |
152 | 153 | return !menuStore.getCollapsedState; |
... | ... | @@ -247,7 +248,6 @@ export default defineComponent({ |
247 | 248 | return () => { |
248 | 249 | const { getCollapsedState } = menuStore; |
249 | 250 | const { mode } = props; |
250 | - | |
251 | 251 | return mode === MenuModeEnum.HORIZONTAL ? ( |
252 | 252 | renderMenu() |
253 | 253 | ) : ( | ... | ... |
src/components/Menu/src/SearchInput.vue
src/components/Menu/src/index.less
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | color: @white; |
5 | 5 | background: linear-gradient( |
6 | 6 | 118deg, |
7 | - rgba(@primary-color, 0.7), | |
7 | + rgba(@primary-color, 0.8), | |
8 | 8 | rgba(@primary-color, 1) |
9 | 9 | ) !important; |
10 | 10 | border-radius: 2px; |
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 | font-size: 12px; |
33 | 33 | flex-direction: column; |
34 | 34 | line-height: 24px; |
35 | + align-items: center; | |
35 | 36 | } |
36 | 37 | |
37 | 38 | & > li[role='menuitem']:not(.ant-menu-submenu) { |
... | ... | @@ -93,6 +94,8 @@ |
93 | 94 | } |
94 | 95 | |
95 | 96 | &-bg__sidebar-hor { |
97 | + overflow: hidden; | |
98 | + | |
96 | 99 | &.ant-menu-horizontal { |
97 | 100 | display: flex; |
98 | 101 | border: 0; |
... | ... | @@ -105,23 +108,16 @@ |
105 | 108 | &.ant-menu-light { |
106 | 109 | .ant-menu-item { |
107 | 110 | &.basic-menu-item__level1 { |
108 | - height: 38px; | |
109 | - line-height: 38px; | |
111 | + height: @header-height; | |
112 | + line-height: @header-height; | |
110 | 113 | } |
111 | 114 | } |
112 | 115 | |
113 | - .ant-menu-item:hover, | |
114 | 116 | .ant-menu-submenu:hover, |
115 | - .ant-menu-item-active, | |
116 | - .ant-menu-submenu-active, | |
117 | 117 | .ant-menu-item-open, |
118 | 118 | .ant-menu-submenu-open, |
119 | 119 | .ant-menu-item-selected, |
120 | - .ant-menu-submenu-selected { | |
121 | - color: @primary-color !important; | |
122 | - border-bottom: 3px solid @primary-color; | |
123 | - } | |
124 | - | |
120 | + .ant-menu-submenu-selected, | |
125 | 121 | .ant-menu-item:hover, |
126 | 122 | .ant-menu-item-active, |
127 | 123 | .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open, |
... | ... | @@ -261,10 +257,13 @@ |
261 | 257 | } |
262 | 258 | |
263 | 259 | &.ant-menu-light { |
260 | + overflow-x: hidden; | |
261 | + border-right: none; | |
262 | + | |
264 | 263 | .basic-menu-item__level1 { |
265 | 264 | &.top-active-menu { |
266 | 265 | color: @primary-color; |
267 | - border-bottom: 6px solid @primary-color; | |
266 | + border-bottom: 3px solid @primary-color; | |
268 | 267 | } |
269 | 268 | } |
270 | 269 | |
... | ... | @@ -306,16 +305,9 @@ |
306 | 305 | } |
307 | 306 | |
308 | 307 | &-light { |
309 | - border-right: 1px solid rgba(221, 221, 221, 0.6); | |
310 | - | |
311 | 308 | .ant-layout-sider-trigger { |
312 | 309 | color: @text-color-base; |
313 | - background: @trigger-light-bg-color; | |
314 | - | |
315 | - &:hover { | |
316 | - color: @text-color-base; | |
317 | - background: @trigger-light-hover-bg-color; | |
318 | - } | |
310 | + border-top: 1px solid @border-color-light; | |
319 | 311 | } |
320 | 312 | } |
321 | 313 | } | ... | ... |
src/components/Menu/src/props.ts
... | ... | @@ -54,6 +54,10 @@ export const basicProps = { |
54 | 54 | type: Boolean as PropType<boolean>, |
55 | 55 | default: true, |
56 | 56 | }, |
57 | + isTop: { | |
58 | + type: Boolean as PropType<boolean>, | |
59 | + default: false, | |
60 | + }, | |
57 | 61 | beforeClickFn: { |
58 | 62 | type: Function as PropType<Fn>, |
59 | 63 | default: null, | ... | ... |
src/design/ant/index.less
... | ... | @@ -2,10 +2,15 @@ |
2 | 2 | @import './input.less'; |
3 | 3 | @import './btn.less'; |
4 | 4 | |
5 | +// TODO beta.11 fix | |
5 | 6 | .ant-col { |
6 | 7 | width: 100%; |
7 | 8 | } |
8 | 9 | |
10 | +// .ant-form-item-label { | |
11 | +// text-align: unset; | |
12 | +// } | |
13 | + | |
9 | 14 | // ================================= |
10 | 15 | // ==============descriptions======= |
11 | 16 | // ================================= | ... | ... |
src/design/index.less
... | ... | @@ -36,7 +36,8 @@ input::-ms-reveal { |
36 | 36 | } |
37 | 37 | |
38 | 38 | body { |
39 | - font-family: 'Microsoft YaHei,微软雅黑,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB'; | |
39 | + // font-family: 'Microsoft YaHei,微软雅黑,Arial,sans-serif,Helvetica Neue,Helvetica,Pingfang SC,Hiragino Sans GB'; | |
40 | + font-family: '-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,noto sans,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,noto color emoji'; | |
40 | 41 | font-style: normal; |
41 | 42 | font-weight: normal; |
42 | 43 | line-height: 1.428571429; // 20/14 |
... | ... | @@ -149,7 +150,7 @@ object { |
149 | 150 | } |
150 | 151 | |
151 | 152 | .ant-layout { |
152 | - background: #f1f1f6; | |
153 | + background: #f0f2f5; | |
153 | 154 | |
154 | 155 | &-content { |
155 | 156 | position: relative; | ... | ... |
src/design/public.less
... | ... | @@ -5,11 +5,11 @@ |
5 | 5 | } |
6 | 6 | |
7 | 7 | // TODO 滚动条样式-待修改 |
8 | -::-webkit-scrollbar-track { | |
9 | - // background: rgba(0, 0, 0, 0.06); | |
10 | - // border-radius: 2px; | |
11 | - // box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); | |
12 | -} | |
8 | +// ::-webkit-scrollbar-track { | |
9 | +// // background: rgba(0, 0, 0, 0.06); | |
10 | +// // border-radius: 2px; | |
11 | +// // box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); | |
12 | +// } | |
13 | 13 | |
14 | 14 | /* 滚动条滑块 */ |
15 | 15 | ::-webkit-scrollbar-thumb { | ... | ... |
src/design/var/index.less
... | ... | @@ -3,13 +3,13 @@ |
3 | 3 | @import 'breakpoint'; |
4 | 4 | |
5 | 5 | // tabs |
6 | -@multiple-height: 36px; | |
6 | +@multiple-height: 30px; | |
7 | 7 | |
8 | 8 | // headers |
9 | -@header-height: 36px; | |
9 | +@header-height: 46px; | |
10 | 10 | |
11 | 11 | // logo width |
12 | -@logo-width: 40px; | |
12 | +@logo-width: 36px; | |
13 | 13 | |
14 | 14 | // |
15 | 15 | @sider-drag-z-index: 200; |
... | ... | @@ -18,4 +18,4 @@ |
18 | 18 | // app menu |
19 | 19 | |
20 | 20 | // left-menu |
21 | -@app-menu-item-height: 44px; | |
21 | +@app-menu-item-height: 42px; | ... | ... |
src/layouts/Logo.vue
1 | 1 | <template> |
2 | - <div class="app-logo" @click="handleGoHome"> | |
2 | + <div class="app-logo" @click="handleGoHome" :style="wrapStyle"> | |
3 | 3 | <img :src="logo" /> |
4 | - <div v-if="show" class="logo-title ml-1 mt-1 ellipsis">{{ globSetting.title }}</div> | |
4 | + <div v-if="show" class="logo-title ml-2 ellipsis">{{ globSetting.title }}</div> | |
5 | 5 | </div> |
6 | 6 | </template> |
7 | 7 | <script lang="ts"> |
8 | - import { defineComponent, PropType, ref, watch } from 'vue'; | |
8 | + import { computed, defineComponent, PropType, ref, watch } from 'vue'; | |
9 | 9 | // hooks |
10 | 10 | import { useSetting } from '/@/hooks/core/useSetting'; |
11 | + import { useTimeout } from '/@/hooks/core/useTimeout'; | |
12 | + import { useGo } from '/@/hooks/web/usePage'; | |
11 | 13 | |
12 | 14 | import { PageEnum } from '/@/enums/pageEnum'; |
15 | + import { MenuTypeEnum } from '../enums/menuEnum'; | |
16 | + | |
13 | 17 | import logo from '/@/assets/images/logo.png'; |
14 | - import { useTimeout } from '/@/hooks/core/useTimeout'; | |
15 | - import { useGo } from '/@/hooks/web/usePage'; | |
18 | + | |
19 | + import { menuStore } from '../store/modules/menu'; | |
20 | + import { appStore } from '../store/modules/app'; | |
16 | 21 | |
17 | 22 | export default defineComponent({ |
18 | 23 | name: 'Logo', |
... | ... | @@ -44,11 +49,24 @@ |
44 | 49 | } |
45 | 50 | ); |
46 | 51 | |
52 | + const wrapStyle = computed(() => { | |
53 | + const { getCollapsedState } = menuStore; | |
54 | + const { | |
55 | + menuSetting: { menuWidth, type }, | |
56 | + } = appStore.getProjectConfig; | |
57 | + const miniWidth = { minWidth: `${menuWidth}px` }; | |
58 | + if (type !== MenuTypeEnum.SIDEBAR) { | |
59 | + return miniWidth; | |
60 | + } | |
61 | + return getCollapsedState ? {} : miniWidth; | |
62 | + }); | |
63 | + | |
47 | 64 | return { |
48 | 65 | handleGoHome, |
49 | 66 | globSetting, |
50 | 67 | show: showRef, |
51 | 68 | logo, |
69 | + wrapStyle, | |
52 | 70 | }; |
53 | 71 | }, |
54 | 72 | }); |
... | ... | @@ -59,12 +77,13 @@ |
59 | 77 | .app-logo { |
60 | 78 | display: flex; |
61 | 79 | align-items: center; |
80 | + padding-left: 16px; | |
62 | 81 | cursor: pointer; |
63 | 82 | |
64 | 83 | .logo-title { |
65 | 84 | display: none; |
66 | - font-family: Georgia, serif; | |
67 | 85 | font-size: 16px; |
86 | + font-weight: 400; | |
68 | 87 | .respond-to(medium,{ |
69 | 88 | display: block; |
70 | 89 | }); | ... | ... |
src/layouts/default/LayoutContent.tsx
... | ... | @@ -4,7 +4,6 @@ import { Layout } from 'ant-design-vue'; |
4 | 4 | |
5 | 5 | import { ContentEnum } from '/@/enums/appEnum'; |
6 | 6 | import { appStore } from '/@/store/modules/app'; |
7 | -// import { RouterView } from 'vue-router'; | |
8 | 7 | import PageLayout from '/@/layouts/page/index'; |
9 | 8 | export default defineComponent({ |
10 | 9 | name: 'DefaultLayoutContent', |
... | ... | @@ -15,9 +14,7 @@ export default defineComponent({ |
15 | 14 | const wrapClass = contentMode === ContentEnum.FULL ? 'full' : 'fixed'; |
16 | 15 | return ( |
17 | 16 | <Layout.Content class={`layout-content ${wrapClass} `}> |
18 | - {{ | |
19 | - default: () => <PageLayout />, | |
20 | - }} | |
17 | + {() => <PageLayout />} | |
21 | 18 | </Layout.Content> |
22 | 19 | ); |
23 | 20 | }; | ... | ... |
src/layouts/default/LayoutHeader.tsx
1 | 1 | import { defineComponent, unref, computed, ref } from 'vue'; |
2 | + | |
2 | 3 | import { Layout, Tooltip, Badge } from 'ant-design-vue'; |
3 | 4 | import Logo from '/@/layouts/Logo.vue'; |
4 | 5 | import UserDropdown from './UserDropdown'; |
5 | 6 | import LayoutMenu from './LayoutMenu'; |
6 | -import { appStore } from '/@/store/modules/app'; | |
7 | -import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; | |
8 | 7 | import LayoutBreadcrumb from './LayoutBreadcrumb'; |
8 | +import LockAction from './actions/LockActionItem'; | |
9 | +import NoticeAction from './actions/notice/NoticeActionItem.vue'; | |
9 | 10 | import { |
10 | 11 | RedoOutlined, |
11 | 12 | FullscreenExitOutlined, |
... | ... | @@ -14,19 +15,24 @@ import { |
14 | 15 | LockOutlined, |
15 | 16 | BugOutlined, |
16 | 17 | } from '@ant-design/icons-vue'; |
18 | + | |
17 | 19 | import { useFullscreen } from '/@/hooks/web/useFullScreen'; |
18 | 20 | import { useTabs } from '/@/hooks/web/useTabs'; |
19 | -import { GITHUB_URL } from '/@/settings/siteSetting'; | |
20 | -import LockAction from './actions/LockActionItem'; | |
21 | -import { useModal } from '/@/components/Modal/index'; | |
22 | -import { errorStore } from '/@/store/modules/error'; | |
23 | 21 | import { useWindowSizeFn } from '/@/hooks/event/useWindowSize'; |
24 | -import NoticeAction from './actions/notice/NoticeActionItem.vue'; | |
25 | 22 | import { useRouter } from 'vue-router'; |
23 | +import { useModal } from '/@/components/Modal/index'; | |
24 | + | |
25 | +import { appStore } from '/@/store/modules/app'; | |
26 | +import { errorStore } from '/@/store/modules/error'; | |
27 | + | |
28 | +import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum'; | |
29 | +import { GITHUB_URL } from '/@/settings/siteSetting'; | |
26 | 30 | export default defineComponent({ |
27 | 31 | name: 'DefaultLayoutHeader', |
28 | 32 | setup() { |
29 | 33 | const widthRef = ref(200); |
34 | + let logoEl: Element | null; | |
35 | + | |
30 | 36 | const { refreshPage } = useTabs(); |
31 | 37 | const { push } = useRouter(); |
32 | 38 | const [register, { openModal }] = useModal(); |
... | ... | @@ -35,6 +41,7 @@ export default defineComponent({ |
35 | 41 | const getProjectConfigRef = computed(() => { |
36 | 42 | return appStore.getProjectConfig; |
37 | 43 | }); |
44 | + | |
38 | 45 | const showTopMenu = computed(() => { |
39 | 46 | const getProjectConfig = unref(getProjectConfigRef); |
40 | 47 | const { |
... | ... | @@ -43,7 +50,6 @@ export default defineComponent({ |
43 | 50 | return mode === MenuModeEnum.HORIZONTAL || splitMenu; |
44 | 51 | }); |
45 | 52 | |
46 | - let logoEl: Element | null; | |
47 | 53 | useWindowSizeFn( |
48 | 54 | () => { |
49 | 55 | if (!unref(showTopMenu)) return; |
... | ... | @@ -80,6 +86,7 @@ export default defineComponent({ |
80 | 86 | function handleLockPage() { |
81 | 87 | openModal(true); |
82 | 88 | } |
89 | + | |
83 | 90 | return () => { |
84 | 91 | const getProjectConfig = unref(getProjectConfigRef); |
85 | 92 | const { |
... | ... | @@ -99,7 +106,9 @@ export default defineComponent({ |
99 | 106 | } = getProjectConfig; |
100 | 107 | |
101 | 108 | const isSidebarType = menuType === MenuTypeEnum.SIDEBAR; |
109 | + | |
102 | 110 | const width = unref(widthRef); |
111 | + | |
103 | 112 | return ( |
104 | 113 | <Layout.Header class={['layout-header', 'flex p-0 px-4 ', unref(headerClass)]}> |
105 | 114 | {() => ( |
... | ... | @@ -112,10 +121,12 @@ export default defineComponent({ |
112 | 121 | )} |
113 | 122 | {unref(showTopMenu) && ( |
114 | 123 | <div |
115 | - class={[`layout-header__menu `, `justify-${topMenuAlign}`]} | |
124 | + class={[`layout-header__menu `]} | |
116 | 125 | style={{ width: `calc(100% - ${unref(width)}px)` }} |
117 | 126 | > |
118 | 127 | <LayoutMenu |
128 | + isTop={true} | |
129 | + class={`justify-${topMenuAlign}`} | |
119 | 130 | theme={headerTheme} |
120 | 131 | splitType={splitMenu ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE} |
121 | 132 | menuMode={splitMenu ? MenuModeEnum.HORIZONTAL : null} | ... | ... |
src/layouts/default/LayoutMenu.tsx
... | ... | @@ -45,6 +45,10 @@ export default defineComponent({ |
45 | 45 | type: Boolean as PropType<boolean>, |
46 | 46 | default: true, |
47 | 47 | }, |
48 | + isTop: { | |
49 | + type: Boolean as PropType<boolean>, | |
50 | + default: false, | |
51 | + }, | |
48 | 52 | menuMode: { |
49 | 53 | type: [String] as PropType<MenuModeEnum | null>, |
50 | 54 | default: '', |
... | ... | @@ -199,6 +203,7 @@ export default defineComponent({ |
199 | 203 | flatItems={unref(flatMenusRef)} |
200 | 204 | onClickSearchInput={handleClickSearchInput} |
201 | 205 | appendClass={props.splitType === MenuSplitTyeEnum.TOP} |
206 | + isTop={props.isTop} | |
202 | 207 | > |
203 | 208 | {{ |
204 | 209 | header: () => | ... | ... |
src/layouts/default/LayoutSideBar.tsx
... | ... | @@ -7,7 +7,7 @@ import { menuStore } from '/@/store/modules/menu'; |
7 | 7 | // import darkMiniIMg from '/@/assets/images/sidebar/dark-mini.png'; |
8 | 8 | // import lightMiniImg from '/@/assets/images/sidebar/light-mini.png'; |
9 | 9 | import darkImg from '/@/assets/images/sidebar/dark.png'; |
10 | -import lightImg from '/@/assets/images/sidebar/light.png'; | |
10 | +// import lightImg from '/@/assets/images/sidebar/light.png'; | |
11 | 11 | import { appStore } from '/@/store/modules/app'; |
12 | 12 | import { MenuModeEnum, MenuSplitTyeEnum, MenuThemeEnum } from '/@/enums/menuEnum'; |
13 | 13 | import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum'; |
... | ... | @@ -39,15 +39,16 @@ export default defineComponent({ |
39 | 39 | // const collapse = unref(collapseRef); |
40 | 40 | |
41 | 41 | const theme = unref(getProjectConfigRef).menuSetting.theme; |
42 | + if (theme === MenuThemeEnum.LIGHT) { | |
43 | + // bg = lightImg; | |
44 | + return {}; | |
45 | + } | |
42 | 46 | let bg = ''; |
43 | 47 | if (theme === MenuThemeEnum.DARK) { |
44 | 48 | // bg = collapse ? darkMiniIMg : darkImg; |
45 | 49 | bg = darkImg; |
46 | 50 | } |
47 | - if (theme === MenuThemeEnum.LIGHT) { | |
48 | - bg = lightImg; | |
49 | - // bg = collapse ? lightMiniImg : lightImg; | |
50 | - } | |
51 | + | |
51 | 52 | return { |
52 | 53 | 'background-image': `url(${bg})`, |
53 | 54 | }; | ... | ... |
src/layouts/default/UserDropdown.tsx
... | ... | @@ -21,6 +21,11 @@ export default defineComponent({ |
21 | 21 | return appStore.getProjectConfig; |
22 | 22 | }); |
23 | 23 | |
24 | + const getUserInfo = computed(() => { | |
25 | + const { realName = '', desc } = userStore.getUserInfoState || {}; | |
26 | + return { realName, desc }; | |
27 | + }); | |
28 | + | |
24 | 29 | /** |
25 | 30 | * @description: 退出登录 |
26 | 31 | */ |
... | ... | @@ -41,10 +46,20 @@ export default defineComponent({ |
41 | 46 | openDoc(); |
42 | 47 | } |
43 | 48 | } |
44 | - const getUserInfo = computed(() => { | |
45 | - const { realName = '', desc } = userStore.getUserInfoState || {}; | |
46 | - return { realName, desc }; | |
47 | - }); | |
49 | + | |
50 | + function renderItem({ icon, text, key }: { icon: string; text: string; key: string }) { | |
51 | + return ( | |
52 | + <Menu.Item key={key}> | |
53 | + {() => ( | |
54 | + <span class="flex items-center"> | |
55 | + <Icon icon={icon} class="mr-1" /> | |
56 | + <span>{text}</span> | |
57 | + </span> | |
58 | + )} | |
59 | + </Menu.Item> | |
60 | + ); | |
61 | + } | |
62 | + | |
48 | 63 | return () => { |
49 | 64 | const { realName } = unref(getUserInfo); |
50 | 65 | const { |
... | ... | @@ -65,28 +80,13 @@ export default defineComponent({ |
65 | 80 | <Menu slot="overlay" onClick={handleMenuClick}> |
66 | 81 | {() => ( |
67 | 82 | <> |
68 | - {showDoc && ( | |
69 | - <Menu.Item key="doc"> | |
70 | - {() => ( | |
71 | - <span class="flex items-center"> | |
72 | - <Icon icon="gg:loadbar-doc" class="mr-1" /> | |
73 | - <span>文档</span> | |
74 | - </span> | |
75 | - )} | |
76 | - </Menu.Item> | |
77 | - )} | |
83 | + {showDoc && renderItem({ key: 'doc', text: '文档', icon: 'gg:loadbar-doc' })} | |
78 | 84 | {showDoc && <Divider />} |
79 | - | |
80 | - <Menu.Item key="loginOut"> | |
81 | - {() => ( | |
82 | - <> | |
83 | - <span class="flex items-center"> | |
84 | - <Icon icon="ant-design:poweroff-outlined" class="mr-1" /> | |
85 | - <span>退出系统</span> | |
86 | - </span> | |
87 | - </> | |
88 | - )} | |
89 | - </Menu.Item> | |
85 | + {renderItem({ | |
86 | + key: 'loginOut', | |
87 | + text: '退出系统', | |
88 | + icon: 'ant-design:poweroff-outlined', | |
89 | + })} | |
90 | 90 | </> |
91 | 91 | )} |
92 | 92 | </Menu> | ... | ... |
src/layouts/default/actions/LockActionItem.less
src/layouts/default/actions/LockActionItem.tsx
src/layouts/default/index.less
1 | 1 | @import (reference) '../../design/index.less'; |
2 | 2 | |
3 | 3 | .default-layout { |
4 | - // .ant-menu-submenu .ant-menu-sub { | |
5 | - // transition: none !important; | |
6 | - // // transition: background 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s, | |
7 | - // // padding 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) 0s !important; | |
8 | - // } | |
9 | - | |
10 | 4 | &__content { |
11 | 5 | position: relative; |
12 | 6 | |
... | ... | @@ -72,6 +66,10 @@ |
72 | 66 | .layout-sidebar { |
73 | 67 | background-size: 100% 100%; |
74 | 68 | |
69 | + &:not(.ant-layout-sider-dark) { | |
70 | + border-right: 1px solid @border-color-light; | |
71 | + } | |
72 | + | |
75 | 73 | .ant-layout-sider-zero-width-trigger { |
76 | 74 | top: 40%; |
77 | 75 | z-index: 10; |
... | ... | @@ -99,25 +97,13 @@ |
99 | 97 | } |
100 | 98 | } |
101 | 99 | |
102 | - .setting-button { | |
103 | - top: 45%; | |
104 | - right: 0; | |
105 | - padding: 8px; | |
106 | - border-radius: 6px 0 0 6px; | |
107 | - | |
108 | - svg { | |
109 | - width: 1em; | |
110 | - height: 1em; | |
111 | - } | |
112 | - } | |
113 | - | |
114 | 100 | &__tabs { |
115 | 101 | z-index: 10; |
116 | 102 | height: @multiple-height; |
117 | 103 | padding: 0; |
118 | 104 | line-height: @multiple-height; |
119 | 105 | background: @border-color-shallow-light; |
120 | - box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.08); | |
106 | + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.12); | |
121 | 107 | } |
122 | 108 | } |
123 | 109 | |
... | ... | @@ -194,11 +180,17 @@ |
194 | 180 | } |
195 | 181 | } |
196 | 182 | |
197 | -.ant-layout-header { | |
183 | +.ant-layout-header:not(.default-layout__tabs) { | |
198 | 184 | height: @header-height; |
199 | 185 | line-height: @header-height; |
200 | 186 | } |
201 | 187 | |
188 | +.ant-layout-header.default-layout__tabs { | |
189 | + height: @multiple-height + 2; | |
190 | + line-height: @multiple-height + 2; | |
191 | + background: @white; | |
192 | +} | |
193 | + | |
202 | 194 | .layout-header { |
203 | 195 | display: flex; |
204 | 196 | height: @header-height; |
... | ... | @@ -351,22 +343,20 @@ |
351 | 343 | } |
352 | 344 | |
353 | 345 | &__menu { |
354 | - // display: flex; | |
355 | 346 | margin-left: 20px; |
356 | 347 | overflow: hidden; |
357 | 348 | align-items: center; |
358 | - // flex-grow: 1; | |
359 | 349 | } |
360 | 350 | |
361 | 351 | &__user-dropdown { |
362 | - height: 52px; | |
352 | + height: @header-height; | |
363 | 353 | padding: 0 0 0 10px; |
364 | 354 | } |
365 | 355 | } |
366 | 356 | |
367 | 357 | .user-dropdown { |
368 | 358 | display: flex; |
369 | - height: 100%; | |
359 | + padding-right: 10px; | |
370 | 360 | font-size: 12px; |
371 | 361 | cursor: pointer; |
372 | 362 | align-items: center; |
... | ... | @@ -374,49 +364,12 @@ |
374 | 364 | img { |
375 | 365 | width: 26px; |
376 | 366 | height: 26px; |
377 | - margin-right: 16px; | |
367 | + margin-right: 12px; | |
378 | 368 | } |
379 | 369 | |
380 | 370 | &__header { |
381 | 371 | border-radius: 50%; |
382 | 372 | } |
383 | - | |
384 | - &__divider { | |
385 | - width: 1px; | |
386 | - height: 30px; | |
387 | - margin-right: 20px; | |
388 | - background: #c6d9ee; | |
389 | - } | |
390 | - | |
391 | - &__exit { | |
392 | - margin-top: -40px; | |
393 | - font-size: 12px; | |
394 | - color: #c6d9ee; | |
395 | - text-align: center; | |
396 | - | |
397 | - > section { | |
398 | - height: 20px; | |
399 | - } | |
400 | - } | |
401 | - | |
402 | - &__info { | |
403 | - display: flex; | |
404 | - margin-right: 12px; | |
405 | - flex-direction: column; | |
406 | - | |
407 | - > section { | |
408 | - line-height: 1.8; | |
409 | - } | |
410 | - } | |
411 | - | |
412 | - &__name { | |
413 | - font-size: 12px; | |
414 | - } | |
415 | - | |
416 | - &__desc { | |
417 | - font-size: 12px; | |
418 | - .text-truncate(); | |
419 | - } | |
420 | 373 | } |
421 | 374 | |
422 | 375 | .layout-breadcrumb { |
... | ... | @@ -425,8 +378,8 @@ |
425 | 378 | } |
426 | 379 | |
427 | 380 | .ant-layout-sider-trigger { |
428 | - height: 30px; | |
429 | - line-height: 30px; | |
381 | + height: 36px; | |
382 | + line-height: 36px; | |
430 | 383 | } |
431 | 384 | |
432 | 385 | .hide-title { | ... | ... |
src/layouts/default/index.tsx
1 | -import { defineComponent, unref, onMounted, computed } from 'vue'; | |
1 | +import { defineComponent, unref, computed } from 'vue'; | |
2 | 2 | import { Layout, BackTop } from 'ant-design-vue'; |
3 | 3 | import LayoutHeader from './LayoutHeader'; |
4 | 4 | |
... | ... | @@ -30,6 +30,7 @@ export default defineComponent({ |
30 | 30 | const getProjectConfigRef = computed(() => { |
31 | 31 | return appStore.getProjectConfig; |
32 | 32 | }); |
33 | + | |
33 | 34 | const getLockMainScrollStateRef = computed(() => { |
34 | 35 | return appStore.getLockMainScrollState; |
35 | 36 | }); |
... | ... | @@ -40,6 +41,7 @@ export default defineComponent({ |
40 | 41 | } = unref(getProjectConfigRef); |
41 | 42 | return show; |
42 | 43 | }); |
44 | + | |
43 | 45 | const isShowMixHeaderRef = computed(() => { |
44 | 46 | const { |
45 | 47 | menuSetting: { type }, |
... | ... | @@ -54,12 +56,6 @@ export default defineComponent({ |
54 | 56 | return show && mode !== MenuModeEnum.HORIZONTAL && !unref(getFullContent); |
55 | 57 | }); |
56 | 58 | |
57 | - // const { currentRoute } = useRouter(); | |
58 | - onMounted(() => { | |
59 | - // Each refresh will request the latest user information, if you don’t need it, you can delete it | |
60 | - // userStore.getUserInfoAction({ userId: userStore.getUserInfoState.userId }); | |
61 | - }); | |
62 | - | |
63 | 59 | // Get project configuration |
64 | 60 | // const { getFullContent } = useFullContent(currentRoute); |
65 | 61 | function getTarget(): any { |
... | ... | @@ -68,6 +64,7 @@ export default defineComponent({ |
68 | 64 | } = unref(getProjectConfigRef); |
69 | 65 | return document.querySelector(`.default-layout__${fixed ? 'main' : 'content'}`); |
70 | 66 | } |
67 | + | |
71 | 68 | return () => { |
72 | 69 | const { getPageLoading, getLockInfo } = appStore; |
73 | 70 | const { |
... | ... | @@ -77,10 +74,11 @@ export default defineComponent({ |
77 | 74 | multiTabsSetting: { show: showTabs }, |
78 | 75 | headerSetting: { fixed }, |
79 | 76 | } = unref(getProjectConfigRef); |
80 | - // const fixedHeaderCls = fixed ? ('fixed' + getLockMainScrollState ? ' lock' : '') : ''; | |
77 | + | |
81 | 78 | const fixedHeaderCls = fixed |
82 | 79 | ? 'fixed' + (unref(getLockMainScrollStateRef) ? ' lock' : '') |
83 | 80 | : ''; |
81 | + | |
84 | 82 | const { isLock } = getLockInfo; |
85 | 83 | return ( |
86 | 84 | <Layout class="default-layout relative"> | ... | ... |
src/layouts/default/multitabs/index.less
1 | 1 | @import (reference) '../../../design/index.less'; |
2 | 2 | |
3 | 3 | .multiple-tabs { |
4 | - box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); | |
5 | - | |
6 | 4 | .ant-tabs-small { |
7 | 5 | height: @multiple-height; |
8 | 6 | } |
... | ... | @@ -13,7 +11,7 @@ |
13 | 11 | margin: 0; |
14 | 12 | background: @white; |
15 | 13 | border: 0; |
16 | - box-shadow: 0 4px 26px 1px rgba(0, 0, 0, 0.08); | |
14 | + box-shadow: none; | |
17 | 15 | |
18 | 16 | .ant-tabs-nav-container { |
19 | 17 | height: @multiple-height; |
... | ... | @@ -22,17 +20,26 @@ |
22 | 20 | |
23 | 21 | .ant-tabs-tab { |
24 | 22 | height: calc(@multiple-height - 2px); |
25 | - font-size: 14px; | |
26 | 23 | line-height: calc(@multiple-height - 2px); |
27 | 24 | color: @text-color-call-out; |
28 | 25 | background: @white; |
29 | - border: 1px solid darken(@border-color-light, 6%); | |
30 | - border-radius: 2px 2px 0 0; | |
26 | + border: 1px solid darken(@border-color-light, 8%); | |
27 | + border-radius: none !important; | |
31 | 28 | transition: none; |
32 | 29 | |
33 | 30 | .ant-tabs-close-x { |
34 | - // display: none; | |
31 | + width: 12px; | |
32 | + height: 12px; | |
33 | + font-size: 12px; | |
35 | 34 | color: inherit; |
35 | + transition: none; | |
36 | + | |
37 | + &:hover { | |
38 | + svg { | |
39 | + width: 0.8em; | |
40 | + transition: all 0.1s; | |
41 | + } | |
42 | + } | |
36 | 43 | } |
37 | 44 | |
38 | 45 | &:hover { |
... | ... | @@ -50,37 +57,12 @@ |
50 | 57 | svg { |
51 | 58 | fill: @text-color-base; |
52 | 59 | } |
53 | - | |
54 | - &::before { | |
55 | - position: absolute; | |
56 | - top: -2px; | |
57 | - right: 0; | |
58 | - left: 0; | |
59 | - height: 4px; | |
60 | - background-color: @primary-color; | |
61 | - border-radius: 16px 6px 0 0; | |
62 | - content: ''; | |
63 | - transform: scaleX(0); | |
64 | - transform-origin: bottom right; | |
65 | - } | |
66 | - | |
67 | - &:hover::before { | |
68 | - transform: scaleX(1); | |
69 | - transition: transform 0.3s ease; | |
70 | - transform-origin: bottom left; | |
71 | - } | |
72 | 60 | } |
73 | 61 | |
74 | 62 | .ant-tabs-tab-active { |
75 | - height: calc(@multiple-height - 3px); | |
76 | 63 | color: @white; |
77 | - background: linear-gradient( | |
78 | - 118deg, | |
79 | - rgba(@primary-color, 0.8), | |
80 | - rgba(@primary-color, 1) | |
81 | - ) !important; | |
64 | + background: fade(@primary-color, 100%); | |
82 | 65 | border: 0; |
83 | - box-shadow: 0 0 6px 1px rgba(@primary-color, 0.7); | |
84 | 66 | |
85 | 67 | &::before { |
86 | 68 | display: none; |
... | ... | @@ -88,6 +70,7 @@ |
88 | 70 | |
89 | 71 | svg { |
90 | 72 | fill: @white; |
73 | + width: 0.7em; | |
91 | 74 | } |
92 | 75 | } |
93 | 76 | } |
... | ... | @@ -95,12 +78,6 @@ |
95 | 78 | .ant-tabs-nav > div:nth-child(1) { |
96 | 79 | padding: 0 10px; |
97 | 80 | } |
98 | - | |
99 | - .ant-tabs-tab-prev, | |
100 | - .ant-tabs-tab-next { | |
101 | - color: @border-color-dark; | |
102 | - background: @white; | |
103 | - } | |
104 | 81 | } |
105 | 82 | |
106 | 83 | .ant-tabs-tab:not(.ant-tabs-tab-active) { |
... | ... | @@ -108,20 +85,19 @@ |
108 | 85 | font-size: 12px; |
109 | 86 | |
110 | 87 | svg { |
111 | - width: 0.8em; | |
112 | - } | |
113 | - } | |
114 | - | |
115 | - &:hover { | |
116 | - .anticon-close { | |
117 | - color: @white; | |
88 | + width: 0.6em; | |
118 | 89 | } |
119 | 90 | } |
120 | 91 | } |
121 | 92 | } |
122 | 93 | |
123 | 94 | .ant-tabs-extra-content { |
124 | - line-height: @multiple-height; | |
95 | + margin-top: 2px; | |
96 | + line-height: @multiple-height !important; | |
97 | +} | |
98 | + | |
99 | +.ant-dropdown-trigger { | |
100 | + display: inline-flex; | |
125 | 101 | } |
126 | 102 | |
127 | 103 | .multiple-tabs-content { |
... | ... | @@ -133,7 +109,7 @@ |
133 | 109 | color: @primary-color; |
134 | 110 | text-align: center; |
135 | 111 | cursor: pointer; |
136 | - box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); | |
112 | + // box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); | |
137 | 113 | |
138 | 114 | span[role='img'] { |
139 | 115 | transform: rotate(90deg); |
... | ... | @@ -143,8 +119,10 @@ |
143 | 119 | &__content { |
144 | 120 | display: inline-block; |
145 | 121 | width: 100%; |
146 | - padding-left: 10px; | |
122 | + height: @multiple-height - 2; | |
123 | + padding-left: 0; | |
147 | 124 | margin-left: -10px; |
125 | + font-size: 12px; | |
148 | 126 | cursor: pointer; |
149 | 127 | user-select: none; |
150 | 128 | } | ... | ... |
src/layouts/default/multitabs/index.tsx
src/layouts/default/setting/index.vue
... | ... | @@ -28,13 +28,21 @@ |
28 | 28 | |
29 | 29 | .setting-button { |
30 | 30 | position: absolute; |
31 | + top: 45%; | |
32 | + right: 0; | |
31 | 33 | z-index: 10; |
32 | 34 | display: flex; |
33 | - // padding: 10px; | |
35 | + padding: 10px; | |
34 | 36 | color: @white; |
35 | 37 | cursor: pointer; |
36 | 38 | background: @primary-color; |
39 | + border-radius: 6px 0 0 6px; | |
37 | 40 | justify-content: center; |
38 | 41 | align-items: center; |
42 | + | |
43 | + svg { | |
44 | + width: 1em; | |
45 | + height: 1em; | |
46 | + } | |
39 | 47 | } |
40 | 48 | </style> | ... | ... |
src/layouts/iframe/index.vue
... | ... | @@ -9,14 +9,15 @@ |
9 | 9 | </template> |
10 | 10 | <script lang="ts"> |
11 | 11 | import { defineComponent } from 'vue'; |
12 | - import { useFrameKeepAlive } from './useFrameKeepAlive'; | |
13 | 12 | import FramePage from '/@/views/sys/iframe/index.vue'; |
13 | + | |
14 | + import { useFrameKeepAlive } from './useFrameKeepAlive'; | |
15 | + | |
14 | 16 | export default defineComponent({ |
15 | 17 | name: 'FrameLayout', |
16 | 18 | components: { FramePage }, |
17 | 19 | setup() { |
18 | - const { hasRenderFrame, showIframe, getFramePages } = useFrameKeepAlive(); | |
19 | - return { hasRenderFrame, showIframe, getFramePages }; | |
20 | + return { ...useFrameKeepAlive() }; | |
20 | 21 | }, |
21 | 22 | }); |
22 | 23 | </script> | ... | ... |
src/settings/projectSetting.ts
... | ... | @@ -55,7 +55,7 @@ const setting: ProjectConfig = { |
55 | 55 | // 是否显示搜索框 |
56 | 56 | showSearch: true, |
57 | 57 | // 菜单宽度 |
58 | - menuWidth: 180, | |
58 | + menuWidth: 200, | |
59 | 59 | // 菜单模式 |
60 | 60 | mode: MenuModeEnum.INLINE, |
61 | 61 | // 菜单类型 |
... | ... | @@ -65,7 +65,7 @@ const setting: ProjectConfig = { |
65 | 65 | // 分割菜单 |
66 | 66 | split: false, |
67 | 67 | // 顶部菜单布局 |
68 | - topMenuAlign: 'start', | |
68 | + topMenuAlign: 'center', | |
69 | 69 | }, |
70 | 70 | // 消息配置 |
71 | 71 | messageSetting: { |
... | ... | @@ -83,7 +83,7 @@ const setting: ProjectConfig = { |
83 | 83 | // 开启快速操作 |
84 | 84 | showQuick: true, |
85 | 85 | // 显示icon |
86 | - showIcon: true, | |
86 | + showIcon: false, | |
87 | 87 | // 标签页缓存最大数量 |
88 | 88 | max: 12, |
89 | 89 | }, | ... | ... |