本地 RAG 知识库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

68 lines
2.1 KiB

<template>
<div class="layout-container">
<!-- 覆盖移动端菜单遮罩 -->
<div class="sidebar-overlay" v-if="mobileMenuOpen" @click="mobileMenuOpen = false"></div>
<!-- 顶部导航 -->
<Topbar @toggle-mobile-menu="mobileMenuOpen = !mobileMenuOpen" @logout="handleLogout" />
<!-- 主体 -->
<div class="layout-body">
<!-- 侧边栏 -->
<Sidebar
:collapsed="sidebarCollapsed"
:mobile-open="mobileMenuOpen"
@toggle-collapse="sidebarCollapsed = !sidebarCollapsed"
@close-mobile-menu="mobileMenuOpen = false"
/>
<!-- 内容区 -->
<main class="main-content">
<router-view />
</main>
</div>
<!-- 文档详情弹窗 -->
<DocDetail v-if="dialog.detailModal.visible" :visible="dialog.detailModal.visible"
:doc="dialog.detailModal.doc" :chunks="dialog.detailModal.chunks"
:chunks-error="dialog.detailModal.chunksError"
@close="dialog.closeDetail" />
</div>
</template>
<script setup lang="ts">
import { ref, provide } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { useDialogStore } from '@/stores/dialog'
import { toast } from '@/utils/toast'
import Topbar from './Topbar.vue'
import Sidebar from './Sidebar.vue'
import DocDetail from '@/views/DocDetail.vue'
const router = useRouter()
const auth = useAuthStore()
const dialog = useDialogStore()
const sidebarCollapsed = ref(false)
const mobileMenuOpen = ref(false)
// 提供给子组件全局弹窗能力
provide('openDocDetail', (docId: string) => dialog.openDetail(docId))
async function handleLogout() {
await auth.doLogout()
toast('已退出登录', 'info')
router.push('/chat')
}
</script>
<style scoped>
.layout-container { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
.layout-body { display: flex; flex: 1; overflow: hidden; }
.main-content { flex: 1; overflow: auto; padding: 0; background: var(--td-bg-color-page); }
.sidebar-overlay { display: none; }
@media (max-width: 768px) {
.sidebar-overlay { display: block; position: fixed; inset: 0; background: rgba(0,0,0,.3); z-index: 98; }
}
</style>