refactor(layout): 统一应用布局结构并优化样式

- 将应用标题从侧边栏移至顶部导航栏显示
- 重构所有布局组件使用统一的 flex 布局结构
- 引入 SystemHeader 组件统一管理系统顶部导航
- 移除重复的页面标题逻辑,改为动态显示
- 优化滚动区域设置,提升页面渲染性能
- 统一高度设置为 100vh 适配不同屏幕尺寸
v3.2
tanlianwang 2026-03-05 18:03:43 +08:00
parent 6163f06a64
commit 59b1279575
7 changed files with 46 additions and 75 deletions

View File

@ -1,6 +1,6 @@
<!doctype html><html lang=""><head><meta charset="UTF-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"/><base target="_blank"/><title>AI-RAG</title><script>;((prefix) => {
<!doctype html><html lang=""><head><meta charset="UTF-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no,viewport-fit=cover"/><base target="_blank"/><title>Ai-RAG</title><script>;((prefix) => {
window.MaxKB = {
prefix: '/admin',
chatPrefix: '/chat',
}
})()</script><script type="module" crossorigin src="./assets/admin-BkqzSx7d.js"></script><link rel="stylesheet" crossorigin href="./assets/admin-B9hvC0K6.css"></head><body><div id="app"></div></body></html>
})()</script><script type="module" crossorigin src="./assets/admin-CkbVdLTL.js"></script><link rel="stylesheet" crossorigin href="./assets/admin-DNnRQ7pR.css"></head><body><div id="app"></div></body></html>

View File

@ -1,8 +1,7 @@
<template>
<div class="sidebar" style="display: flex; flex-direction: column; height: 100vh; background-color: #F9FAFB; width: 240px;">
<div class="sidebar" style="display: flex; flex-direction: column; height: 100%; background-color: #F9FAFB; width: 240px;">
<!-- 顶部 Logo -->
<div style="padding: 16px;">
<h1 style="font-size: 18px; font-weight: 600; margin: 0;">AI-RAG</h1>
</div>
<!-- 业务菜单或系统管理菜单 -->

View File

