style: Dynamic Layout

This commit is contained in:
fit2cloud-chenyw
2025-05-09 15:56:28 +08:00
parent 846b8cd1fa
commit 0f5185bbeb
4 changed files with 208 additions and 40 deletions
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746770210598" class="icon" viewBox="0 0 1092 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11567" xmlns:xlink="http://www.w3.org/1999/xlink" width="273" height="256"><path d="M912.742481 930.912187H177.099287c-27.246044 0-45.407236 18.161191-45.407235 45.407236s18.161191 45.407236 45.407235 45.407235h735.643194c27.246044 0 45.407236-18.161191 45.407236-45.407235s-22.699361-45.407236-45.407236-45.407236zM45.407236 458.644582C18.161191 458.644582 0 476.805774 0 504.051818v181.645971c0 27.246044 18.161191 45.407236 45.407236 45.407236s45.41575-18.161191 45.41575-45.407236V504.051818c0-27.246044-18.169706-45.407236-45.41575-45.407236z m999.027297 0c-27.246044 0-45.41575 18.161191-45.41575 45.407236v181.645971c0 27.246044 18.169706 45.407236 45.41575 45.407236 27.246044 0 45.407236-18.161191 45.407236-45.407236V504.051818c0-27.246044-18.161191-45.407236-45.407236-45.407236zM681.151105 295.168317H590.32812v-77.199963c40.869066-18.161191 68.115111-59.030258 68.11511-104.437493C658.44323 49.953919 608.497826 0 544.920884 0c-63.576941 0-113.522346 54.492088-113.522346 113.530861 0 45.407236 27.246044 86.276302 68.115111 104.437493V295.168317H408.690663c-163.476265 0-295.168317 131.692052-295.168317 295.168317 0 163.476265 131.692052 295.159803 295.168317 295.159803h272.460442c163.476265 0 295.168317-131.683537 295.168318-295.159803C976.319423 426.860369 844.627371 295.168317 681.151105 295.168317zM385.982788 681.151105c-49.945405 0-90.814471-40.869066-90.814471-90.814471 0-49.953919 40.869066-90.822986 90.814471-90.822985C435.936707 499.513649 476.805774 540.382715 476.805774 590.336634c0 54.492088-40.869066 90.814471-90.822986 90.814471z m317.876192 0C653.905061 681.151105 613.035995 640.282039 613.035995 590.336634 613.035995 540.382715 653.905061 499.513649 703.85898 499.513649c49.945405 0 90.814471 40.869066 90.814472 90.822985 0 54.492088-40.869066 90.814471-90.814472 90.814471z" fill="#000000" p-id="11568"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746770070364" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4907" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"><path d="M293.172603 530.235616c25.249315 0 50.49863-5.610959 74.345205-18.235616 16.832877-8.416438 23.846575-29.457534 15.430137-47.693151-8.416438-16.832877-29.457534-23.846575-47.69315-15.430137-12.624658 7.013699-26.652055 9.819178-42.082192 9.819178-50.49863 0-91.178082-40.679452-91.178082-91.178082s40.679452-91.178082 91.178082-91.178082c5.610959 0 12.624658 0 18.235616 1.40274 8.416438 1.40274 16.832877 0 23.846576-4.208219-5.610959 16.832877-8.416438 35.068493-8.416439 54.706849 0 103.80274 84.164384 186.564384 186.564384 186.564383S701.369863 432.043836 701.369863 328.241096c0-21.041096-4.208219-40.679452-9.819178-60.317808 8.416438 8.416438 19.638356 11.221918 32.263014 9.819178 5.610959-1.40274 12.624658-1.40274 18.235616-1.40274 50.49863 0 91.178082 40.679452 91.178082 91.178082s-40.679452 91.178082-91.178082 91.178082c-15.430137 0-29.457534-2.805479-42.082192-9.819178-16.832877-8.416438-37.873973-1.40274-47.69315 15.430137-8.416438 16.832877-1.40274 37.873973 15.430137 47.693151 22.443836 11.221918 47.693151 18.235616 74.345205 18.235616 89.775342 0 161.315068-72.942466 161.315069-161.315068s-72.942466-161.315068-161.315069-161.315069c-11.221918 0-22.443836 1.40274-32.263014 2.80548-16.832877 2.805479-28.054795 18.235616-28.054794 35.068493-30.860274-60.317808-93.983562-102.4-166.926028-102.4-68.734247 0-129.052055 37.873973-161.315068 93.983562-2.805479-12.624658-12.624658-22.443836-26.652055-25.249315-11.221918-2.805479-21.041096-2.805479-32.263014-2.80548-89.775342 0-161.315068 72.942466-161.315068 161.315069s70.136986 159.912329 159.912329 159.912328z m220.230137-318.421917c64.526027 0 116.427397 51.90137 116.427397 116.427397s-51.90137 116.427397-116.427397 116.427397-116.427397-51.90137-116.427398-116.427397 51.90137-116.427397 116.427398-116.427397zM740.646575 533.041096c-11.221918 0-22.443836 0-33.665753 1.40274-19.638356 2.805479-32.263014 19.638356-30.860274 39.276712 0 1.40274 0 2.805479 1.40274 4.208219-47.693151-28.054795-103.80274-44.887671-164.120548-44.887671-57.512329 0-110.816438 15.430137-157.10685 40.679452 2.805479-19.638356-11.221918-36.471233-30.860274-39.276712-9.819178-1.40274-21.041096-1.40274-32.263013-1.40274C140.273973 533.041096 16.832877 656.482192 16.832877 807.978082c0 19.638356 15.430137 35.068493 35.068493 35.068493s35.068493-15.430137 35.068493-35.068493c0-113.621918 92.580822-206.20274 206.20274-206.20274 7.013699 0 12.624658 0 19.638356 1.40274-74.345205 58.915068-122.038356 150.093151-122.038356 252.493151 0 19.638356 15.430137 35.068493 35.068493 35.068493s35.068493-15.430137 35.068493-35.068493c0-140.273973 113.621918-253.89589 253.89589-253.895891 140.273973 0 253.89589 113.621918 253.895891 253.895891 0 19.638356 15.430137 35.068493 35.068493 35.068493s35.068493-15.430137 35.068493-35.068493c0-102.4-47.693151-193.578082-122.038356-252.493151 8.416438-1.40274 16.832877-1.40274 25.249315-1.40274 113.621918 0 206.20274 92.580822 206.20274 206.20274 0 19.638356 15.430137 35.068493 35.068493 35.068493s35.068493-15.430137 35.068493-35.068493C1016.986301 656.482192 893.545205 533.041096 740.646575 533.041096z" fill="" p-id="4908"></path></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

