chore: 初始化项目仓库
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { siteConfig } from '~/config/site'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="py-6 text-center text-sm border-t" style="color: var(--color-text-secondary); border-color: var(--color-border);">
|
||||
<p>
|
||||
© {{ new Date().getFullYear() }} {{ siteConfig.siteName }}
|
||||
·
|
||||
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer" class="hover:opacity-70" style="border-bottom: 1px solid var(--color-text-secondary); padding-bottom: 1px;">蜀ICP备2026028044号</a>
|
||||
</p>
|
||||
</footer>
|
||||
</template>
|
||||
@@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import { siteConfig } from '~/config/site'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const breadcrumbs = computed(() => {
|
||||
const path = route.path
|
||||
if (path === '/') return []
|
||||
|
||||
const parts = path.split('/').filter(Boolean)
|
||||
const result: Array<{ label: string; path: string }> = []
|
||||
|
||||
let currentPath = ''
|
||||
for (const part of parts) {
|
||||
currentPath += `/${part}`
|
||||
result.push({
|
||||
label: part,
|
||||
path: currentPath,
|
||||
})
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="sticky top-0 z-40 w-full backdrop-blur-sm border-b"
|
||||
style="background-color: color-mix(in srgb, var(--color-bg) 80%, transparent); border-color: var(--color-border);">
|
||||
<div class="relative flex h-10 items-center justify-between px-2">
|
||||
<!-- 最左边:头像 + 面包屑 -->
|
||||
<div class="flex items-center gap-1 min-w-0">
|
||||
<NuxtLink to="/" class="shrink-0 hover:opacity-80 transition-opacity">
|
||||
<img
|
||||
:src="siteConfig.avatar"
|
||||
:alt="siteConfig.siteName"
|
||||
class="h-6 w-6 rounded-full nav-avatar"
|
||||
/>
|
||||
</NuxtLink>
|
||||
<template v-for="(crumb, i) in breadcrumbs" :key="crumb.path">
|
||||
<span class="shrink-0 text-muted-foreground/40">/</span>
|
||||
<NuxtLink
|
||||
:to="crumb.path"
|
||||
class="text-xs font-medium truncate shrink min-w-0 hover:opacity-80 transition-opacity"
|
||||
:class="i === breadcrumbs.length - 1 ? 'text-foreground' : 'text-muted-foreground'"
|
||||
>
|
||||
{{ crumb.label }}
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- 最右边:主题切换 -->
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<LayoutThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.nav-avatar {
|
||||
animation: spin 2s linear infinite;
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
.nav-avatar:hover {
|
||||
animation-play-state: running;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue'
|
||||
|
||||
const colorMode = useColorMode()
|
||||
|
||||
const modes = ['light', 'dark', 'system'] as const
|
||||
type Mode = typeof modes[number]
|
||||
|
||||
const iconMap: Record<Mode, string> = {
|
||||
light: 'mdi:weather-sunny',
|
||||
dark: 'mdi:weather-night',
|
||||
system: 'mdi:monitor',
|
||||
}
|
||||
|
||||
const labelMap: Record<Mode, string> = {
|
||||
light: '浅色模式',
|
||||
dark: '深色模式',
|
||||
system: '跟随系统',
|
||||
}
|
||||
|
||||
const currentMode = computed(() => colorMode.preference as Mode)
|
||||
const currentIcon = computed(() => iconMap[currentMode.value] || iconMap.system)
|
||||
const currentLabel = computed(() => labelMap[currentMode.value] || labelMap.system)
|
||||
|
||||
function cycle() {
|
||||
const idx = modes.indexOf(currentMode.value)
|
||||
colorMode.preference = modes[(idx + 1) % modes.length]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
@click="cycle"
|
||||
class="inline-flex items-center justify-center rounded-md w-8 h-8 transition-colors"
|
||||
style="color: var(--color-text-secondary)"
|
||||
:class="[
|
||||
'hover:bg-[var(--color-bg-hover)] hover:text-[var(--color-text)]',
|
||||
]"
|
||||
:aria-label="currentLabel"
|
||||
:title="currentLabel"
|
||||
>
|
||||
<Icon :icon="currentIcon" class="w-5 h-5" />
|
||||
</button>
|
||||
</template>
|
||||
Reference in New Issue
Block a user