@ -2,10 +2,10 @@
<div class="app-top-bar-container border-b flex-center">
<div class="flex-between w-full align-center" style="padding: 0 16px;">
<div style="display: flex; align-items: center;">
<h1 style="font-size: 18px; font-weight: 600; margin: 0;">AI-RAG | 系统管理</h1>
<h1 style="font-size: 18px; font-weight: 600; margin: 0;">{{ isSystemManagement ? 'AI-RAG | 系统管理' : 'AI-RAG' }}</h1>
</div>
<div style="display: flex; align-items: center;">
<router-link to="/application" style="display: flex; align-items: center; padding: 6px 12px; border-radius: 6px; text-decoration: none; color: #1890ff; border: 1px solid #1890ff;">
<router-link v-if="isSystemManagement" to="/application" style="display: flex; align-items: center; padding: 6px 12px; border-radius: 6px; text-decoration: none; color: #1890ff; border: 1px solid #1890ff;">
<span style="margin-right: 4px;"></span>
返回工作空间
</router-link>
@ -14,13 +14,16 @@
</div>
</template>
<script setup lang="ts">
import { RoleConst } from '@/utils/permission/data'
import Avatar from './avatar/index.vue'
import TopAbout from './top-about/index.vue'
import { useRouter } from 'vue-router'
import { hasPermission } from '@/utils/permission'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
//
const isSystemManagement = computed(() => {
const path = route.path
return path.startsWith('/system') || path.startsWith('/admin/system')
})
</script>
<style lang="scss" scoped>
.app-top-bar-container {

View File

@ -1,12 +1,15 @@
<template>
<div class="app-layout">
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex;">
<div class="app-layout" style="display: flex; flex-direction: column; height: 100vh;">
<!-- 顶部 header -->
<SystemHeader />
<!-- 主内容区 -->
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex; flex: 1; overflow: hidden;">
<!-- 最左侧侧边栏 -->
<div style="width: 240px; border-right: 1px solid #e5e7eb;">
<Sidebar />
</div>
<!-- 内容区 -->
<div style="flex: 1; overflow: hidden;">
<!-- 内容区 -->
<div style="flex: 1; overflow: auto;">
<AppMain />
</div>
</div>
@ -16,6 +19,7 @@
import { computed } from 'vue'
import Sidebar from '@/layout/components/sidebar/index.vue'
import AppMain from '@/layout/app-main/index.vue'
import SystemHeader from '@/layout/layout-header/SystemHeader.vue'
import useStore from '@/stores'
import { useRoute } from 'vue-router'
const route = useRoute()

View File

@ -1,9 +1,25 @@
<template>
<div class="app-layout" style="display: flex; flex-direction: column; height: 100vh;">
<!-- 顶部 header -->
<SystemHeader />
<!-- 主内容区 -->
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex; flex: 1; overflow: hidden;">
<!-- 最左侧侧边栏 -->
<div style="width: 240px; border-right: 1px solid #e5e7eb;">
<Sidebar />
</div>
<!-- 内容区域 -->
<div style="flex: 1; overflow: auto;">
<AppMain />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import Sidebar from '@/layout/components/sidebar/index.vue'
import AppMain from '@/layout/app-main/index.vue'
import LayoutContainer from '@/components/layout-container/index.vue'
import UserAvatar from '@/layout/layout-header/avatar/index.vue'
import SystemHeader from '@/layout/layout-header/SystemHeader.vue'
import useStore from '@/stores'
import { useRoute } from 'vue-router'
const route = useRoute()
@ -20,58 +36,7 @@ const isShared = computed(() => {
route.path.includes('resource-management')
)
})
//
const isSystemManagement = computed(() => {
const path = route.path
return path.startsWith('/system')
})
//
const pageTitle = computed(() => {
return 'AI-RAG'
})
//
const currentSystemPage = computed(() => {
const path = route.path
if (path.startsWith('/system/user')) {
return '用户管理'
} else if (path.startsWith('/system/resource')) {
return '资源授权'
} else if (path.startsWith('/system/settings')) {
return '系统设置'
}
return '用户管理'
})
</script>
<template>
<div class="app-layout">
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex;">
<!-- 最左侧侧边栏 -->
<div style="width: 240px; border-right: 1px solid #e5e7eb;">
<Sidebar />
</div>
<!-- 主内容区 -->
<div style="flex: 1; overflow: hidden;">
<!-- 顶部功能区仅系统管理模式显示 -->
<div v-if="isSystemManagement" style="display: flex; justify-content: space-between; align-items: center; padding: 16px; border-bottom: 1px solid #e5e7eb;">
<div style="display: flex; align-items: center;">
<h2 style="font-size: 18px; font-weight: 600; margin: 0;">AI-RAG | 系统管理</h2>
</div>
<div style="display: flex; align-items: center;">
<router-link to="/application" style="display: flex; align-items: center; padding: 6px 12px; border-radius: 6px; text-decoration: none; color: #1890ff; border: 1px solid #1890ff;">
<span style="margin-right: 4px;"></span>
返回工作空间
</router-link>
</div>
</div>
<AppMain />
</div>
</div>
</div>
</template>
<style lang="scss">
@use './index.scss';
</style>
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="app-layout">
<div class="app-header" :class="!isDefaultTheme ? 'custom-header' : ''">
<div class="app-layout" style="display: flex; flex-direction: column; height: 100vh;">
<div class="app-header" :class="!isDefaultTheme ? 'custom-header' : ''" style="position: static;">
<el-alert
v-if="user.isExpire()"
:title="$t('layout.isExpire')"
@ -11,13 +11,13 @@
/>
<SystemHeader />
</div>
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex;">
<div class="app-main" :class="user.isExpire() ? 'isExpire' : ''" style="display: flex; flex: 1; overflow: hidden;">
<!-- 最左侧侧边栏 -->
<div style="width: 240px; border-right: 1px solid #e5e7eb;">
<Sidebar />
</div>
<!-- 主内容区 -->
<div style="flex: 1; overflow: hidden;">
<div style="flex: 1; overflow: auto;">
<AppMain />
</div>
</div>

View File

@ -187,7 +187,7 @@
:title="item.name"
:description="item.desc"
class="cursor"
@click="goApp(item)"
@click="toChat(item)"
>
<template #icon>
<el-avatar shape="square" :size="32" style="background: none">