722 lines
17 KiB
Vue
722 lines
17 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useColorMode } from '@vueuse/core';
|
|
import logoDark from '@/assets/images/logo-dark.png';
|
|
import logo from '@/assets/images/logo.png';
|
|
import ConsoleBtn from '@/layouts/components/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 ContactUsBtn from './components/ContactUsBtn.vue';
|
|
import LoginBtn from './components/LoginBtn.vue';
|
|
import ThemeBtn from './components/ThemeBtn.vue';
|
|
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
const userStore = useUserStore();
|
|
|
|
// 使用 VueUse 的 useColorMode 获取主题状态
|
|
const mode = useColorMode({
|
|
attribute: 'data-theme',
|
|
modes: {
|
|
light: 'light',
|
|
dark: 'dark',
|
|
},
|
|
storageKey: 'yi-theme',
|
|
initialValue: 'light',
|
|
});
|
|
|
|
// 根据主题切换 logo
|
|
const currentLogo = computed(() => {
|
|
return mode.value === 'dark' ? logoDark : logo;
|
|
});
|
|
|
|
// 移动端菜单抽屉状态
|
|
const mobileMenuVisible = ref(false);
|
|
|
|
// 当前激活的菜单项
|
|
const activeIndex = computed(() => {
|
|
if (route.path.startsWith('/console'))
|
|
return 'console';
|
|
if (route.path.startsWith('/model-library') || route.path.startsWith('/ranking'))
|
|
return 'model-library';
|
|
if (route.path.includes('/chat/'))
|
|
return 'chat';
|
|
return '';
|
|
});
|
|
|
|
// 导航处理
|
|
function handleSelect(key: string) {
|
|
if (key && key !== 'no-route') {
|
|
router.push(key);
|
|
mobileMenuVisible.value = false; // 移动端导航后关闭菜单
|
|
}
|
|
}
|
|
|
|
// 修改 AI 聊天菜单的点击事件
|
|
function handleAIClick(e: MouseEvent) {
|
|
e.stopPropagation(); // 阻止事件冒泡
|
|
router.push('/chat/conversation');
|
|
mobileMenuVisible.value = false;
|
|
}
|
|
|
|
// 修改控制台菜单的点击事件
|
|
function handleConsoleClick(e: MouseEvent) {
|
|
e.stopPropagation(); // 阻止事件冒泡
|
|
router.push('/console/user');
|
|
mobileMenuVisible.value = false;
|
|
}
|
|
|
|
// 修改模型库菜单的点击事件
|
|
function handleModelLibraryClick(e: MouseEvent) {
|
|
e.stopPropagation(); // 阻止事件冒泡
|
|
router.push('/model-library');
|
|
mobileMenuVisible.value = false;
|
|
}
|
|
|
|
// 跳转到模型监控外部链接
|
|
function goToModelMonitor() {
|
|
window.open('http://data.ccnetcore.com:91/?period=24h', '_blank');
|
|
mobileMenuVisible.value = false;
|
|
}
|
|
|
|
// 切换移动端菜单
|
|
function toggleMobileMenu() {
|
|
mobileMenuVisible.value = !mobileMenuVisible.value;
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="header-container">
|
|
<!-- 桌面端菜单 -->
|
|
<el-menu
|
|
:default-active="activeIndex"
|
|
class="header-menu desktop-menu"
|
|
mode="horizontal"
|
|
:ellipsis="false"
|
|
:router="false"
|
|
@select="handleSelect"
|
|
>
|
|
<!-- 左侧品牌区域 -->
|
|
<div class="menu-left">
|
|
<div class="brand-container" @click="router.push('/')">
|
|
<el-image :src="currentLogo" 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" @click="handleAIClick">AI应用</span>
|
|
</template>
|
|
<el-menu-item index="/chat/conversation">
|
|
AI对话
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/image">
|
|
AI图片
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/video">
|
|
AI视频
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/agent">
|
|
AI智能体
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/api">
|
|
AI接口
|
|
</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-sub-menu index="model-library" class="model-library-submenu" popper-class="custom-popover">
|
|
<template #title>
|
|
<span class="menu-title" @click="handleModelLibraryClick">模型</span>
|
|
</template>
|
|
<el-menu-item index="/model-library">
|
|
模型库
|
|
</el-menu-item>
|
|
<el-menu-item index="/ranking">
|
|
模型排行榜
|
|
</el-menu-item>
|
|
<el-menu-item index="no-route" @click="goToModelMonitor">
|
|
模型监控
|
|
</el-menu-item>
|
|
</el-sub-menu>
|
|
|
|
<!-- AI教程 -->
|
|
<el-menu-item class="custom-menu-item" index="no-route">
|
|
<AiTutorialBtn />
|
|
</el-menu-item>
|
|
|
|
<!-- 联系我们 -->
|
|
<el-menu-item class="custom-menu-item" index="no-route">
|
|
<ContactUsBtn />
|
|
</el-menu-item>
|
|
|
|
<!-- 控制台菜单 -->
|
|
<el-sub-menu index="console" class="console-submenu" popper-class="custom-popover">
|
|
<template #title>
|
|
<ConsoleBtn @click="handleConsoleClick" />
|
|
</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 class="custom-menu-item" index="no-route">
|
|
<ThemeBtn />
|
|
</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 class="mobile-header">
|
|
<div class="mobile-brand" @click="router.push('/')">
|
|
<el-image :src="currentLogo" alt="logo" fit="contain" class="mobile-logo" />
|
|
<span class="mobile-brand-text">意心AI</span>
|
|
</div>
|
|
|
|
<div class="mobile-actions">
|
|
<!-- 用户头像或登录按钮 -->
|
|
<div v-if="userStore.userInfo" class="mobile-avatar">
|
|
<Avatar />
|
|
</div>
|
|
<LoginBtn v-else :is-menu-item="false" />
|
|
|
|
<!-- 汉堡菜单按钮 -->
|
|
<el-button class="menu-toggle" text @click="toggleMobileMenu">
|
|
<el-icon :size="24">
|
|
<component :is="mobileMenuVisible ? 'Close' : 'Menu'" />
|
|
</el-icon>
|
|
</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 移动端抽屉菜单 -->
|
|
<el-drawer
|
|
v-model="mobileMenuVisible"
|
|
direction="rtl"
|
|
:size="280"
|
|
:close-on-click-modal="true"
|
|
:lock-scroll="true"
|
|
modal-class="mobile-drawer-modal"
|
|
class="mobile-drawer"
|
|
>
|
|
<template #header>
|
|
<div class="drawer-header">
|
|
<span class="drawer-title">菜单</span>
|
|
</div>
|
|
</template>
|
|
|
|
<el-menu
|
|
:default-active="activeIndex"
|
|
class="mobile-menu"
|
|
@select="handleSelect"
|
|
>
|
|
<!-- AI应用 -->
|
|
<el-sub-menu index="chat">
|
|
<template #title>
|
|
<el-icon><ChatDotRound /></el-icon>
|
|
<span>AI应用</span>
|
|
</template>
|
|
<el-menu-item index="/chat/conversation">
|
|
AI对话
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/image">
|
|
AI图片
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/video">
|
|
AI视频
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/agent">
|
|
AI智能体
|
|
</el-menu-item>
|
|
<el-menu-item index="/chat/api">
|
|
AI接口
|
|
</el-menu-item>
|
|
</el-sub-menu>
|
|
|
|
<!-- 模型库下拉菜单 -->
|
|
<el-sub-menu index="model-library">
|
|
<template #title>
|
|
<el-icon><Box /></el-icon>
|
|
<span>模型</span>
|
|
</template>
|
|
<el-menu-item index="/model-library">
|
|
模型库
|
|
</el-menu-item>
|
|
<el-menu-item index="/ranking">
|
|
模型排行榜
|
|
</el-menu-item>
|
|
<el-menu-item index="no-route" @click="goToModelMonitor">
|
|
模型监控
|
|
</el-menu-item>
|
|
</el-sub-menu>
|
|
|
|
<!-- 控制台 -->
|
|
<el-sub-menu index="console">
|
|
<template #title>
|
|
<el-icon><Setting /></el-icon>
|
|
<span>控制台</span>
|
|
</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>
|
|
|
|
<!-- 其他功能 -->
|
|
<div class="mobile-menu-actions">
|
|
<div class="action-item">
|
|
<AnnouncementBtn :is-menu-item="false" />
|
|
</div>
|
|
<div class="action-item">
|
|
<AiTutorialBtn />
|
|
</div>
|
|
<div class="action-item">
|
|
<ContactUsBtn />
|
|
</div>
|
|
<div v-if="userStore.userInfo" class="action-item">
|
|
<BuyBtn :is-menu-item="false" />
|
|
</div>
|
|
</div>
|
|
</el-menu>
|
|
</el-drawer>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.header-container {
|
|
--menu-hover-bg: var(--color-white);
|
|
--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;
|
|
position: relative;
|
|
}
|
|
|
|
// 移动端头部(默认隐藏)
|
|
.mobile-header {
|
|
display: none;
|
|
}
|
|
|
|
.header-menu {
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: 100%;
|
|
border-bottom: none !important;
|
|
//background: var(--color-white);
|
|
|
|
}
|
|
|
|
// 左侧品牌区域
|
|
.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 4px !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,
|
|
.model-library-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 4px;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
// 移动端头部样式
|
|
.mobile-brand {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
cursor: pointer;
|
|
padding: 8px;
|
|
border-radius: 6px;
|
|
transition: background-color 0.2s;
|
|
|
|
&:hover {
|
|
background-color: var(--menu-hover-bg);
|
|
}
|
|
}
|
|
|
|
.mobile-logo {
|
|
width: 32px;
|
|
height: 32px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.mobile-brand-text {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--brand-color, #000000);
|
|
}
|
|
|
|
.mobile-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.mobile-avatar {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.menu-toggle {
|
|
padding: 8px;
|
|
color: var(--el-text-color-primary);
|
|
|
|
&:hover {
|
|
color: var(--el-color-primary);
|
|
}
|
|
}
|
|
|
|
// 移动端抽屉样式
|
|
.drawer-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0;
|
|
}
|
|
|
|
.drawer-title {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--el-text-color-primary);
|
|
}
|
|
|
|
.mobile-menu {
|
|
border: none;
|
|
|
|
:deep(.el-sub-menu__title),
|
|
:deep(.el-menu-item) {
|
|
height: 48px;
|
|
line-height: 48px;
|
|
padding: 0 20px !important;
|
|
margin: 4px 0;
|
|
border-radius: 8px;
|
|
transition: all 0.2s;
|
|
|
|
&:hover {
|
|
background-color: var(--el-color-primary-light-9);
|
|
}
|
|
|
|
&.is-active {
|
|
color: var(--el-color-primary);
|
|
background-color: var(--el-color-primary-light-9);
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
:deep(.el-icon) {
|
|
margin-right: 12px;
|
|
font-size: 18px;
|
|
}
|
|
}
|
|
|
|
.mobile-menu-actions {
|
|
margin-top: 20px;
|
|
padding: 16px 0;
|
|
border-top: 1px solid var(--el-border-color-light);
|
|
|
|
.action-item {
|
|
padding: 8px 20px;
|
|
margin: 4px 0;
|
|
|
|
&:hover {
|
|
background-color: var(--el-color-primary-light-9);
|
|
border-radius: 8px;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 响应式设计
|
|
@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) {
|
|
// 隐藏桌面端菜单
|
|
.desktop-menu {
|
|
display: none !important;
|
|
}
|
|
|
|
// 显示移动端头部
|
|
.mobile-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: 100%;
|
|
padding: 0 12px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.mobile-header {
|
|
padding: 0 8px;
|
|
}
|
|
|
|
.mobile-brand-text {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.mobile-logo {
|
|
width: 28px;
|
|
height: 28px;
|
|
}
|
|
|
|
.mobile-actions {
|
|
gap: 4px;
|
|
}
|
|
}
|
|
</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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.el-sub-menu .el-sub-menu__icon-arrow{
|
|
margin-right: -20px;
|
|
}
|
|
</style>
|