Files
Yi.Admin/Yi.Ai.Vue3/src/layouts/components/Header/index.vue
2025-12-28 22:45:23 +08:00

537 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
&lt;!&ndash; Header 头部 &ndash;&gt;
<script setup lang="ts">
import { useRouter } from 'vue-router';
import logo from '@/assets/images/logo.png';
import { useUserStore } from '@/stores';
import AiTutorialBtn from './components/AiTutorialBtn.vue';
import AnnouncementBtn from './components/AnnouncementBtn.vue';
import Avatar from './components/Avatar.vue';
import BuyBtn from './components/BuyBtn.vue';
import ConsoleBtn from './components/ConsoleBtn.vue';
import LoginBtn from './components/LoginBtn.vue';
import ModelLibraryBtn from './components/ModelLibraryBtn.vue';
import StartChatBtn from './components/StartChatBtn.vue';
import ThemeBtn from './components/ThemeBtn.vue';
const router = useRouter();
const userStore = useUserStore();
// 打开控制台
function handleOpenConsole() {
router.push('/console');
}
</script>
<template>
<div class="header-container">
<div class="header-box">
&lt;!&ndash; 左侧logo和品牌区域 &ndash;&gt;
<div class="left-section">
<div class="brand-container">
<el-image :src="logo" alt="logo" fit="contain" class="logo-img" />
<span class="brand-text">意心AI</span>
</div>
</div>
&lt;!&ndash; 右侧功能按钮区域 &ndash;&gt;
<div class="right-section">
<StartChatBtn />
<AnnouncementBtn />
<ModelLibraryBtn />
<AiTutorialBtn />
<ConsoleBtn @open-console="handleOpenConsole" />
<BuyBtn v-show="userStore.userInfo" />
<ThemeBtn />
<LoginBtn v-show="!userStore.userInfo" />
<Avatar v-show="userStore.userInfo" />
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.header-container {
display: flex;
flex-shrink: 0;
width: 100%;
height: var(&#45;&#45;header-container-default-height, 60px);
.header-box {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
padding: 0 16px;
background: var(&#45;&#45;header-bg-color, #ffffff);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}
// 左侧品牌区域
.left-section {
display: flex;
align-items: center;
min-width: fit-content;
flex-shrink: 0;
.brand-container {
display: flex;
align-items: center;
gap: 8px;
.logo-img {
width: 36px; // 优化为更合适的大小
height: 36px;
flex-shrink: 0;
transition: transform 0.2s ease;
&:hover {
transform: scale(1.05);
}
}
.brand-text {
font-size: 22px; // 减小字体大小
font-weight: bold;
color: var(&#45;&#45;brand-color, #000000);
white-space: nowrap;
letter-spacing: -0.5px;
transition: color 0.2s ease;
&:hover {
//color: var(&#45;&#45;brand-hover-color, #40a9ff);
}
}
}
}
// 右侧功能区域
.right-section {
display: flex;
align-items: center;
gap: 12px; // 优化按钮间距
height: 100%;
flex-shrink: 0;
// 统一按钮样式
:deep(.menu-button) {
height: 36px;
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>
-->
<!-- Header 头部 -->
<script setup lang="ts">
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import logo from '@/assets/images/logo.png';
import ConsoleBtn from '@/layouts/components0/Header/components/ConsoleBtn.vue';
import { useUserStore } from '@/stores';
import AiTutorialBtn from './components/AiTutorialBtn.vue';
import AnnouncementBtn from './components/AnnouncementBtn.vue';
import Avatar from './components/Avatar.vue';
import BuyBtn from './components/BuyBtn.vue';
import LoginBtn from './components/LoginBtn.vue';
import ModelLibraryBtn from './components/ModelLibraryBtn.vue';
import ThemeBtn from './components/ThemeBtn.vue';
const router = useRouter();
const route = useRoute();
const userStore = useUserStore();
// 当前激活的菜单项
const activeIndex = computed(() => {
if (route.path.startsWith('/console'))
return 'console';
if (route.path.startsWith('/model-library'))
return 'model-library';
if (route.path.includes('/chat/'))
return 'chat';
return '';
});
// 导航处理
function handleSelect(key: string) {
if (key && key !== 'no-route') {
router.push(key);
}
}
</script>
<template>
<div class="header-container">
<el-menu
:default-active="activeIndex"
class="header-menu"
mode="horizontal"
:ellipsis="false"
:router="false"
@select="handleSelect"
>
<!-- 左侧品牌区域 -->
<div class="menu-left">
<div class="brand-container" @click="router.push('/')">
<el-image :src="logo" alt="logo" fit="contain" class="logo-img" />
<span class="brand-text">意心AI</span>
</div>
</div>
<!-- 右侧功能区域 -->
<div class="menu-right">
<!-- AI聊天菜单 -->
<el-sub-menu index="chat" class="chat-submenu" popper-class="custom-popover">
<template #title>
<span class="menu-title">AI聊天</span>
</template>
<el-menu-item index="/chat/conversation">
AI对话
</el-menu-item>
<el-menu-item index="/chat/image">
图片生成
</el-menu-item>
<el-menu-item index="/chat/video">
视频生成
</el-menu-item>
</el-sub-menu>
<!-- 公告按钮 -->
<el-menu-item class="custom-menu-item" index="no-route">
<AnnouncementBtn :is-menu-item="true" />
</el-menu-item>
<!-- 模型库 -->
<el-menu-item index="/model-library" class="custom-menu-item">
<ModelLibraryBtn :is-menu-item="true" />
</el-menu-item>
<!-- AI教程 -->
<el-menu-item class="custom-menu-item" index="no-route">
<AiTutorialBtn />
</el-menu-item>
<!-- 控制台菜单 -->
<el-sub-menu index="console" class="console-submenu" popper-class="custom-popover">
<template #title>
<ConsoleBtn />
</template>
<el-menu-item index="/console/user">
用户信息
</el-menu-item>
<el-menu-item index="/console/apikey">
API密钥
</el-menu-item>
<el-menu-item index="/console/recharge-log">
充值记录
</el-menu-item>
<el-menu-item index="/console/usage">
用量统计
</el-menu-item>
<el-menu-item index="/console/premium">
尊享服务
</el-menu-item>
<el-menu-item index="/console/daily-task">
每日任务
</el-menu-item>
<el-menu-item index="/console/invite">
每周邀请
</el-menu-item>
<el-menu-item index="/console/activation">
激活码兑换
</el-menu-item>
</el-sub-menu>
<!-- 购买按钮 -->
<el-menu-item v-if="userStore.userInfo" class="custom-menu-item" index="no-route">
<BuyBtn :is-menu-item="true" />
</el-menu-item>
<!-- 主题切换暂不显示 -->
<el-menu-item v-if="false" class="custom-menu-item" index="no-route">
<ThemeBtn :is-menu-item="true" />
</el-menu-item>
<!-- 用户头像 -->
<div v-if="userStore.userInfo" class="avatar-container">
<Avatar />
</div>
<!-- 登录按钮 -->
<el-menu-item v-if="!userStore.userInfo" class="login-menu-item" index="no-route">
<LoginBtn :is-menu-item="true" />
</el-menu-item>
</div>
</el-menu>
</div>
</template>
<style scoped lang="scss">
.header-container {
--menu-hover-bg: #f5f5f5;
--menu-active-color: var(--el-color-primary);
--menu-transition: all 0.2s ease;
width: 100%;
height: var(--header-container-default-height, 64px);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
user-select: none;
}
.header-menu {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
border-bottom: none !important;
}
// 左侧品牌区域
.menu-left {
flex-shrink: 0;
margin-left: 20px;
}
.brand-container {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
padding: 8px 12px;
border-radius: 6px;
transition: background-color var(--menu-transition);
&:hover {
background-color: var(--menu-hover-bg);
}
}
.logo-img {
width: 34px;
height: 34px;
flex-shrink: 0;
transition: transform var(--menu-transition);
&:hover {
transform: scale(1.05);
}
}
.brand-text {
font-size: 20px;
font-weight: 600;
color: var(--brand-color, #000000);
white-space: nowrap;
letter-spacing: -0.5px;
}
// 右侧功能区域
.menu-right {
display: flex;
align-items: center;
height: 100%;
margin-right: 16px;
gap: 4px;
}
// 公共菜单项样式
:deep(.el-menu-item),
:deep(.el-sub-menu__title) {
height: 100% !important;
border-bottom: none !important;
padding: 0 12px !important;
color: inherit !important;
&:hover {
background-color: transparent !important;
color: var(--menu-active-color) !important;
}
&.is-active {
background-color: transparent !important;
color: var(--menu-active-color) !important;
.menu-title {
color: var(--menu-active-color) !important;
}
}
}
// 聊天和控制台子菜单
.chat-submenu,
.console-submenu {
:deep(.el-sub-menu__title) {
display: flex;
align-items: center;
justify-content: center;
min-width: 80px;
}
}
.menu-title {
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
font-size: 1.2rem;
font-weight: bold;
color: #606266;
transition: all 0.2s;
}
// 自定义按钮菜单项
.custom-menu-item,
.login-menu-item {
:deep(.el-menu-item-content) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 0 !important;
}
}
// Avatar 容器
.avatar-container {
height: 100%;
display: flex;
align-items: center;
padding: 0 12px;
margin-left: 4px;
}
// 响应式设计
@media (max-width: 1280px) {
.brand-text {
font-size: 18px;
}
.menu-left {
margin-left: 16px;
}
.menu-right {
margin-right: 12px;
gap: 2px;
}
:deep(.el-menu-item),
:deep(.el-sub-menu__title) {
padding: 0 10px !important;
}
}
@media (max-width: 1024px) {
.brand-container {
gap: 8px;
padding: 6px 10px;
}
.logo-img {
width: 30px;
height: 30px;
}
.brand-text {
font-size: 16px;
}
.menu-title {
font-size: 13px;
}
.avatar-container {
padding: 0 8px;
}
}
@media (max-width: 768px) {
.brand-text {
display: none;
}
.logo-img {
width: 32px;
height: 32px;
}
.menu-left {
margin-left: 12px;
}
.menu-right {
margin-right: 8px;
// 隐藏按钮文字
:deep(.button-text) {
display: none;
}
.menu-title {
display: none;
}
// 显示图标
:deep(.el-icon) {
font-size: 18px;
}
}
:deep(.el-menu-item),
:deep(.el-sub-menu__title) {
padding: 0 8px !important;
min-width: auto !important;
}
}
@media (max-width: 480px) {
.menu-right {
gap: 0;
:deep(.el-menu-item),
:deep(.el-sub-menu__title) {
padding: 0 6px !important;
}
}
}
</style>
<style lang="scss">
// 自定义弹出框样式
.custom-popover {
.el-menu {
border: none;
border-radius: 8px;
padding: 6px 0;
min-width: 160px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
.el-menu-item {
height: 40px;
line-height: 40px;
padding: 0 20px;
margin: 2px 8px;
border-radius: 6px;
font-size: 14px;
transition: all 0.2s ease;
&:hover {
background-color: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
&.is-active {
color: var(--el-color-primary);
background-color: var(--el-color-primary-light-9);
font-weight: 500;
}
}
}
}
</style>