11<script setup lang="ts">
2- import { ref } from ' vue'
2+ import { ref , watch } from ' vue'
33import { useRoute } from ' vue-router'
4+ import { useI18n } from ' vue-i18n'
45
56const route = useRoute ()
7+ const { t, locale } = useI18n ()
68const mobileOpen = ref (false )
79const projectDropdownOpen = ref (false )
810
911const projects = [
1012 { name: ' LLM Simple Router' , path: ' /project/llm-simple-router/' },
1113]
1214
13- function toggleMobile() {
14- mobileOpen .value = ! mobileOpen .value
15- }
15+ watch (locale , (val ) => { localStorage .setItem (' locale' , val ) })
1616
17- function isActive( path : string ) : boolean {
18- return route .path .startsWith (path )
19- }
17+ function toggleMobile() { mobileOpen . value = ! mobileOpen . value }
18+ function isActive( path : string ) : boolean { return route .path .startsWith (path ) }
19+ function toggleLocale() { locale . value = locale . value === ' zh ' ? ' en ' : ' zh ' }
2020 </script >
2121
2222<template >
2323 <nav class =" fixed top-0 left-0 right-0 z-50 flex h-14 items-center border-b border-white/10 bg-surface/80 backdrop-blur-md" >
24- <!-- 左侧 Logo 区域:w-64 与 SideBar 对齐 -->
2524 <router-link to =" /" class =" flex h-14 w-64 shrink-0 items-center px-6 group" >
2625 <svg width =" 134" height =" 30" viewBox =" 0 0 134 30" fill =" none" class =" transition-opacity group-hover:opacity-80" >
2726 <text x =" 0" y =" 24" font-family =" monospace" font-size =" 20" font-weight =" bold" fill =" #60a5fa" >Z</text >
@@ -38,11 +37,10 @@ function isActive(path: string): boolean {
3837 </svg >
3938 </router-link >
4039
41- <!-- 右侧:导航菜单 + 图标(从 SideBar 分割线位置开始) -->
4240 <div class =" hidden flex-1 items-center justify-between pr-6 md:flex" >
4341 <div class =" flex items-center gap-1" >
4442 <router-link to =" /about" class =" rounded-md px-3 py-1.5 text-sm text-gray-400 hover:bg-white/5 hover:text-gray-200 transition-colors" >
45- 个人介绍
43+ {{ t('nav.about') }}
4644 </router-link >
4745
4846 <div class =" relative" @mouseleave =" projectDropdownOpen = false" >
@@ -51,33 +49,31 @@ function isActive(path: string): boolean {
5149 :class =" isActive('/project') ? 'text-gray-200 bg-white/5' : 'text-gray-400 hover:bg-white/5 hover:text-gray-200'"
5250 @mouseenter =" projectDropdownOpen = true"
5351 >
54- 项目介绍
55- <svg class =" h-3.5 w-3.5" fill =" none" viewBox =" 0 0 24 24" stroke =" currentColor" stroke-width =" 2" >
56- <path stroke-linecap =" round" stroke-linejoin =" round" d =" M19 9l-7 7-7-7" />
57- </svg >
52+ {{ t('nav.projects') }}
53+ <svg class =" h-3.5 w-3.5" fill =" none" viewBox =" 0 0 24 24" stroke =" currentColor" stroke-width =" 2" ><path stroke-linecap =" round" stroke-linejoin =" round" d =" M19 9l-7 7-7-7" /></svg >
5854 </button >
5955 <div v-show =" projectDropdownOpen" class =" absolute left-0 top-[calc(100%-4px)] z-10" @mouseenter =" projectDropdownOpen = true" >
6056 <div class =" h-1 w-full" />
6157 <div class =" w-56 rounded-lg border border-white/10 bg-surface-50 py-1 shadow-xl" >
62- <router-link
63- v-for =" project in projects"
64- :key =" project.path"
65- :to =" project.path"
66- class =" block px-4 py-2 text-sm text-gray-300 hover:bg-white/5 hover:text-white transition-colors"
67- @click =" projectDropdownOpen = false"
68- >
69- {{ project.name }}
70- </router-link >
58+ <router-link v-for =" p in projects" :key =" p.path" :to =" p.path" class =" block px-4 py-2 text-sm text-gray-300 hover:bg-white/5 hover:text-white transition-colors" @click =" projectDropdownOpen = false" >{{ p.name }}</router-link >
7159 </div >
7260 </div >
7361 </div >
7462
7563 <router-link to =" /social" class =" rounded-md px-3 py-1.5 text-sm text-gray-400 hover:bg-white/5 hover:text-gray-200 transition-colors" >
76- 社交平台
64+ {{ t('nav.social') }}
7765 </router-link >
7866 </div >
7967
80- <div class =" flex items-center gap-3" >
68+ <div class =" flex items-center gap-2" >
69+ <!-- Language switcher -->
70+ <button @click =" toggleLocale" class =" flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-gray-400 hover:text-gray-200 hover:bg-white/5 transition-colors" title =" Switch Language" >
71+ <svg class =" h-4 w-4" fill =" none" viewBox =" 0 0 24 24" stroke =" currentColor" stroke-width =" 2" >
72+ <path stroke-linecap =" round" stroke-linejoin =" round" d =" M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129" />
73+ </svg >
74+ <span >{{ locale === 'zh' ? 'EN' : '中文' }}</span >
75+ </button >
76+
8177 <a href =" https://github.com/zhushanwen321" target =" _blank" rel =" noopener" class =" text-gray-500 hover:text-gray-300 transition-colors" aria-label =" GitHub" >
8278 <svg class =" h-5 w-5" fill =" currentColor" viewBox =" 0 0 24 24" ><path d =" M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" /></svg >
8379 </a >
@@ -88,22 +84,25 @@ function isActive(path: string): boolean {
8884 </div >
8985
9086 <!-- Mobile hamburger -->
91- <div class =" flex flex-1 items-center justify-end pr-6 md:hidden" >
87+ <div class =" flex flex-1 items-center justify-end gap-2 pr-4 md:hidden" >
88+ <button @click =" toggleLocale" class =" text-xs text-gray-400 hover:text-gray-200 px-1.5 py-1" >
89+ {{ locale === 'zh' ? 'EN' : '中文' }}
90+ </button >
9291 <button class =" text-gray-400 hover:text-gray-200 transition-colors" @click =" toggleMobile" aria-label =" Toggle menu" >
9392 <svg v-if =" !mobileOpen" class =" h-6 w-6" fill =" none" viewBox =" 0 0 24 24" stroke =" currentColor" stroke-width =" 2" ><path stroke-linecap =" round" stroke-linejoin =" round" d =" M4 6h16M4 12h16M4 18h16" /></svg >
9493 <svg v-else class =" h-6 w-6" fill =" none" viewBox =" 0 0 24 24" stroke =" currentColor" stroke-width =" 2" ><path stroke-linecap =" round" stroke-linejoin =" round" d =" M6 18L18 6M6 6l12 12" /></svg >
9594 </button >
9695 </div >
9796
9897 <!-- Mobile menu -->
99- <div v-show =" mobileOpen" class =" absolute left-0 right-0 top-14 border-t border-white/10 md:hidden" >
98+ <div v-show =" mobileOpen" class =" absolute left-0 right-0 top-14 border-t border-white/10 md:hidden bg-surface " >
10099 <div class =" space-y-1 px-4 py-3" >
101- <router-link to =" /about" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >个人介绍 </router-link >
100+ <router-link to =" /about" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >{{ t('nav.about') }} </router-link >
102101 <div class =" pl-3" >
103- <p class =" px-3 py-1 text-xs font-semibold uppercase tracking-wider text-gray-500" >项目介绍 </p >
104- <router-link v-for =" project in projects" :key =" project .path" :to =" project .path" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >{{ project .name }}</router-link >
102+ <p class =" px-3 py-1 text-xs font-semibold uppercase tracking-wider text-gray-500" >{{ t('nav.projects') }} </p >
103+ <router-link v-for =" p in projects" :key =" p .path" :to =" p .path" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >{{ p .name }}</router-link >
105104 </div >
106- <router-link to =" /social" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >社交平台 </router-link >
105+ <router-link to =" /social" class =" block rounded-md px-3 py-2 text-sm text-gray-300 hover:bg-white/5" @click =" mobileOpen = false" >{{ t('nav.social') }} </router-link >
107106 </div >
108107 </div >
109108 </nav >
0 commit comments