Files
InsightRadar/frontend/src/views/HomeView.vue
T
stardrophere f4d9b2075c 改名
2026-04-02 01:25:30 +08:00

302 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 概览页展示当前账户会话状态认证接入说明 -->
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import ThemeToggle from '@/components/ThemeToggle.vue'
import { useAuthStore } from '@/stores/auth'
import BrandLogo from '@/components/BrandLogo.vue'
const authStore = useAuthStore()
const router = useRouter()
const displayName = computed(() => authStore.user?.nickname || authStore.user?.email || '用户')
const tokenExpiryText = computed(() => {
if (!authStore.expiresAt) {
return '未知'
}
return new Date(authStore.expiresAt).toLocaleString('zh-CN')
})
async function handleLogout() {
authStore.logout()
await router.replace('/login')
}
</script>
<template>
<div class="dashboard-layout">
<header class="top-nav">
<div class="nav-container">
<div class="nav-brand">
<div class="logo">
<BrandLogo />
聚势智见
</div>
</div>
<div class="nav-actions">
<ThemeToggle />
<div class="divider"></div>
<button class="btn-ghost" type="button" @click="handleLogout">退出登录</button>
</div>
</div>
</header>
<main class="dashboard-main">
<div class="page-header">
<h1>概览</h1>
<p>欢迎回来{{ displayName }}这里是您的全局事件中心</p>
</div>
<div class="bento-grid">
<article class="bento-card">
<div class="card-icon">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
</div>
<p class="card-label">当前账户</p>
<h2 class="card-value">{{ displayName }}</h2>
<p class="card-meta">{{ authStore.user?.email }}</p>
</article>
<article class="bento-card">
<div class="card-icon" :class="authStore.isAuthenticated ? 'text-success' : ''">
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
/>
</svg>
</div>
<p class="card-label">会话状态</p>
<h2 class="card-value">{{ authStore.isAuthenticated ? '安全连接中' : '未登录' }}</h2>
<p class="card-meta">有效期至{{ tokenExpiryText }}</p>
</article>
<article class="bento-card col-span-full feature-card">
<div class="feature-content">
<p class="card-label">开发者接入</p>
<h2 class="card-value">认证体系已就绪</h2>
<p class="card-meta">在请求您的业务接口时请在 Headers 中携带如下凭证</p>
<div class="code-snippet">
<code>Authorization: Bearer {token}</code>
</div>
</div>
</article>
</div>
</main>
</div>
</template>
<style scoped>
.dashboard-layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* 顶部导航 */
.top-nav {
background-color: var(--bg-surface);
border-bottom: 1px solid var(--border-subtle);
position: sticky;
top: 0;
z-index: 10;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
}
.nav-brand {
display: flex;
align-items: center;
gap: 10px;
font-weight: 600;
font-size: 16px;
}
.logo-dot {
width: 10px;
height: 10px;
background: var(--brand-primary);
border-radius: 3px;
}
.logo {
display: flex;
align-items: center;
gap: 12px;
font-size: 23px;
font-weight: 700;
}
.nav-actions {
display: flex;
align-items: center;
gap: 16px;
}
.divider {
width: 1px;
height: 20px;
background-color: var(--border-strong);
}
.btn-ghost {
font-size: 14px;
font-weight: 500;
color: var(--text-secondary);
padding: 6px 12px;
border-radius: var(--radius-md);
transition: all 0.2s;
}
.btn-ghost:hover {
background-color: var(--bg-input);
color: var(--text-primary);
}
/* 主内容区 */
.dashboard-main {
flex: 1;
max-width: 1000px;
margin: 0 auto;
width: 100%;
padding: 48px 24px;
}
.page-header {
margin-bottom: 40px;
}
.page-header h1 {
font-size: 32px;
font-weight: 700;
margin: 0 0 8px 0;
letter-spacing: -0.02em;
}
.page-header p {
font-size: 16px;
color: var(--text-secondary);
margin: 0;
}
/* Bento Grid */
.bento-grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 20px;
}
@media (min-width: 768px) {
.bento-grid {
grid-template-columns: repeat(2, 1fr);
}
.col-span-full {
grid-column: 1 / -1;
}
}
.bento-card {
background-color: var(--bg-surface);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-xl);
padding: 24px;
box-shadow: var(--shadow-sm);
transition:
box-shadow 0.3s ease,
border-color 0.3s ease;
}
.bento-card:hover {
box-shadow: var(--shadow-md);
border-color: var(--border-strong);
}
.card-icon {
width: 40px;
height: 40px;
border-radius: var(--radius-lg);
background-color: var(--bg-input);
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
color: var(--text-secondary);
}
.card-icon svg {
width: 20px;
height: 20px;
}
.text-success {
color: var(--status-success);
background-color: rgba(16, 185, 129, 0.1);
}
.card-label {
font-size: 13px;
font-weight: 600;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 0 0 8px 0;
}
.card-value {
font-size: 24px;
font-weight: 700;
margin: 0 0 8px 0;
color: var(--text-primary);
}
.card-meta {
font-size: 14px;
color: var(--text-secondary);
margin: 0;
}
/* 强调卡片 */
.feature-card {
position: relative;
overflow: hidden;
}
.feature-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--brand-primary), #818cf8);
}
.code-snippet {
margin-top: 16px;
background-color: var(--bg-input);
border: 1px solid var(--border-subtle);
padding: 12px 16px;
border-radius: var(--radius-md);
font-family: monospace;
font-size: 14px;
color: var(--brand-primary);
}
</style>