From eb4c8504b1d9e92151c9eb7809d2eb56316246d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=BC=A0?= <2091066548@qq.com> Date: Sun, 7 Sep 2025 17:50:03 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=96=B0=E6=B5=AE=E7=AA=97?= =?UTF-8?q?=EF=BC=8C=E5=92=8C=E5=88=87=E6=8D=A2=E8=AF=AD=E8=A8=80=EF=BC=8C?= =?UTF-8?q?=E5=92=8C=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83=E7=9A=84=E5=AD=97?= =?UTF-8?q?=E4=BD=93=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/layout/AppHeader.vue | 404 ++++++++++++++++++++-------- src/views/Profile.vue | 103 +++++-- 2 files changed, 368 insertions(+), 139 deletions(-) diff --git a/src/components/layout/AppHeader.vue b/src/components/layout/AppHeader.vue index d85fa3d..19deb82 100644 --- a/src/components/layout/AppHeader.vue +++ b/src/components/layout/AppHeader.vue @@ -59,18 +59,23 @@
-
- - - {{ t('header.languageSwitch') }} -
-
- {{ t('languageDropdown.switchToChinese') }} +
+ +
+
+ + + + +
+ {{ getCurrentLanguageLabel() }} +
+ + + +
-
- {{ t('languageDropdown.switchToEnglish') }} -
-
+
@@ -195,6 +200,52 @@ const registerModalVisible = ref(false) const showLanguageDropdown = ref(false) const languageSwitcherRef = ref(null) +// 语言选项配置 +const languageOptions = computed(() => [ + { + label: '中文', + key: 'zh', + props: { + onClick: () => handleLanguageSelect('zh') + } + }, + { + label: 'English', + key: 'en', + props: { + onClick: () => handleLanguageSelect('en') + } + }, + { + label: 'Русский', + key: 'ru', + props: { + onClick: () => handleLanguageSelect('ru') + } + }, + { + label: 'Français', + key: 'fr', + props: { + onClick: () => handleLanguageSelect('fr') + } + }, + { + label: 'Español', + key: 'es', + props: { + onClick: () => handleLanguageSelect('es') + } + }, + { + label: '日本語', + key: 'ja', + props: { + onClick: () => handleLanguageSelect('ja') + } + } +]) + // 切换移动端菜单 const toggleMobileMenu = () => { mobileMenuOpen.value = !mobileMenuOpen.value @@ -205,12 +256,34 @@ const toggleLanguageDropdown = () => { showLanguageDropdown.value = !showLanguageDropdown.value } -// 切换语言 -const switchLanguage = (lang: string) => { +// 处理语言选择 +const handleLanguageSelect = (lang: string) => { locale.value = lang localStorage.setItem('locale', lang) - showLanguageDropdown.value = false - console.log('语言已切换到:', lang === 'zh' ? '中文' : '英文') + console.log('语言已切换到:', getLanguageName(lang)) +} + +// 获取当前语言标签 +const getCurrentLanguageLabel = () => { + return getLanguageName(locale.value) +} + +// 获取语言名称 +const getLanguageName = (lang: string): string => { + const languageMap: { [key: string]: string } = { + 'zh': '中文', + 'en': 'English', + 'ru': 'Русский', + 'fr': 'Français', + 'es': 'Español', + 'ja': '日本語' + } + return languageMap[lang] || '中文' +} + +// 切换语言(保留兼容性) +const switchLanguage = (lang: string) => { + handleLanguageSelect(lang) } const handleLearningCenter = () => { @@ -324,72 +397,146 @@ const setupMenuHoverEffects = () => { }, 500) } -// 用户菜单选项 +// 用户菜单选项 - 自定义渲染为网格布局 const userMenuOptions = computed(() => [ { - label: '个人中心', - key: 'profile', - icon: () => h('div', { - class: 'menu-icon-container', - style: 'position: relative; width: 18px; height: 18px; display: inline-block; margin-right: 1px; overflow: hidden;' + type: 'render', + render: () => h('div', { + class: 'custom-user-menu', + style: 'padding: 16px 24px; width: 280px;' }, [ - h('img', { - src: '/images/personal/用户_user备份@2x.png', - alt: '个人中心', - class: 'menu-icon default-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0;' - }), - h('img', { - src: '/images/personal/用户_user备份 2@2x.png', - alt: '个人中心', - class: 'menu-icon hover-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0; opacity: 0;' - }) - ]) - }, - { - label: '切换教师端', - key: 'teacher', - icon: () => h('div', { - class: 'menu-icon-container', - style: 'position: relative; width: 18px; height: 18px; display: inline-block; margin-right: 1px; overflow: hidden;' - }, [ - h('img', { - src: '/images/personal/切换_switch备份@2x.png', - alt: '切换教师端', - class: 'menu-icon default-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0;' - }), - h('img', { - src: '/images/personal/切换_switch备份 2@2x.png', - alt: '切换教师端', - class: 'menu-icon hover-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0; opacity: 0;' - }) - ]) - }, - { - type: 'divider' - }, - { - label: '退出登录', - key: 'logout', - icon: () => h('div', { - class: 'menu-icon-container', - style: 'position: relative; width: 18px; height: 18px; display: inline-block; margin-right: 1px; overflow: hidden;' - }, [ - h('img', { - src: '/images/personal/退出_logout备份 2@2x.png', - alt: '退出登录', - class: 'menu-icon default-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0;' - }), - h('img', { - src: '/images/personal/退出_logout备份 3@2x.png', - alt: '退出登录', - class: 'menu-icon hover-icon', - style: 'width: 18px !important; height: 18px !important; max-width: 18px; max-height: 18px; object-fit: contain; position: absolute; top: 0; left: 0; opacity: 0;' - }) + // 用户信息头部 + h('div', { + class: 'user-menu-header', + style: 'display: flex; align-items: center; margin-bottom: 16px;' + }, [ + h('span', { + style: 'font-size: 14px; color: #333; font-weight: 500;' + }, `Hi~ ${userStore.user?.profile?.realName || userStore.user?.nickname || userStore.user?.username || 'U2per'}`) + ]), + + // 2x2 网格菜单 + h('div', { + class: 'user-menu-grid', + style: 'display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 16px;' + }, [ + // 我的课程 + h('div', { + class: 'menu-grid-item', + style: 'display: flex; align-items: center; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; background-color: #f9f9f9;', + onClick: () => handleUserMenuSelect('courses') + }, [ + h('div', { + class: 'menu-icon-container', + style: 'margin-right: 8px;' + }, [ + h('img', { + src: '/images/personal/用户_user备份@2x.png', + alt: '我的课程', + style: 'width: 18px; height: 18px; object-fit: contain;' + }) + ]), + h('span', { + style: 'font-size: 14px; color: #333; font-weight: 500;' + }, '我的课程') + ]), + + // 购买记录 + h('div', { + class: 'menu-grid-item', + style: 'display: flex; align-items: center; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; background-color: #f9f9f9;', + onClick: () => handleUserMenuSelect('purchase') + }, [ + h('div', { + class: 'menu-icon-container', + style: 'margin-right: 8px;' + }, [ + h('img', { + src: '/images/personal/用户_user备份@2x.png', + alt: '购买记录', + style: 'width: 18px; height: 18px; object-fit: contain;' + }) + ]), + h('span', { + style: 'font-size: 14px; color: #333; font-weight: 500;' + }, '购买记录') + ]), + + // 我的学币 + h('div', { + class: 'menu-grid-item', + style: 'display: flex; align-items: center; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; background-color: #f9f9f9;', + onClick: () => handleUserMenuSelect('coins') + }, [ + h('div', { + class: 'menu-icon-container', + style: 'margin-right: 8px;' + }, [ + h('img', { + src: '/images/personal/切换_switch备份@2x.png', + alt: '我的学币', + style: 'width: 18px; height: 18px; object-fit: contain;' + }) + ]), + h('span', { + style: 'font-size: 14px; color: #333; font-weight: 500;' + }, '我的学币') + ]), + + // 个人资料 + h('div', { + class: 'menu-grid-item', + style: 'display: flex; align-items: center; padding: 10px 12px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; background-color: #f9f9f9;', + onClick: () => handleUserMenuSelect('profile') + }, [ + h('div', { + class: 'menu-icon-container', + style: 'margin-right: 8px;' + }, [ + h('img', { + src: '/images/personal/用户_user备份@2x.png', + alt: '个人资料', + style: 'width: 18px; height: 18px; object-fit: contain;' + }) + ]), + h('span', { + style: 'font-size: 14px; color: #333; font-weight: 500;' + }, '个人资料') + ]) + ]), + + // 底部操作区 + h('div', { + class: 'user-menu-footer', + style: 'display: flex; justify-content: space-between; align-items: center; padding-top: 12px; border-top: 1px solid #f0f0f0;' + }, [ + // 切换教师端 + h('div', { + class: 'footer-action', + style: 'display: flex; align-items: center; gap: 4px; cursor: pointer; padding: 4px 8px; border-radius: 4px; transition: background-color 0.2s;', + onClick: () => handleUserMenuSelect('teacher') + }, [ + h('img', { + src: '/images/personal/切换_switch备份@2x.png', + alt: '切换教师端', + style: 'width: 14px; height: 14px; object-fit: contain;' + }), + h('span', { + style: 'font-size: 12px; color: #666;' + }, '切换教师端') + ]), + + // 安全退出 + h('div', { + class: 'footer-action', + style: 'display: flex; align-items: center; gap: 4px; cursor: pointer; padding: 4px 8px; border-radius: 4px; transition: background-color 0.2s;', + onClick: () => handleUserMenuSelect('logout') + }, [ + h('span', { + style: 'font-size: 12px; color: #666;' + }, '安全退出') + ]) + ]) ]) } ]) @@ -433,6 +580,22 @@ const handleMenuSelect = (key: string) => { // 处理用户菜单选择 const handleUserMenuSelect = (key: string) => { switch (key) { + case 'courses': + // 跳转到我的课程 + router.push('/profile/courses').then(() => { + window.location.reload(); + }) + break + case 'purchase': + // 跳转到购买记录 + console.log('跳转到购买记录') + // 这里可以添加购买记录页面的路由 + break + case 'coins': + // 跳转到我的学币 + console.log('跳转到我的学币') + // 这里可以添加学币页面的路由 + break case 'profile': router.push('/profile').then(() => { // 检查sessionStorage中是否已有刷新标志 @@ -784,44 +947,45 @@ watch(() => route.path, () => { /* 语言切换器 */ .language-switcher { position: relative; - cursor: pointer; } - - .language-dropdown { - position: absolute; - top: 100%; - left: 0; - right: 0; - background: white; - border: 1px solid #e8e8e8; - border-radius: 6px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); - z-index: 1000; - margin-top: 4px; - min-width: 120px; - } - - .language-option { - padding: 8px 12px; - font-size: 13px; - color: #666; + + .language-trigger { + display: flex; + align-items: center; + gap: 6px; cursor: pointer; + padding: 6px 8px; + border-radius: 4px; transition: all 0.2s; - border-bottom: 1px solid #f5f5f5; } - - .language-option:last-child { - border-bottom: none; + + .language-trigger:hover { + background-color: #f0f8ff; } - - .language-option:hover { - background: #f0f8ff; - color: #1890ff; + + .language-icon { + display: flex; + align-items: center; + justify-content: center; } - + .language-text { + font-size: 14px; + color: #1890ff; + font-weight: 500; white-space: nowrap; } + + .language-arrow { + display: flex; + align-items: center; + justify-content: center; + transition: transform 0.2s; + } + + .language-switcher:hover .language-arrow { + transform: rotate(180deg); + } /* 认证按钮 */ .auth-buttons { @@ -893,10 +1057,28 @@ watch(() => route.path, () => { /* 美化用户菜单样式 */ :deep(.n-dropdown-menu) { - border-radius: 8px; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); - border: 1px solid #f0f0f0; - padding: 8px 0; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12); + border: 1px solid #e6e6e6; + padding: 0; + min-width: 280px; + } + + /* 自定义用户菜单样式 */ + .custom-user-menu { + background: white; + } + + .user-menu-header { + font-weight: 500; + } + + .menu-grid-item:hover { + background-color: #eeeeee !important; + } + + .footer-action:hover { + background-color: #f5f5f5 !important; } :deep(.n-dropdown-option) { diff --git a/src/views/Profile.vue b/src/views/Profile.vue index bcc1234..9417728 100644 --- a/src/views/Profile.vue +++ b/src/views/Profile.vue @@ -770,12 +770,12 @@ @@ -826,17 +826,15 @@