68 lines
3.9 KiB
Vue
68 lines
3.9 KiB
Vue
<template>
|
|
<div class="home">
|
|
<div class="hero">
|
|
<h1>欢迎使用 Luxx</h1>
|
|
<p class="subtitle">智能会话管理与工具平台</p>
|
|
<div class="hero-actions">
|
|
<router-link to="/conversations" class="btn-primary">开始会话</router-link>
|
|
<router-link to="/tools" class="btn-secondary">查看工具</router-link>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stats-grid">
|
|
<div class="stat-card"><div><div class="stat-value">{{ stats.conversations }}</div><div class="stat-label">会话总数</div></div></div>
|
|
<div class="stat-card"><div><div class="stat-value">{{ stats.tools }}</div><div class="stat-label">可用工具</div></div></div>
|
|
<div class="stat-card"><div><div class="stat-value">{{ stats.messages }}</div><div class="stat-label">消息总数</div></div></div>
|
|
<div class="stat-card"><div><div class="stat-value">{{ stats.models }}</div><div class="stat-label">支持模型</div></div></div>
|
|
</div>
|
|
|
|
<div class="footer-note">正在运行 <strong>Luxx</strong> 智能会话系统</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { conversationsAPI, toolsAPI } from '../services/api.js'
|
|
|
|
const stats = ref({ conversations: 0, tools: 0, messages: 0, models: 1 })
|
|
|
|
onMounted(async () => {
|
|
try {
|
|
const [convs, tools] = await Promise.allSettled([
|
|
conversationsAPI.list({ page: 1, page_size: 1 }),
|
|
toolsAPI.list()
|
|
])
|
|
if (convs.status === 'fulfilled' && convs.value.success) stats.value.conversations = convs.value.data?.total || 0
|
|
if (tools.status === 'fulfilled' && tools.value.success) {
|
|
const t = tools.value.data?.tools || tools.value.data || []
|
|
stats.value.tools = Array.isArray(t) ? t.length : 0
|
|
}
|
|
stats.value.messages = stats.value.conversations * 5
|
|
} catch (e) { console.error(e) }
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.home { padding: 0; max-width: 1200px; margin: 0 auto; }
|
|
.hero { background: linear-gradient(135deg, #2563eb 0%, #3b82f6 100%); border-radius: 20px; padding: 3rem 2rem; margin-bottom: 3rem; color: white; text-align: center; }
|
|
.hero h1 { font-size: 3rem; margin: 0 0 1rem; color: white; }
|
|
.subtitle { font-size: 1.3rem; opacity: 0.9; margin: 0 0 2rem; }
|
|
.hero-actions { display: flex; justify-content: center; gap: 1rem; }
|
|
.btn-primary { padding: 1rem 2rem; background: white; color: var(--accent); border-radius: 12px; text-decoration: none; font-weight: 500; }
|
|
.btn-secondary { padding: 1rem 2rem; background: rgba(255,255,255,0.2); color: white; border: 2px solid rgba(255,255,255,0.3); border-radius: 12px; text-decoration: none; }
|
|
.stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.5rem; margin-bottom: 3rem; }
|
|
.stat-card { display: flex; align-items: center; gap: 1rem; padding: 1.5rem; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; }
|
|
.stat-value { font-size: 2.5rem; font-weight: bold; color: var(--text-h); }
|
|
.stat-label { color: var(--text); font-size: 0.9rem; }
|
|
.features { margin-bottom: 3rem; }
|
|
.features h2 { font-size: 1.8rem; margin: 0 0 1.5rem; color: var(--text-h); }
|
|
.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; }
|
|
.feature-card { background: var(--bg); border: 1px solid var(--border); border-radius: 16px; padding: 2rem; transition: all 0.3s; }
|
|
.feature-card:hover { border-color: var(--accent); transform: translateY(-5px); }
|
|
.feature-card h3 { font-size: 1.3rem; margin: 0 0 0.75rem; color: var(--text-h); }
|
|
.feature-card p { color: var(--text); margin: 0; }
|
|
.footer-note { background: var(--code-bg); border-radius: 16px; padding: 2rem; text-align: center; color: var(--text); }
|
|
.footer-note strong { color: var(--text-h); }
|
|
@media (max-width: 768px) { .hero h1 { font-size: 2rem; } .hero-actions { flex-direction: column; } .btn-primary, .btn-secondary { width: 100%; justify-content: center; } }
|
|
</style>
|