Skip to content

Commit 5fe2bc4

Browse files
committed
更新博客展示UI
1 parent 2c806cb commit 5fe2bc4

1 file changed

Lines changed: 104 additions & 9 deletions

File tree

frontend/src/components/BlogHeader.vue

Lines changed: 104 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,30 @@
1717
<router-link class="site-nav-link" to="/" :class="{ active: isActive('/') }">首页</router-link>
1818
<router-link class="site-nav-link" to="/all" :class="{ active: isActive('/all') }">博客</router-link>
1919
<router-link class="site-nav-link" to="/about" :class="{ active: isActive('/about') }">关于</router-link>
20-
<a
21-
class="site-nav-link"
22-
href="http://ai.wecode.xin/"
23-
target="_blank"
24-
rel="noopener noreferrer"
25-
>
26-
AI平台
27-
</a>
20+
<div ref="dropdownRoot" class="site-nav-dropdown">
21+
<button
22+
type="button"
23+
class="site-nav-link site-nav-link-btn site-nav-dropdown-trigger"
24+
:aria-expanded="dropdownOpen"
25+
aria-haspopup="menu"
26+
@click.stop="toggleDropdown"
27+
>
28+
AI实验室 <span class="site-nav-dropdown-caret" aria-hidden="true">▾</span>
29+
</button>
30+
31+
<div v-if="dropdownOpen" class="site-nav-dropdown-menu" role="menu">
32+
<a
33+
class="site-nav-dropdown-item"
34+
href="http://ai.wecode.xin/"
35+
target="_blank"
36+
rel="noopener noreferrer"
37+
role="menuitem"
38+
@click="closeDropdown"
39+
>
40+
AI工作平台
41+
</a>
42+
</div>
43+
</div>
2844
<a
2945
class="site-nav-link"
3046
href="https://github.com/yyyCode/OpenBlog.git"
@@ -42,14 +58,17 @@
4258
</template>
4359

4460
<script setup>
45-
import { onMounted, ref } from 'vue'
61+
import { onBeforeUnmount, onMounted, ref } from 'vue'
4662
import { useRoute } from 'vue-router'
4763
import { toggleTheme as applyToggle } from '../theme'
4864
4965
const isDark = ref(false)
5066
const route = useRoute()
5167
const emit = defineEmits(['toggle-widgets'])
5268
69+
const dropdownOpen = ref(false)
70+
const dropdownRoot = ref(null)
71+
5372
function sync() {
5473
isDark.value = document.documentElement.getAttribute('data-theme') === 'dark'
5574
}
@@ -58,6 +77,31 @@ onMounted(() => {
5877
sync()
5978
})
6079
80+
function toggleDropdown() {
81+
dropdownOpen.value = !dropdownOpen.value
82+
}
83+
84+
function closeDropdown() {
85+
dropdownOpen.value = false
86+
}
87+
88+
function onDocClick(e) {
89+
const el = dropdownRoot.value
90+
if (!el) return
91+
// 点击下拉触发器或菜单内部:不收起
92+
const target = e?.target
93+
if (target && el.contains(target)) return
94+
closeDropdown()
95+
}
96+
97+
onMounted(() => {
98+
document.addEventListener('click', onDocClick)
99+
})
100+
101+
onBeforeUnmount(() => {
102+
document.removeEventListener('click', onDocClick)
103+
})
104+
61105
function onToggle() {
62106
applyToggle()
63107
sync()
@@ -67,3 +111,54 @@ function isActive(path) {
67111
return route.path === path
68112
}
69113
</script>
114+
115+
<style scoped>
116+
.site-nav-dropdown {
117+
position: relative;
118+
display: inline-flex;
119+
}
120+
121+
.site-nav-dropdown-trigger {
122+
display: inline-flex;
123+
align-items: center;
124+
gap: 6px;
125+
white-space: nowrap;
126+
}
127+
128+
.site-nav-dropdown-caret {
129+
font-size: 12px;
130+
opacity: 0.85;
131+
transform: translateY(-1px);
132+
}
133+
134+
.site-nav-dropdown-menu {
135+
position: absolute;
136+
left: 0;
137+
top: calc(100% + 8px);
138+
background: var(--bg);
139+
border: 1px solid var(--border);
140+
border-radius: 10px;
141+
padding: 6px;
142+
min-width: 160px;
143+
box-shadow: var(--shadow);
144+
z-index: 1000;
145+
}
146+
147+
.site-nav-dropdown-item {
148+
display: block;
149+
text-decoration: none;
150+
color: var(--muted);
151+
font-weight: 600;
152+
font-size: 13px;
153+
padding: 10px 12px;
154+
border-radius: 8px;
155+
transition:
156+
background 0.15s ease,
157+
color 0.15s ease;
158+
}
159+
160+
.site-nav-dropdown-item:hover {
161+
color: var(--text);
162+
background: var(--accent-bg);
163+
}
164+
</style>

0 commit comments

Comments
 (0)