You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.2 KiB
140 lines
3.2 KiB
<script setup lang="ts">
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import { useRouter } from 'vue-router'
|
|
import { useTheme } from '@/composables/useTheme'
|
|
|
|
const auth = useAuthStore()
|
|
const router = useRouter()
|
|
const theme = useTheme()
|
|
|
|
async function handleLogout() {
|
|
try {
|
|
await auth.logout()
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
router.push('/')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<header class="app-header">
|
|
<router-link to="/" class="brand">Mach-CMS</router-link>
|
|
<nav class="nav-links">
|
|
<router-link to="/">首页</router-link>
|
|
<router-link to="/search">搜索</router-link>
|
|
<router-link v-if="auth.isLoggedIn" to="/admin">管理后台</router-link>
|
|
<span v-if="auth.username" class="username">{{ auth.username }}</span>
|
|
<a v-if="auth.isLoggedIn" href="#" @click.prevent="handleLogout">退出</a>
|
|
<router-link v-else to="/login">登录</router-link>
|
|
</nav>
|
|
<button
|
|
class="theme-toggle"
|
|
type="button"
|
|
:title="theme.isDark ? '切至天青昼' : '切至黛墨夜'"
|
|
@click="theme.toggle()"
|
|
>{{ theme.isDark ? '昼' : '夜' }}</button>
|
|
</header>
|
|
<main class="app-main">
|
|
<router-view v-slot="{ Component }">
|
|
<transition name="page" mode="out-in">
|
|
<component :is="Component" />
|
|
</transition>
|
|
</router-view>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.app-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
padding: 0 24px;
|
|
height: 60px;
|
|
background-color: var(--ac-header-bg);
|
|
color: var(--ac-header-text);
|
|
border-bottom: 1px solid var(--ac-border);
|
|
transition: background-color var(--song-dur-2) var(--song-ease), color var(--song-dur-2) var(--song-ease);
|
|
}
|
|
|
|
.app-header .brand {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
margin-right: auto;
|
|
color: var(--ac-header-text);
|
|
font-family: var(--song-font-display);
|
|
font-size: 18px;
|
|
font-weight: 400;
|
|
letter-spacing: 0.06em;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.nav-links {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
gap: 6px;
|
|
}
|
|
|
|
.nav-links a,
|
|
.nav-links .username {
|
|
color: var(--ac-header-muted);
|
|
text-decoration: none;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.nav-links a {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
padding: 0 12px;
|
|
color: var(--ac-header-muted);
|
|
}
|
|
|
|
.nav-links a:hover {
|
|
color: var(--ac-header-text);
|
|
}
|
|
|
|
.nav-links a.router-link-active {
|
|
color: var(--ac-header-text);
|
|
background: var(--ac-header-active-bg);
|
|
}
|
|
|
|
.nav-links .username {
|
|
margin-left: 12px;
|
|
}
|
|
|
|
.theme-toggle {
|
|
width: 34px;
|
|
height: 34px;
|
|
flex-shrink: 0;
|
|
border: 1px solid var(--ac-border);
|
|
border-radius: var(--ac-radius-m);
|
|
background: transparent;
|
|
color: var(--ac-header-muted);
|
|
font-family: var(--song-font-serif);
|
|
font-size: 15px;
|
|
letter-spacing: 0.1em;
|
|
cursor: pointer;
|
|
transition: color var(--song-dur-1) var(--song-ease), border-color var(--song-dur-1) var(--song-ease), background var(--song-dur-1) var(--song-ease);
|
|
}
|
|
|
|
.theme-toggle:hover {
|
|
color: var(--ac-header-text);
|
|
border-color: var(--ac-header-muted);
|
|
background: var(--ac-header-active-bg);
|
|
}
|
|
|
|
.app-main {
|
|
max-width: 960px;
|
|
margin: 24px auto;
|
|
padding: 0 16px;
|
|
}
|
|
</style>
|