xto-fronted 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Layout/Sidebar.vue.d.ts +1 -8
- package/dist/index-B6DTsC6l.js +1715 -0
- package/dist/index-B7etKk33.js +372 -0
- package/dist/index-BBqvHkzE.js +475 -0
- package/dist/index-BGmUwemj.js +372 -0
- package/dist/index-C0VN9nFF.js +142 -0
- package/dist/index-Cb-SxHJp.js +345 -0
- package/dist/index-CeCysOnl.js +345 -0
- package/dist/index-D7TZamyY.js +1664 -0
- package/dist/index-DnJ481u1.js +475 -0
- package/dist/index-YDlNLFVk.js +142 -0
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/Layout/Header.vue +327 -188
- package/src/components/Layout/Sidebar.vue +25 -190
- package/src/components/Layout/index.vue +8 -180
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { computed } from 'vue'
|
|
3
3
|
import { useRoute, useRouter } from 'vue-router'
|
|
4
4
|
import { useMenuStore } from '@/stores/menu'
|
|
5
5
|
import { useUserStore } from '@/stores/user'
|
|
@@ -7,19 +7,7 @@ import { useAuthStore } from '@/stores/auth'
|
|
|
7
7
|
import { useAppStore } from '@/stores/app'
|
|
8
8
|
import { Menu, MenuItem, SubMenu } from '@xto/navigation'
|
|
9
9
|
import { Button } from '@xto/base'
|
|
10
|
-
import {
|
|
11
|
-
import type { MenuItem as MenuItemType } from '@/types/api'
|
|
12
|
-
|
|
13
|
-
const props = withDefaults(
|
|
14
|
-
defineProps<{
|
|
15
|
-
mode?: 'vertical' | 'horizontal'
|
|
16
|
-
showLogo?: boolean
|
|
17
|
-
}>(),
|
|
18
|
-
{
|
|
19
|
-
mode: 'vertical',
|
|
20
|
-
showLogo: true
|
|
21
|
-
}
|
|
22
|
-
)
|
|
10
|
+
import { Icon } from '@xto/base'
|
|
23
11
|
|
|
24
12
|
const route = useRoute()
|
|
25
13
|
const router = useRouter()
|
|
@@ -28,7 +16,6 @@ const userStore = useUserStore()
|
|
|
28
16
|
const authStore = useAuthStore()
|
|
29
17
|
const appStore = useAppStore()
|
|
30
18
|
|
|
31
|
-
const searchKeyword = ref('')
|
|
32
19
|
const isCollapsed = computed(() => appStore.isCollapsed)
|
|
33
20
|
const activeMenu = computed(() => route.path)
|
|
34
21
|
|
|
@@ -37,63 +24,13 @@ const menuBgColor = computed(() => appStore.isDark ? '#1d1e1f' : '#fff')
|
|
|
37
24
|
const menuTextColor = computed(() => appStore.isDark ? '#cfd3dc' : '#303133')
|
|
38
25
|
const menuActiveTextColor = computed(() => '#409eff')
|
|
39
26
|
|
|
40
|
-
// 扁平化菜单用于搜索
|
|
41
|
-
const flattenMenus = (menus: MenuItemType[], parentTitle = ''): (MenuItemType & { parentTitle: string })[] => {
|
|
42
|
-
const result: (MenuItemType & { parentTitle: string })[] = []
|
|
43
|
-
menus.forEach(menu => {
|
|
44
|
-
if (menu.children && menu.children.length > 0) {
|
|
45
|
-
result.push(...flattenMenus(menu.children, menu.title))
|
|
46
|
-
} else {
|
|
47
|
-
result.push({ ...menu, parentTitle })
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
return result
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 搜索结果
|
|
54
|
-
const searchResults = computed(() => {
|
|
55
|
-
if (!searchKeyword.value.trim()) return []
|
|
56
|
-
const flatMenus = flattenMenus(menuStore.menuList)
|
|
57
|
-
return flatMenus.filter(menu =>
|
|
58
|
-
menu.title.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
|
59
|
-
)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
// 过滤后的菜单列表
|
|
63
|
-
const filteredMenuList = computed(() => {
|
|
64
|
-
if (!searchKeyword.value.trim()) return menuStore.menuList
|
|
65
|
-
|
|
66
|
-
return menuStore.menuList.map(menu => {
|
|
67
|
-
if (menu.children && menu.children.length > 0) {
|
|
68
|
-
const filteredChildren = menu.children.filter(child =>
|
|
69
|
-
child.title.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
|
70
|
-
)
|
|
71
|
-
if (filteredChildren.length > 0) {
|
|
72
|
-
return { ...menu, children: filteredChildren }
|
|
73
|
-
}
|
|
74
|
-
return null
|
|
75
|
-
}
|
|
76
|
-
if (menu.title.toLowerCase().includes(searchKeyword.value.toLowerCase())) {
|
|
77
|
-
return menu
|
|
78
|
-
}
|
|
79
|
-
return null
|
|
80
|
-
}).filter(Boolean) as MenuItemType[]
|
|
81
|
-
})
|
|
82
|
-
|
|
83
27
|
// 菜单选择
|
|
84
28
|
const handleMenuSelect = (index: string) => {
|
|
85
29
|
if (index && index !== route.path) {
|
|
86
30
|
router.push(index)
|
|
87
|
-
searchKeyword.value = ''
|
|
88
31
|
}
|
|
89
32
|
}
|
|
90
33
|
|
|
91
|
-
// 搜索结果点击
|
|
92
|
-
const handleSearchItemClick = (path: string) => {
|
|
93
|
-
router.push(path)
|
|
94
|
-
searchKeyword.value = ''
|
|
95
|
-
}
|
|
96
|
-
|
|
97
34
|
// 退出登录
|
|
98
35
|
const handleLogout = () => {
|
|
99
36
|
authStore.logout()
|
|
@@ -102,65 +39,33 @@ const handleLogout = () => {
|
|
|
102
39
|
router.push('/login')
|
|
103
40
|
}
|
|
104
41
|
|
|
105
|
-
//
|
|
106
|
-
const getMenuIcon = (icon?: string) => {
|
|
42
|
+
// 获取菜单图标名称
|
|
43
|
+
const getMenuIcon = (icon?: string): string => {
|
|
107
44
|
const iconMap: Record<string, string> = {
|
|
108
|
-
dashboard: '
|
|
109
|
-
system: '
|
|
110
|
-
user: '
|
|
111
|
-
role: '
|
|
112
|
-
menu: '
|
|
113
|
-
setting: '
|
|
114
|
-
}
|
|
115
|
-
return iconMap[icon || ''] || '
|
|
45
|
+
dashboard: 'dashboard',
|
|
46
|
+
system: 'system',
|
|
47
|
+
user: 'user',
|
|
48
|
+
role: 'role',
|
|
49
|
+
menu: 'list',
|
|
50
|
+
setting: 'setting'
|
|
51
|
+
}
|
|
52
|
+
return iconMap[icon || ''] || 'file'
|
|
116
53
|
}
|
|
117
|
-
|
|
118
|
-
const isVertical = computed(() => props.mode === 'vertical')
|
|
119
|
-
const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
120
54
|
</script>
|
|
121
55
|
|
|
122
56
|
<template>
|
|
123
|
-
<div class="sidebar" :class="
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
{ 'sidebar--horizontal': isHorizontal }
|
|
127
|
-
]">
|
|
128
|
-
<!-- Logo(仅垂直模式显示) -->
|
|
129
|
-
<div v-if="showLogo && isVertical" class="sidebar__logo">
|
|
57
|
+
<div class="sidebar" :class="{ 'sidebar--collapsed': isCollapsed }">
|
|
58
|
+
<!-- Logo -->
|
|
59
|
+
<div class="sidebar__logo">
|
|
130
60
|
<img src="/vite.svg" alt="Logo" class="sidebar__logo-img" />
|
|
131
61
|
<span v-show="!isCollapsed" class="sidebar__logo-text">{{ appStore.appName }}</span>
|
|
132
62
|
</div>
|
|
133
63
|
|
|
134
|
-
<!-- 搜索框(仅垂直模式显示) -->
|
|
135
|
-
<div v-if="isVertical && !isCollapsed" class="sidebar__search">
|
|
136
|
-
<Input
|
|
137
|
-
v-model="searchKeyword"
|
|
138
|
-
placeholder="搜索菜单..."
|
|
139
|
-
size="small"
|
|
140
|
-
clearable
|
|
141
|
-
/>
|
|
142
|
-
<!-- 搜索结果 -->
|
|
143
|
-
<div v-if="searchResults.length > 0" class="sidebar__search-results">
|
|
144
|
-
<div
|
|
145
|
-
v-for="item in searchResults"
|
|
146
|
-
:key="item.path"
|
|
147
|
-
class="sidebar__search-item"
|
|
148
|
-
@click="handleSearchItemClick(item.path)"
|
|
149
|
-
>
|
|
150
|
-
<span class="menu-icon">{{ getMenuIcon(item.icon) }}</span>
|
|
151
|
-
<div class="sidebar__search-item-info">
|
|
152
|
-
<span class="sidebar__search-item-title">{{ item.title }}</span>
|
|
153
|
-
<span v-if="item.parentTitle" class="sidebar__search-item-parent">{{ item.parentTitle }}</span>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
|
|
159
64
|
<!-- 菜单 -->
|
|
160
65
|
<Menu
|
|
161
66
|
:default-active="activeMenu"
|
|
162
|
-
|
|
163
|
-
:collapse="isCollapsed
|
|
67
|
+
mode="vertical"
|
|
68
|
+
:collapse="isCollapsed"
|
|
164
69
|
:collapse-transition="false"
|
|
165
70
|
:background-color="menuBgColor"
|
|
166
71
|
:text-color="menuTextColor"
|
|
@@ -168,11 +73,11 @@ const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
|
168
73
|
class="sidebar__menu"
|
|
169
74
|
@select="handleMenuSelect"
|
|
170
75
|
>
|
|
171
|
-
<template v-for="menu in
|
|
76
|
+
<template v-for="menu in menuStore.menuList" :key="menu.path">
|
|
172
77
|
<!-- 有子菜单 -->
|
|
173
78
|
<SubMenu v-if="menu.children && menu.children.length > 0" :index="menu.path">
|
|
174
79
|
<template #title>
|
|
175
|
-
<
|
|
80
|
+
<Icon :name="getMenuIcon(menu.icon)" :size="16" />
|
|
176
81
|
<span>{{ menu.title }}</span>
|
|
177
82
|
</template>
|
|
178
83
|
<MenuItem
|
|
@@ -180,20 +85,20 @@ const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
|
180
85
|
:key="child.path"
|
|
181
86
|
:index="child.path"
|
|
182
87
|
>
|
|
183
|
-
<
|
|
88
|
+
<Icon :name="getMenuIcon(child.icon)" :size="16" />
|
|
184
89
|
<span>{{ child.title }}</span>
|
|
185
90
|
</MenuItem>
|
|
186
91
|
</SubMenu>
|
|
187
92
|
<!-- 无子菜单 -->
|
|
188
93
|
<MenuItem v-else :index="menu.path">
|
|
189
|
-
<
|
|
94
|
+
<Icon :name="getMenuIcon(menu.icon)" :size="16" />
|
|
190
95
|
<span>{{ menu.title }}</span>
|
|
191
96
|
</MenuItem>
|
|
192
97
|
</template>
|
|
193
98
|
</Menu>
|
|
194
99
|
|
|
195
|
-
<!--
|
|
196
|
-
<div v-if="
|
|
100
|
+
<!-- 用户信息 -->
|
|
101
|
+
<div v-if="!isCollapsed" class="sidebar__user">
|
|
197
102
|
<div class="sidebar__user-info">
|
|
198
103
|
<span class="sidebar__user-name">{{ userStore.nickname }}</span>
|
|
199
104
|
<span class="sidebar__user-role">{{ userStore.roles?.join(', ') }}</span>
|
|
@@ -209,26 +114,9 @@ const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
|
209
114
|
display: flex;
|
|
210
115
|
flex-direction: column;
|
|
211
116
|
background-color: var(--bg-color);
|
|
117
|
+
border-right: 1px solid var(--color-border-lighter);
|
|
212
118
|
|
|
213
|
-
|
|
214
|
-
&--vertical {
|
|
215
|
-
border-right: 1px solid var(--color-border-lighter);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 水平模式
|
|
219
|
-
&--horizontal {
|
|
220
|
-
flex-direction: row;
|
|
221
|
-
border: none;
|
|
222
|
-
background-color: transparent;
|
|
223
|
-
|
|
224
|
-
.sidebar__menu {
|
|
225
|
-
border: none;
|
|
226
|
-
background-color: transparent;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// 折叠状态
|
|
231
|
-
&--collapsed.sidebar--vertical {
|
|
119
|
+
&--collapsed {
|
|
232
120
|
.sidebar__logo {
|
|
233
121
|
justify-content: center;
|
|
234
122
|
padding: 0;
|
|
@@ -255,55 +143,6 @@ const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
|
255
143
|
color: var(--color-primary);
|
|
256
144
|
}
|
|
257
145
|
|
|
258
|
-
&__search {
|
|
259
|
-
padding: 10px;
|
|
260
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
261
|
-
position: relative;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
&__search-results {
|
|
265
|
-
position: absolute;
|
|
266
|
-
top: 100%;
|
|
267
|
-
left: 0;
|
|
268
|
-
right: 0;
|
|
269
|
-
background-color: var(--bg-color);
|
|
270
|
-
border: 1px solid var(--color-border-lighter);
|
|
271
|
-
border-radius: var(--border-radius-base);
|
|
272
|
-
box-shadow: var(--box-shadow);
|
|
273
|
-
max-height: 300px;
|
|
274
|
-
overflow-y: auto;
|
|
275
|
-
z-index: 100;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
&__search-item {
|
|
279
|
-
display: flex;
|
|
280
|
-
align-items: center;
|
|
281
|
-
gap: 10px;
|
|
282
|
-
padding: 10px 12px;
|
|
283
|
-
cursor: pointer;
|
|
284
|
-
transition: background-color 0.2s;
|
|
285
|
-
|
|
286
|
-
&:hover {
|
|
287
|
-
background-color: var(--color-fill);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
&-info {
|
|
291
|
-
display: flex;
|
|
292
|
-
flex-direction: column;
|
|
293
|
-
gap: 2px;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
&-title {
|
|
297
|
-
font-size: 14px;
|
|
298
|
-
color: var(--color-text-primary);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
&-parent {
|
|
302
|
-
font-size: 12px;
|
|
303
|
-
color: var(--color-text-secondary);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
146
|
&__menu {
|
|
308
147
|
flex: 1;
|
|
309
148
|
border-right: none;
|
|
@@ -334,8 +173,4 @@ const isHorizontal = computed(() => props.mode === 'horizontal')
|
|
|
334
173
|
color: var(--color-text-secondary);
|
|
335
174
|
}
|
|
336
175
|
}
|
|
337
|
-
|
|
338
|
-
.menu-icon {
|
|
339
|
-
margin-right: 8px;
|
|
340
|
-
}
|
|
341
176
|
</style>
|
|
@@ -9,73 +9,21 @@ const appStore = useAppStore()
|
|
|
9
9
|
const sidebarWidth = computed(() =>
|
|
10
10
|
appStore.isCollapsed ? '64px' : '210px'
|
|
11
11
|
)
|
|
12
|
-
|
|
13
|
-
const layoutMode = computed(() => appStore.layout)
|
|
14
|
-
|
|
15
|
-
const isSidebarMode = computed(() => layoutMode.value === 'sidebar')
|
|
16
|
-
const isTopMode = computed(() => layoutMode.value === 'top')
|
|
17
|
-
const isMixMode = computed(() => layoutMode.value === 'mix')
|
|
18
12
|
</script>
|
|
19
13
|
|
|
20
14
|
<template>
|
|
21
|
-
<div class="layout"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
</div>
|
|
29
|
-
<Sidebar class="layout__top-menu" mode="horizontal" />
|
|
30
|
-
<div class="layout__header-right">
|
|
31
|
-
<Header :show-breadcrumb="false" :show-collapse="false" />
|
|
32
|
-
</div>
|
|
15
|
+
<div class="layout">
|
|
16
|
+
<aside class="layout__aside" :style="{ width: sidebarWidth }">
|
|
17
|
+
<Sidebar />
|
|
18
|
+
</aside>
|
|
19
|
+
<div class="layout__main">
|
|
20
|
+
<header class="layout__header">
|
|
21
|
+
<Header />
|
|
33
22
|
</header>
|
|
34
23
|
<main class="layout__content">
|
|
35
24
|
<router-view />
|
|
36
25
|
</main>
|
|
37
|
-
</
|
|
38
|
-
|
|
39
|
-
<!-- 混合模式:顶部导航 + 左侧菜单 -->
|
|
40
|
-
<template v-else-if="isMixMode">
|
|
41
|
-
<header class="layout__header-mix">
|
|
42
|
-
<div class="layout__header-left">
|
|
43
|
-
<div class="layout__collapse" @click="appStore.toggleCollapse">
|
|
44
|
-
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
|
|
45
|
-
<path v-if="appStore.isCollapsed" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
|
|
46
|
-
<path v-else d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/>
|
|
47
|
-
</svg>
|
|
48
|
-
</div>
|
|
49
|
-
<Sidebar class="layout__top-menu" mode="horizontal" />
|
|
50
|
-
</div>
|
|
51
|
-
<div class="layout__header-right">
|
|
52
|
-
<Header :show-breadcrumb="false" :show-collapse="false" />
|
|
53
|
-
</div>
|
|
54
|
-
</header>
|
|
55
|
-
<div class="layout__body">
|
|
56
|
-
<aside class="layout__aside" :style="{ width: sidebarWidth }">
|
|
57
|
-
<Sidebar mode="vertical" :show-logo="false" />
|
|
58
|
-
</aside>
|
|
59
|
-
<main class="layout__content">
|
|
60
|
-
<router-view />
|
|
61
|
-
</main>
|
|
62
|
-
</div>
|
|
63
|
-
</template>
|
|
64
|
-
|
|
65
|
-
<!-- 侧边栏模式:左侧菜单 + 顶部 -->
|
|
66
|
-
<template v-else-if="isSidebarMode">
|
|
67
|
-
<aside class="layout__aside" :style="{ width: sidebarWidth }">
|
|
68
|
-
<Sidebar />
|
|
69
|
-
</aside>
|
|
70
|
-
<div class="layout__main">
|
|
71
|
-
<header class="layout__header">
|
|
72
|
-
<Header />
|
|
73
|
-
</header>
|
|
74
|
-
<main class="layout__content">
|
|
75
|
-
<router-view />
|
|
76
|
-
</main>
|
|
77
|
-
</div>
|
|
78
|
-
</template>
|
|
26
|
+
</div>
|
|
79
27
|
</div>
|
|
80
28
|
</template>
|
|
81
29
|
|
|
@@ -85,126 +33,6 @@ const isMixMode = computed(() => layoutMode.value === 'mix')
|
|
|
85
33
|
width: 100%;
|
|
86
34
|
height: 100%;
|
|
87
35
|
|
|
88
|
-
// 侧边栏模式
|
|
89
|
-
&--sidebar {
|
|
90
|
-
flex-direction: row;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// 顶部模式
|
|
94
|
-
&--top {
|
|
95
|
-
flex-direction: column;
|
|
96
|
-
|
|
97
|
-
.layout__header-top {
|
|
98
|
-
height: 50px;
|
|
99
|
-
background-color: var(--bg-color);
|
|
100
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
101
|
-
display: flex;
|
|
102
|
-
align-items: center;
|
|
103
|
-
padding: 0 20px;
|
|
104
|
-
gap: 20px;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.layout__header-logo {
|
|
108
|
-
display: flex;
|
|
109
|
-
align-items: center;
|
|
110
|
-
gap: 10px;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.layout__logo-img {
|
|
114
|
-
width: 32px;
|
|
115
|
-
height: 32px;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.layout__logo-text {
|
|
119
|
-
font-size: 16px;
|
|
120
|
-
font-weight: 600;
|
|
121
|
-
color: var(--color-primary);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.layout__top-menu {
|
|
125
|
-
flex: 1;
|
|
126
|
-
border: none;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.layout__header-right {
|
|
130
|
-
display: flex;
|
|
131
|
-
align-items: center;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.layout__content {
|
|
135
|
-
flex: 1;
|
|
136
|
-
overflow: auto;
|
|
137
|
-
background-color: var(--bg-color-page);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 混合模式
|
|
142
|
-
&--mix {
|
|
143
|
-
flex-direction: column;
|
|
144
|
-
|
|
145
|
-
.layout__header-mix {
|
|
146
|
-
height: 50px;
|
|
147
|
-
background-color: var(--bg-color);
|
|
148
|
-
border-bottom: 1px solid var(--color-border-lighter);
|
|
149
|
-
display: flex;
|
|
150
|
-
align-items: center;
|
|
151
|
-
justify-content: space-between;
|
|
152
|
-
padding: 0 20px;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.layout__header-left {
|
|
156
|
-
display: flex;
|
|
157
|
-
align-items: center;
|
|
158
|
-
gap: 15px;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.layout__collapse {
|
|
162
|
-
width: 24px;
|
|
163
|
-
height: 24px;
|
|
164
|
-
display: flex;
|
|
165
|
-
align-items: center;
|
|
166
|
-
justify-content: center;
|
|
167
|
-
cursor: pointer;
|
|
168
|
-
color: var(--color-text-regular);
|
|
169
|
-
transition: color 0.2s;
|
|
170
|
-
|
|
171
|
-
&:hover {
|
|
172
|
-
color: var(--color-primary);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.layout__top-menu {
|
|
177
|
-
border: none;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.layout__header-right {
|
|
181
|
-
display: flex;
|
|
182
|
-
align-items: center;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
.layout__body {
|
|
186
|
-
flex: 1;
|
|
187
|
-
display: flex;
|
|
188
|
-
overflow: hidden;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.layout__aside {
|
|
192
|
-
transition: width 0.3s;
|
|
193
|
-
overflow: hidden;
|
|
194
|
-
flex-shrink: 0;
|
|
195
|
-
height: 100%;
|
|
196
|
-
background-color: var(--bg-color);
|
|
197
|
-
border-right: 1px solid var(--color-border-lighter);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.layout__content {
|
|
201
|
-
flex: 1;
|
|
202
|
-
overflow: auto;
|
|
203
|
-
background-color: var(--bg-color-page);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// 通用样式
|
|
208
36
|
&__aside {
|
|
209
37
|
transition: width 0.3s;
|
|
210
38
|
overflow: hidden;
|