+204 -38
View File
@@ -1,9 +1,9 @@
<template>
<div class="app-container">
<div class="sidebar">
<div class="app-container" :class="{ 'app-topbar-container': topLayout }">
<div class="main-menu" :class="{ 'main-menu-sidebar': !topLayout, 'main-menu-topbar': topLayout }">
<div class="logo">SQLBot</div>
<div class="workspace-area">
<div v-if="!topLayout || !showSubmenu" :class="{ 'workspace-area': !topLayout, 'topbar-workspace-area': topLayout }">
<el-select
v-model="workspace"
placeholder="Select"
@@ -26,21 +26,57 @@
</el-select>
</div>
<el-menu
v-if="!topLayout || !showSubmenu"
:default-active="activeMenu"
class="menu-container">
class="menu-container"
:mode="topLayout ? 'horizontal' : 'vertical'"
>
<el-menu-item v-for="item in routerList" :key="item.path" :index="item.path" @click="menuSelect">
<el-icon v-if="item.meta.icon">
<component :is="resolveIcon(item.meta.icon)" />
</el-icon>
<span>{{ item.meta.title }}</span>
</el-menu-item>
</el-menu>
<div v-else class="top-bar-title">
<span class="split" />
<span>System manage</span>
</div>
<div class="main-topbar-right" v-if="topLayout">
<div class="top-back-area" v-if="showSubmenu">
<el-button type="primary" text="primary" @click="backMain">
<el-icon class="el-icon--right"><ArrowLeftBold /></el-icon>Back
</el-button>
</div>
<el-tooltip content="System manage" placement="bottom" v-else>
<div class="header-icon-btn" @click="toSystem">
<el-icon><iconsystem /></el-icon>
<!-- <span>System manage</span> -->
</div>
</el-tooltip>
<el-dropdown trigger="click">
<div class="user-info">
<el-avatar size="small">{{ name?.charAt(0) }}</el-avatar>
<span class="user-name">{{ name }}</span>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="switchLayout">Switch Layout</el-dropdown-item>
<el-dropdown-item @click="logout">Logout</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<div class="main-content">
<div class="header-container">
<div class="main-content" :class="{'main-conntent-withbar': topLayout}">
<div class="header-container" v-if="!topLayout">
<div class="header">
<h1>{{ currentPageTitle }}</h1>
<div class="header-actions">
@@ -50,18 +86,7 @@
<span>System manage</span>
</div>
</el-tooltip>
<!-- <el-tooltip content="Help" placement="bottom">
<div class="header-icon-btn">
<el-icon><question-filled /></el-icon>
<span>Help</span>
</div>
</el-tooltip>
<el-tooltip content="Notice" placement="bottom">
<div class="header-icon-btn">
<el-icon><BellFilled /></el-icon>
<span>Notice</span>
</div>
</el-tooltip> -->
<el-dropdown trigger="click">
<div class="user-info">
<el-avatar size="small">{{ name?.charAt(0) }}</el-avatar>
@@ -69,6 +94,7 @@
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="switchLayout">Switch Layout</el-dropdown-item>
<el-dropdown-item @click="logout">Logout</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -77,11 +103,11 @@
</div>
</div>
<div v-if="sysRouterList.length && showHead" class="sys-setting-container">
<div v-if="sysRouterList.length && showSubmenu" class="sub-menu-container">
<el-menu
:default-active="activeMenu"
class="el-menu-demo"
mode="horizontal"
:mode="!topLayout ? 'horizontal' : 'vertical'"
>
<el-menu-item v-for="item in sysRouterList" :key="item.path" :index="item.path" @click="menuSelect">
<el-icon v-if="item.meta.icon">
@@ -92,7 +118,7 @@
</el-menu>
</div>
<div v-if="sysRouterList.length && showHead" class="sys-page-content">
<div v-if="sysRouterList.length && showSubmenu" class="sys-page-content">
<div class="sys-inner-container">
<router-view />
</div>
@@ -105,7 +131,7 @@
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserStore } from '@/stores/user'
import folder from '@/assets/svg/folder.svg'
@@ -114,11 +140,12 @@ import dashboard from '@/assets/svg/dashboard.svg'
import chat from '@/assets/svg/chat.svg'
import iconsetting from '@/assets/svg/setting.svg'
import iconsystem from '@/assets/svg/system.svg'
/* import {
QuestionFilled,
BellFilled
} from '@element-plus/icons-vue' */
import icon_user from '@/assets/svg/icon_user.svg'
import icon_ai from '@/assets/svg/icon_ai.svg'
import { ArrowLeftBold } from '@element-plus/icons-vue'
import { useCache } from '@/utils/useCache'
const { wsCache } = useCache()
const topLayout = ref(false)
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
@@ -134,7 +161,7 @@ const sysRouterList = computed(() => {
return router.getRoutes().filter(route => route.path.includes('/system'))
})
const showHead = computed(() => {
const showSubmenu = computed(() => {
return route.path.includes('/system')
})
const workspace = ref('1')
@@ -154,7 +181,9 @@ const resolveIcon = (iconName: any) => {
'ds': ds,
'dashboard': dashboard,
'chat': chat,
'setting': iconsetting
'setting': iconsetting,
'icon_user': icon_user,
'icon_ai': icon_ai,
}
return typeof icons[iconName] === 'function' ? icons[iconName]() : icons[iconName]
}
@@ -169,21 +198,30 @@ const logout = () => {
const toSystem = () => {
router.push('/system')
}
const backMain = () => {
router.push('/')
}
const switchLayout = () => {
topLayout.value = !topLayout.value
wsCache.set('sqlbot-topbar-layout', topLayout.value)
}
onMounted(() => {
topLayout.value = wsCache.get('sqlbot-topbar-layout') || true
})
</script>
<style lang="less" scoped>
.app-topbar-container {
flex-direction: column;
}
.app-container {
display: flex;
height: 100vh;
.sidebar {
width: 240px;
background: #fff;
border-right: 1px solid #e6e6e6;
.main-menu {
display: flex;
flex-direction: column;
.workspace-area {
margin: 8px 16px;
width: 208px;
overflow: hidden;
.workspace-select {
width: 100% !important;
@@ -220,10 +258,114 @@ const toSystem = () => {
.menu-container {
flex: 1;
border-right: none;
border-bottom: none;
}
}
.main-menu-sidebar {
width: 240px;
background: #fff;
border-right: 1px solid #e6e6e6;
display: flex;
flex-direction: column;
}
.main-menu-topbar {
height: 60px;
line-height: 60px;
font-size: 24px;
font-weight: bold;
color: var(--el-color-primary);
text-align: left;
justify-content: space-between;
border-bottom: 1px solid var(--el-menu-border-color);
text-align: center;
.logo {
height: 60px;
line-height: 60px;
}
.main-topbar-right {
display: flex;
height: 60px;
align-items: center;
padding-right: 24px;
.header-icon-btn {
display: flex;
column-gap: 12px;
align-items: center;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
border: none;
font-weight: 500;
transition: all 0.3s;
font-size: 14px;
color: #5f6368;
&:hover {
background-color: rgba(0, 0, 0, 0.05);
}
}
:deep(.user-info) {
display: flex;
column-gap: 4px;
align-items: center;
.el-avatar {
background-color: var(--el-color-primary);
color: #fff;
}
.user-name {
font-size: 14px;
font-weight: 500;
color: #202124;
}
}
.top-back-area {
align-items: center;
display: flex;
}
}
.topbar-workspace-area {
margin: 0 32px;
height: auto;
width: 208px;
line-height: 54px;
.workspace-select {
width: 100% !important;
:deep(.el-select__wrapper) {
border-radius: 10px;
box-shadow: none !important;
background-color: #f1f3f4;
line-height: 24px;
min-height: 32px;
.workspace-label {
color: #2d2e31;
font-weight: 600;
display: flex;
column-gap: 8px;
align-items: center;
height: 32px;
}
}
}
}
.top-bar-title {
font-size: 14px;
color: var(--el-color-info);
display: flex;
align-items: center;
left: 132px;
width: 200px;
position: fixed;
.split {
color: #bbbbbb;
border: 0.5px solid;
margin-right: 16px;
height: 12px;
}
}
}
.main-content {
width: calc(100% - 288px);
flex: 1;
display: flex;
flex-direction: column;
@@ -299,6 +441,7 @@ const toSystem = () => {
padding: 24px;
box-shadow: var(--shadow);
margin-top: 24px;
flex: 1;
.sys-inner-container {
background: #fff;
border-radius: 8px;
@@ -306,10 +449,33 @@ const toSystem = () => {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
}
.sys-setting-container {
.sub-menu-container {
overflow: hidden;
border-radius: 8px;
}
}
.main-conntent-withbar {
padding: 0;
width: 100%;
display: flex;
flex-direction: row;
.sub-menu-container {
flex: 0 0 auto;
background-color: lightblue;
resize: horizontal;
overflow: auto;
border-right: 1px solid var(--el-menu-border-color);
border-radius: 0;
background-color: var(--white);
:deep(.el-menu) {
border: none;
}
}
.sys-page-content {
margin: 0;
border-radius: 0;
width: calc(100% - 288px);
}
}
}
</style>
+2 -2
View File
@@ -76,13 +76,13 @@ const router = createRouter({
path: 'user',
name: 'user',
component: () => import('@/views/system/user/index.vue'),
meta: { title: 'User Management', icon: 'setting' }
meta: { title: 'User Management', icon: 'icon_user' }
},
{
path: 'model',
name: 'model',
component: () => import('@/views/system/model/index.vue'),
meta: { title: 'AI Model Configuration', icon: 'setting' }
meta: { title: 'AI Model Configuration', icon: 'icon_ai' }
}
]
}