mirror of
https://gitee.com/ccnetcore/Yi
synced 2026-04-05 08:46:35 +08:00
537 lines
12 KiB
Vue
537 lines
12 KiB
Vue
<!--
|
||
<!– Header 头部 –>
|
||
<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">
|
||
<!– 左侧logo和品牌区域 –>
|
||
<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>
|
||
|
||
<!– 右侧功能按钮区域 –>
|
||
<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(--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(--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(--brand-color, #000000);
|
||
white-space: nowrap;
|
||
letter-spacing: -0.5px;
|
||
transition: color 0.2s ease;
|
||
|
||
&:hover {
|
||
//color: var(--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>
|