feat: 侧边栏开发

This commit is contained in:
2026-04-11 16:27:01 +08:00
parent 0c5ab186da
commit 5151379726

View File

@@ -2,28 +2,16 @@
<div class="flex flex-col h-screen w-screen overflow-hidden"> <div class="flex flex-col h-screen w-screen overflow-hidden">
<div class="flex flex-1 overflow-hidden"> <div class="flex flex-1 overflow-hidden">
<!-- 侧边栏 --> <!-- 侧边栏 -->
<aside :class="['flex flex-col bg-white border-r border-gray-200 transition-all duration-300 no-drag', appStore.collapsed ? 'w-16' : 'w-56']"> <aside :class="['flex flex-col bg-[#EEEFF2] border-r border-gray-200 transition-all duration-300 no-drag', appStore.collapsed ? 'w-16' : 'w-[244px]']">
<!-- Logo -->
<div class="flex items-center h-14 px-4 border-b border-gray-200 shrink-0">
<el-icon class="text-blue-500 text-xl shrink-0"><Monitor /></el-icon>
<template v-if="!appStore.collapsed">
<el-button class="ml-2 font-semibold text-gray-800 truncate" link @click="showAppInfo = true">
{{ appStore.title }}
</el-button>
</template>
</div>
<!-- 自定义菜单 --> <!-- 自定义菜单 -->
<nav class="flex-1 px-3 py-4 space-y-1"> <nav class="flex-1 px-3 py-4 space-y-1 overflow-y-auto">
<div <div
v-for="(item, index) in menus" v-for="(item, index) in menus"
:key="index" :key="index"
:class="[ :class="[
'flex items-center rounded-xl cursor-pointer transition-all duration-200 ease-out group relative overflow-hidden', 'flex items-center justify-between cursor-pointer transition-all duration-200 ease-out group relative overflow-hidden',
appStore.collapsed ? 'justify-center px-0 py-3 mx-auto w-11' : 'px-4 py-3 mx-0', appStore.collapsed ? 'justify-center px-0 py-3 mx-auto w-11 rounded-xl' : 'w-[216px] h-[37px] rounded-[10px] pl-3 pr-[146px] py-0 mx-auto',
$route.path === item.index $route.path === item.index ? 'bg-[#DEE0E4] text-gray-900' : 'text-gray-500 hover:bg-gray-50 hover:text-gray-700',
? 'bg-gradient-to-r from-blue-500 to-blue-600 text-white shadow-md shadow-blue-200'
: 'text-gray-500 hover:bg-gray-50 hover:text-gray-700',
]" ]"
@click="router.push(item.index)" @click="router.push(item.index)"
> >
@@ -35,40 +23,45 @@
$route.path === item.index ? 'scale-110' : 'group-hover:scale-105', $route.path === item.index ? 'scale-110' : 'group-hover:scale-105',
]" ]"
> >
<el-icon :class="['transition-colors duration-200', appStore.collapsed ? 'text-xl' : 'text-lg']"> <LucideIcon :name="item.icon" :size="appStore.collapsed ? 20 : 18" :class="['transition-colors duration-200']" />
<component :is="item.icon" />
</el-icon>
</div> </div>
<!-- 文字 --> <!-- 文字 -->
<span v-show="!appStore.collapsed" class="ml-3 text-sm font-medium whitespace-nowrap transition-all duration-200"> <span v-show="!appStore.collapsed" class="ml-3 text-sm font-medium whitespace-nowrap transition-all duration-200">
{{ item.name }} {{ item.name }}
</span> </span>
</div>
<!-- Active 指示条 --> <el-divider></el-divider>
<div <div class="w-54 h-8 text-sm mx-3 py-4 flex items-center" style="color: #8a9097">历史记录</div>
v-if="$route.path === item.index && !appStore.collapsed" <div
class="absolute right-0 top-1/2 -translate-y-1/2 w-1 h-6 bg-white/50 rounded-l-full" v-for="(item, index) in historyItems"
/> :key="index"
class="flex items-center w-[216px] h-[37px] justify-between rounded-[10px] pl-3 pr-[132px] mx-auto text-gray-500 hover:bg-gray-50 hover:text-gray-700 cursor-pointer transition-all duration-200"
>
<span class="text-sm font-medium whitespace-nowrap truncate">{{ item.name }}</span>
</div> </div>
</nav> </nav>
<!-- 折叠按钮 --> <!-- 用户区域 -->
<div class="p-3 border-t border-gray-200"> <div class="flex items-center justify-between p-3 border-t border-gray-200">
<el-button :icon="appStore.collapsed ? Expand : Fold" circle size="small" @click="appStore.toggleSidebar" /> <div class="flex items-center">
<el-avatar :size="32" />
<div v-show="!appStore.collapsed" class="ml-3">
<div class="text-sm font-medium">123</div>
<div class="text-xs text-gray-500">12321</div>
</div>
</div>
<LucideIcon v-show="!appStore.collapsed" name="bolt" color="#808080" size="18"></LucideIcon>
</div> </div>
<!-- &lt;!&ndash; 折叠按钮 &ndash;&gt;-->
<!-- <div class="p-3 border-t border-gray-200">-->
<!-- <el-button :icon="appStore.collapsed ? Expand : Fold" circle size="small" @click="appStore.toggleSidebar" />-->
<!-- </div>-->
</aside> </aside>
<!-- 主内容区 --> <!-- 主内容区 -->
<div class="flex flex-col flex-1 overflow-hidden"> <div class="flex flex-col flex-1 overflow-hidden">
<!-- 顶部栏 -->
<header class="flex items-center justify-between h-14 px-6 bg-white border-b border-gray-200 shrink-0">
<h1 class="text-base font-medium text-gray-700">{{ currentTitle }}</h1>
<div class="flex items-center gap-2">
<el-avatar :size="32" class="bg-blue-500">U</el-avatar>
</div>
</header>
<!-- 页面内容 --> <!-- 页面内容 -->
<main class="flex-1 overflow-hidden p-6"> <main class="flex-1 overflow-hidden p-6">
<div class="h-full overflow-auto"> <div class="h-full overflow-auto">
@@ -77,24 +70,11 @@
</main> </main>
</div> </div>
</div> </div>
<!-- 应用信息弹窗 -->
<el-dialog v-model="showAppInfo" :title="appStore.title" width="400">
<div class="p-4 text-center">
<p class="text-lg font-medium mb-2">欢迎使用 {{ appStore.title }}</p>
<p class="text-sm text-gray-500">这是一个基于 Electron Vue 3 的应用示例</p>
</div>
<template #footer>
<div class="flex justify-end">
<el-button type="primary" @click="showAppInfo = false">确定</el-button>
</div>
</template>
</el-dialog>
</div> </div>
</template> </template>
<script setup> <script setup>
import { computed, ref } from 'vue'; import { ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useAppStore } from '@/stores/app'; import { useAppStore } from '@/stores/app';
import { House, Monitor, Expand, Fold, ChatDotRound, Search, Collection, Clock } from '@element-plus/icons-vue'; import { House, Monitor, Expand, Fold, ChatDotRound, Search, Collection, Clock } from '@element-plus/icons-vue';
@@ -104,14 +84,11 @@ const route = useRoute();
const appStore = useAppStore(); const appStore = useAppStore();
const menus = ref([ const menus = ref([
{ name: '新对话', index: '/', icon: House }, { name: '新对话', index: '/', icon: 'plus' },
{ name: '知识空间', index: '/knowledge', icon: Collection }, { name: '知识空间', index: '/knowledge', icon: 'book' },
{ name: 'opencode对话', index: '/chat', icon: ChatDotRound }, { name: 'opencode对话', index: '/chat', icon: 'bot' },
{ name: '发现设备', index: '/bonjour', icon: Search }, { name: '发现设备', index: '/bonjour', icon: 'server' },
{ name: '历史对话', index: '/history', icon: Clock },
]); ]);
const showAppInfo = ref(false); const historyItems = ref([{ name: '历史记录示例 1' }, { name: '历史记录示例 2' }, { name: '历史记录示例 3' }]);
const currentTitle = computed(() => route.meta?.title || appStore.title);
</script> </script>