11<template >
2- <div class =" app-container" >
3- <div class =" sidebar" >
2+ <div class =" app-container" :class = " { 'app-topbar-container': topLayout } " >
3+ <div class =" main-menu " :class = " { 'main-menu- sidebar': !topLayout, 'main-menu-topbar': topLayout } " >
44 <div class =" logo" >SQLBot</div >
55
6- <div class =" workspace-area" >
6+ <div v-if = " !topLayout || !showSubmenu " : class =" { ' workspace-area': !topLayout, 'topbar-workspace-area': topLayout } " >
77 <el-select
88 v-model =" workspace"
99 placeholder =" Select"
2626 </el-select >
2727 </div >
2828 <el-menu
29+ v-if =" !topLayout || !showSubmenu"
2930 :default-active =" activeMenu"
30- class =" menu-container" >
31-
31+ class =" menu-container"
32+ :mode =" topLayout ? 'horizontal' : 'vertical'"
33+ >
3234 <el-menu-item v-for =" item in routerList" :key =" item.path" :index =" item.path" @click =" menuSelect" >
3335 <el-icon v-if =" item.meta.icon" >
3436 <component :is =" resolveIcon(item.meta.icon)" />
3537 </el-icon >
3638 <span >{{ item.meta.title }}</span >
3739 </el-menu-item >
38-
3940 </el-menu >
41+
42+ <div v-else class =" top-bar-title" >
43+ <span class =" split" />
44+ <span >System manage</span >
45+ </div >
46+
47+
48+ <div class =" main-topbar-right" v-if =" topLayout" >
49+
50+ <div class =" top-back-area" v-if =" showSubmenu" >
51+ <el-button type =" primary" text =" primary" @click =" backMain" >
52+ <el-icon class =" el-icon--right" ><ArrowLeftBold /></el-icon >Back
53+ </el-button >
54+ </div >
55+
56+ <el-tooltip content =" System manage" placement =" bottom" v-else >
57+ <div class =" header-icon-btn" @click =" toSystem" >
58+ <el-icon ><iconsystem /></el-icon >
59+ <!-- <span>System manage</span> -->
60+ </div >
61+ </el-tooltip >
62+
63+ <el-dropdown trigger =" click" >
64+ <div class =" user-info" >
65+ <el-avatar size =" small" >{{ name?.charAt(0) }}</el-avatar >
66+ <span class =" user-name" >{{ name }}</span >
67+ </div >
68+ <template #dropdown >
69+ <el-dropdown-menu >
70+ <el-dropdown-item @click =" switchLayout" >Switch Layout</el-dropdown-item >
71+ <el-dropdown-item @click =" logout" >Logout</el-dropdown-item >
72+ </el-dropdown-menu >
73+ </template >
74+ </el-dropdown >
75+ </div >
4076 </div >
4177
42- <div class =" main-content" >
43- <div class =" header-container" >
78+ <div class =" main-content" :class = " {'main-conntent-withbar': topLayout} " >
79+ <div class =" header-container" v-if = " !topLayout " >
4480 <div class =" header" >
4581 <h1 >{{ currentPageTitle }}</h1 >
4682 <div class =" header-actions" >
5086 <span >System manage</span >
5187 </div >
5288 </el-tooltip >
53- <!-- <el-tooltip content="Help" placement="bottom">
54- <div class="header-icon-btn">
55- <el-icon><question-filled /></el-icon>
56- <span>Help</span>
57- </div>
58- </el-tooltip>
59- <el-tooltip content="Notice" placement="bottom">
60- <div class="header-icon-btn">
61- <el-icon><BellFilled /></el-icon>
62- <span>Notice</span>
63- </div>
64- </el-tooltip> -->
89+
6590 <el-dropdown trigger =" click" >
6691 <div class =" user-info" >
6792 <el-avatar size =" small" >{{ name?.charAt(0) }}</el-avatar >
6893 <span class =" user-name" >{{ name }}</span >
6994 </div >
7095 <template #dropdown >
7196 <el-dropdown-menu >
97+ <el-dropdown-item @click =" switchLayout" >Switch Layout</el-dropdown-item >
7298 <el-dropdown-item @click =" logout" >Logout</el-dropdown-item >
7399 </el-dropdown-menu >
74100 </template >
77103 </div >
78104 </div >
79105
80- <div v-if =" sysRouterList.length && showHead " class =" sys-setting -container" >
106+ <div v-if =" sysRouterList.length && showSubmenu " class =" sub-menu -container" >
81107 <el-menu
82108 :default-active =" activeMenu"
83109 class =" el-menu-demo"
84- mode =" horizontal"
110+ : mode =" !topLayout ? ' horizontal' : 'vertical' "
85111 >
86112 <el-menu-item v-for =" item in sysRouterList" :key =" item.path" :index =" item.path" @click =" menuSelect" >
87113 <el-icon v-if =" item.meta.icon" >
92118 </el-menu >
93119 </div >
94120
95- <div v-if =" sysRouterList.length && showHead " class =" sys-page-content" >
121+ <div v-if =" sysRouterList.length && showSubmenu " class =" sys-page-content" >
96122 <div class =" sys-inner-container" >
97123 <router-view />
98124 </div >
105131</template >
106132
107133<script lang="ts" setup>
108- import { ref , computed } from ' vue'
134+ import { ref , computed , onMounted } from ' vue'
109135import { useRouter , useRoute } from ' vue-router'
110136import { useUserStore } from ' @/stores/user'
111137import folder from ' @/assets/svg/folder.svg'
@@ -114,11 +140,12 @@ import dashboard from '@/assets/svg/dashboard.svg'
114140import chat from ' @/assets/svg/chat.svg'
115141import iconsetting from ' @/assets/svg/setting.svg'
116142import iconsystem from ' @/assets/svg/system.svg'
117- /* import {
118- QuestionFilled,
119- BellFilled
120- } from '@element-plus/icons-vue' */
121-
143+ import icon_user from ' @/assets/svg/icon_user.svg'
144+ import icon_ai from ' @/assets/svg/icon_ai.svg'
145+ import { ArrowLeftBold } from ' @element-plus/icons-vue'
146+ import { useCache } from ' @/utils/useCache'
147+ const { wsCache } = useCache ()
148+ const topLayout = ref (false )
122149const router = useRouter ()
123150const route = useRoute ()
124151const userStore = useUserStore ()
@@ -134,7 +161,7 @@ const sysRouterList = computed(() => {
134161 return router .getRoutes ().filter (route => route .path .includes (' /system' ))
135162})
136163
137- const showHead = computed (() => {
164+ const showSubmenu = computed (() => {
138165 return route .path .includes (' /system' )
139166})
140167const workspace = ref (' 1' )
@@ -154,7 +181,9 @@ const resolveIcon = (iconName: any) => {
154181 ' ds' : ds ,
155182 ' dashboard' : dashboard ,
156183 ' chat' : chat ,
157- ' setting' : iconsetting
184+ ' setting' : iconsetting ,
185+ ' icon_user' : icon_user ,
186+ ' icon_ai' : icon_ai ,
158187 }
159188 return typeof icons [iconName ] === ' function' ? icons [iconName ]() : icons [iconName ]
160189}
@@ -169,21 +198,30 @@ const logout = () => {
169198const toSystem = () => {
170199 router .push (' /system' )
171200}
201+ const backMain = () => {
202+ router .push (' /' )
203+ }
204+ const switchLayout = () => {
205+ topLayout .value = ! topLayout .value
206+ wsCache .set (' sqlbot-topbar-layout' , topLayout .value )
207+ }
208+ onMounted (() => {
209+ topLayout .value = wsCache .get (' sqlbot-topbar-layout' ) || true
210+ })
172211 </script >
173212
174213<style lang="less" scoped>
214+ .app-topbar-container {
215+ flex-direction : column ;
216+ }
175217.app-container {
176218 display : flex ;
177219 height : 100vh ;
178-
179- .sidebar {
180- width : 240px ;
181- background : #fff ;
182- border-right : 1px solid #e6e6e6 ;
220+ .main-menu {
183221 display : flex ;
184- flex-direction : column ;
185222 .workspace-area {
186223 margin : 8px 16px ;
224+ width : 208px ;
187225 overflow : hidden ;
188226 .workspace-select {
189227 width : 100% !important ;
@@ -220,10 +258,114 @@ const toSystem = () => {
220258 .menu-container {
221259 flex : 1 ;
222260 border-right : none ;
261+ border-bottom : none ;
262+ }
263+ }
264+ .main-menu-sidebar {
265+ width : 240px ;
266+ background : #fff ;
267+ border-right : 1px solid #e6e6e6 ;
268+ display : flex ;
269+ flex-direction : column ;
270+ }
271+ .main-menu-topbar {
272+ height : 60px ;
273+ line-height : 60px ;
274+ font-size : 24px ;
275+ font-weight : bold ;
276+ color : var (--el-color-primary );
277+ text-align : left ;
278+ justify-content : space-between ;
279+ border-bottom : 1px solid var (--el-menu-border-color );
280+ text-align : center ;
281+ .logo {
282+ height : 60px ;
283+ line-height : 60px ;
284+ }
285+
286+ .main-topbar-right {
287+ display : flex ;
288+ height : 60px ;
289+ align-items : center ;
290+ padding-right : 24px ;
291+ .header-icon-btn {
292+ display : flex ;
293+ column-gap : 12px ;
294+ align-items : center ;
295+ padding : 8px 16px ;
296+ border-radius : 4px ;
297+ cursor : pointer ;
298+ border : none ;
299+ font-weight : 500 ;
300+ transition : all 0.3s ;
301+ font-size : 14px ;
302+ color : #5f6368 ;
303+ & :hover {
304+ background-color : rgba (0 , 0 , 0 , 0.05 );
305+ }
306+ }
307+ :deep(.user-info ) {
308+ display : flex ;
309+ column-gap : 4px ;
310+ align-items : center ;
311+ .el-avatar {
312+ background-color : var (--el-color-primary );
313+ color : #fff ;
314+ }
315+ .user-name {
316+ font-size : 14px ;
317+ font-weight : 500 ;
318+ color : #202124 ;
319+ }
320+ }
321+ .top-back-area {
322+ align-items : center ;
323+ display : flex ;
324+ }
325+ }
326+ .topbar-workspace-area {
327+ margin : 0 32px ;
328+ height : auto ;
329+ width : 208px ;
330+ line-height : 54px ;
331+ .workspace-select {
332+ width : 100% !important ;
333+ :deep(.el-select__wrapper ) {
334+ border-radius : 10px ;
335+ box-shadow : none !important ;
336+ background-color : #f1f3f4 ;
337+ line-height : 24px ;
338+ min-height : 32px ;
339+ .workspace-label {
340+ color : #2d2e31 ;
341+ font-weight : 600 ;
342+ display : flex ;
343+ column-gap : 8px ;
344+ align-items : center ;
345+ height : 32px ;
346+ }
347+ }
348+ }
349+ }
350+ .top-bar-title {
351+ font-size : 14px ;
352+ color : var (--el-color-info );
353+ display : flex ;
354+ align-items : center ;
355+ left : 132px ;
356+ width : 200px ;
357+ position : fixed ;
358+ .split {
359+ color : #bbbbbb ;
360+ border : 0.5px solid ;
361+ margin-right : 16px ;
362+ height : 12px ;
363+ }
223364 }
224365 }
225366
226367 .main-content {
368+ width : calc (100% - 288px );
227369 flex : 1 ;
228370 display : flex ;
229371 flex-direction : column ;
@@ -299,17 +441,41 @@ const toSystem = () => {
299441 padding : 24px ;
300442 box-shadow : var (--shadow );
301443 margin-top : 24px ;
444+ flex : 1 ;
302445 .sys-inner-container {
303446 background : #fff ;
304447 border-radius : 8px ;
305448 padding : 20px ;
306449 box-shadow : 0 2px 8px rgba (0 , 0 , 0 , 0.1 );
307450 }
308451 }
309- .sys-setting -container {
452+ .sub-menu -container {
310453 overflow : hidden ;
311454 border-radius : 8px ;
312455 }
313456 }
457+ .main-conntent-withbar {
458+ padding : 0 ;
459+ width : 100% ;
460+ display : flex ;
461+ flex-direction : row ;
462+ .sub-menu-container {
463+ flex : 0 0 auto ;
464+ background-color : lightblue ;
465+ resize : horizontal ;
466+ overflow : auto ;
467+ border-right : 1px solid var (--el-menu-border-color );
468+ border-radius : 0 ;
469+ background-color : var (--white );
470+ :deep(.el-menu ) {
471+ border : none ;
472+ }
473+ }
474+ .sys-page-content {
475+ margin : 0 ;
476+ border-radius : 0 ;
477+ width : calc (100% - 288px );
478+ }
479+ }
314480}
315481 </style >
0 commit comments