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
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>
|