WebIndex/components/nav/NavBar.vue

199 lines
4.5 KiB
Vue
Raw Normal View History

2024-11-17 11:45:08 +08:00
<script lang="ts" setup>
2025-01-13 21:51:37 +08:00
import { computed, onMounted, onUnmounted, ref } from 'vue'
2024-11-17 11:45:08 +08:00
type Widget = {
icon: string[]
url: string
title: string
}
2024-12-01 13:09:44 +08:00
const props = defineProps({
2025-01-13 21:51:37 +08:00
navColor: {
default: false,
type: Boolean,
},
}),
// 使用 ref 跟踪是否滚动
scrolled = ref(false),
littleWidget: Widget[] = [
{
icon: ['fas', 'gauge'],
url: '/netdata/',
title: 'Pi Dashboard',
},
{
icon: ['fas', 'cloud'],
url: '/nas/',
title: 'Nextcloud',
},
{
icon: ['fas', 'code-branch'],
url: '/git/',
title: 'Git Repository',
},
],
// Const logoUrl = getAssetURL("w.png")
logoType: string = 'logo',
showLogo = computed(() => logoType === 'text'),
isExpended = ref<boolean>(false),
route = useRoute(),
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
entry = [
{
title: '主页',
icon: ['fas', 'home'],
entry: [],
to: 'index',
},
{
title: '文章',
icon: ['fas', 'pen'],
entry: [
{
title: '博客',
url: false,
to: 'article',
},
{
title: '日记',
url: false,
to: 'diary',
},
],
},
{
title: '作品',
icon: ['fas', 'brush'],
entry: [
{
title: '软件',
url: false,
to: 'soft',
},
{
title: '仓库',
url: true,
to: 'https://cantyonion.site/git/',
},
],
},
{
title: '杂谈',
icon: ['fas', 'chess-rook'],
entry: [],
to: 'talk',
},
],
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
menuExpanded = () => {
isExpended.value = !isExpended.value
},
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
menuClose = () => {
isExpended.value = false
},
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
// 监听 scroll 事件
handleScroll = () => {
scrolled.value = window.scrollY > 0
},
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
debouncedScroll = debounce(handleScroll, 10),
2024-11-17 11:45:08 +08:00
2025-01-13 21:51:37 +08:00
alwaysBlueBackground = computed(() => route.name !== 'index' || props.navColor)
2024-11-17 11:45:08 +08:00
// 在组件挂载和卸载时添加和移除事件监听
onMounted(() => {
window.addEventListener('scroll', debouncedScroll)
})
onUnmounted(() => {
window.removeEventListener('scroll', debouncedScroll)
})
</script>
<template>
2025-01-13 21:51:37 +08:00
<nav
:class="{ 'bg-transparent': !scrolled && !alwaysBlueBackground,
'bg-blue-400': scrolled || alwaysBlueBackground,
'shadow': scrolled }"
class="fixed top-0 z-20 h-16 w-full text-white transition-all duration-300"
2024-11-17 11:45:08 +08:00
>
<div class="container mx-auto flex h-16 w-full items-center justify-between px-4 md:px-0 xl:max-w-screen-xl">
<!-- 下拉菜单按钮 -->
2025-01-13 21:51:37 +08:00
<div
class="flex h-8 w-10 items-center justify-center rounded-md border-gray-600 md:hidden"
@click="menuExpanded"
2024-11-17 11:45:08 +08:00
>
2025-01-13 21:51:37 +08:00
<font-awesome-icon
:icon="['fas', 'bars']"
class="h-6"
/>
2024-11-17 11:45:08 +08:00
</div>
<!-- Logo -->
<div class="absolute left-1/2 -translate-x-1/2 md:relative md:left-0 md:translate-x-0">
<!-- 文字模式 -->
2025-01-13 21:51:37 +08:00
<div
v-if="showLogo"
class="h-full text-4xl min-w-16 logo py-3.5"
>
2024-11-17 11:45:08 +08:00
<span>CantyOni_on's Index</span>
</div>
<!-- 图片模式 -->
2025-01-13 21:51:37 +08:00
<div
v-else
class="py-2"
>
<img
src="~/assets/images/logo/w.png"
alt=""
class="h-12 w-12"
>
2024-11-17 11:45:08 +08:00
</div>
</div>
<!-- Entry -->
2025-01-13 21:51:37 +08:00
<div
:class="{ 'h-screen opacity-100 visible': isExpended, 'h-0 opacity-0 invisible': !isExpended }"
class="absolute top-full right-0 left-0 bg-white transition-all md:visible md:relative md:top-0 md:flex
md:h-auto md:bg-transparent md:opacity-100"
2024-11-17 11:45:08 +08:00
>
2025-01-13 21:51:37 +08:00
<nav-bar-entry-item
v-for="item in entry"
:key="item.title"
:entry="item.entry"
:icon="item.icon"
:title="item.title"
:to="item.to"
@on-go="menuClose"
2024-11-17 11:45:08 +08:00
/>
</div>
<!-- 快速跳转小组件 -->
<div class="flex items-center justify-between gap-4 text-xl">
2025-01-13 21:51:37 +08:00
<a
v-for="item in littleWidget"
:key="item.url"
:href="item.url"
:title="item.title"
class="transition-all hover:scale-125"
>
<font-awesome-icon :icon="item.icon" />
2024-11-17 11:45:08 +08:00
</a>
</div>
</div>
</nav>
2024-11-17 13:05:55 +08:00
<!-- 用于隔开元素 -->
2025-01-13 21:51:37 +08:00
<div
v-if="alwaysBlueBackground"
class="h-16 w-full"
/>
2024-11-17 11:45:08 +08:00
</template>
<style scoped>
.logo {
font-family: BaconyScript, serif;
}
2025-01-13 21:51:37 +08:00
</style>