This commit is contained in:
aaron 2025-05-09 12:39:07 +08:00
parent c2b949919f
commit 30502d1c3e
5 changed files with 659 additions and 197 deletions

View File

@ -5,8 +5,8 @@ services:
build:
context: .
dockerfile: Dockerfile
image: icrypto-web:1.0.13
container_name: icrypto-web
image: tradus-web:1.0.13
container_name: tradus-web
ports:
- '6000:80'
restart: unless-stopped

View File

@ -7,7 +7,7 @@
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<title>Crypto.AI - AI Agent for Web3</title>
<title>tradus - AI Agent for trading</title>
<style>
html,
body {

View File

@ -6,86 +6,140 @@ import { useUserStore } from './stores/user'
const userStore = useUserStore()
const isAuthenticated = computed(() => userStore.isAuthenticated)
const userInfo = computed(() => userStore.userInfo)
const showUserMenu = ref(false)
const showMobileMenu = ref(false)
const handleLogout = () => {
userStore.logout()
if (window.location.pathname.includes('/user')) {
window.location.href = '/'
}
showUserMenu.value = false
showMobileMenu.value = false
}
const toggleUserMenu = () => {
showUserMenu.value = !showUserMenu.value
const toggleMobileMenu = () => {
showMobileMenu.value = !showMobileMenu.value
}
//
const closeUserMenu = (event: MouseEvent) => {
const closeMenus = (event: MouseEvent) => {
const target = event.target as HTMLElement
if (!target.closest('.user-section')) {
showUserMenu.value = false
if (!target.closest('.mobile-menu') && !target.closest('.menu-button')) {
showMobileMenu.value = false
}
}
onMounted(() => {
document.addEventListener('click', closeUserMenu)
document.addEventListener('click', closeMenus)
})
onUnmounted(() => {
document.removeEventListener('click', closeUserMenu)
document.removeEventListener('click', closeMenus)
})
</script>
<template>
<div class="app-container">
<!-- 移动端菜单按钮 -->
<button class="menu-button" @click="toggleMobileMenu">
<svg
viewBox="0 0 24 24"
width="24"
height="24"
stroke="currentColor"
stroke-width="2"
fill="none"
>
<path d="M3 12h18M3 6h18M3 18h18" />
</svg>
</button>
<!-- 左侧栏 -->
<aside class="sidebar">
<aside class="sidebar" :class="{ 'sidebar-open': showMobileMenu }">
<div class="sidebar-content">
<!-- 网站标题 -->
<div class="site-title">
<span class="title-text">AI Trade</span>
<span class="title-text">tradus</span>
<div class="subtitle-text">AI for Trading</div>
</div>
<!-- Agent 列表 -->
<div class="agent-list">
<RouterLink to="/" class="agent-item">
<span class="agent-icon">🏠</span>
<RouterLink to="/" class="agent-item" @click="showMobileMenu = false">
<svg
class="agent-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
<span class="agent-name">首页</span>
</RouterLink>
<RouterLink to="/ai-agent" class="agent-item">
<span class="agent-icon">🤖</span>
<RouterLink to="/ai-agent" class="agent-item" @click="showMobileMenu = false">
<svg
class="agent-icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
/>
</svg>
<span class="agent-name">AI 助手</span>
</RouterLink>
</div>
</div>
</aside>
<!-- 右侧对话区域 -->
<main class="chat-container">
<div class="chat-content">
<RouterView />
</div>
<!-- 用户信息区域 -->
<div class="user-section" v-if="isAuthenticated">
<div class="user-info-box" @click="toggleUserMenu">
<!-- 桌面端用户信息 -->
<div class="desktop-user-info" v-if="isAuthenticated">
<div class="user-info-box">
<div class="user-avatar">
<span>{{ userInfo?.nickname?.charAt(0) || 'U' }}</span>
</div>
<span class="user-nickname">{{ userInfo?.nickname }}</span>
</div>
<!-- 用户菜单 -->
<div v-if="showUserMenu" class="user-menu">
<button class="menu-item" @click="handleLogout">退出登录</button>
<button class="logout-button" @click="handleLogout">退出登录</button>
</div>
</div>
<div v-else class="user-section">
<div class="auth-buttons">
<div class="desktop-user-info" v-else>
<RouterLink to="/login" class="auth-link">登录</RouterLink>
<RouterLink to="/register" class="auth-link register-link">注册</RouterLink>
<RouterLink to="/register" class="auth-link">注册</RouterLink>
</div>
<!-- 移动端用户信息 -->
<div class="mobile-user-info" v-if="isAuthenticated">
<div class="user-info-box">
<div class="user-avatar">
<span>{{ userInfo?.nickname?.charAt(0) || 'U' }}</span>
</div>
<span class="user-nickname">{{ userInfo?.nickname }}</span>
</div>
<button class="logout-button" @click="handleLogout">退出登录</button>
</div>
<div class="mobile-user-info" v-else>
<RouterLink to="/login" class="mobile-auth-link" @click="showMobileMenu = false"
>登录</RouterLink
>
<RouterLink to="/register" class="mobile-auth-link" @click="showMobileMenu = false"
>注册</RouterLink
>
</div>
</div>
</aside>
<!-- 遮罩层 -->
<div class="sidebar-overlay" v-if="showMobileMenu" @click="showMobileMenu = false"></div>
<!-- 右侧对话区域 -->
<main class="chat-container">
<div class="chat-content">
<RouterView />
</div>
</main>
</div>
@ -94,22 +148,21 @@ onUnmounted(() => {
<style>
:root {
--color-bg-primary: #ffffff;
--color-bg-secondary: #f8f9fa;
--color-bg-elevated: #ffffff;
--color-bg-card: #f8f9fa;
--color-bg-secondary: #f8fafc;
--color-bg-hover: rgba(51, 85, 255, 0.04);
--color-bg-active: rgba(51, 85, 255, 0.08);
--color-text-primary: #2c3e50;
--color-text-secondary: #6c757d;
--color-text-tertiary: #8c98a4;
--color-text-disabled: #adb5bd;
--color-divider: rgba(0, 0, 0, 0.1);
--color-border: rgba(0, 0, 0, 0.1);
--color-border-hover: rgba(0, 0, 0, 0.2);
--color-text-primary: #1e293b;
--color-text-secondary: #64748b;
--color-text-tertiary: #94a3b8;
--color-accent: #3355ff;
--color-accent-hover: #2244ee;
--color-accent-light: rgba(51, 85, 255, 0.1);
--color-accent-hover: #4466ff;
--color-accent-active: #2244ee;
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
--font-weight-light: 300;
--font-weight-regular: 400;
@ -156,8 +209,8 @@ body {
.sidebar {
width: var(--sidebar-width);
height: 100vh;
background-color: var(--color-bg-elevated);
border-right: 1px solid var(--color-border);
background-color: var(--color-bg-secondary);
border-right: 1px solid rgba(0, 0, 0, 0.06);
display: flex;
flex-direction: column;
}
@ -173,7 +226,7 @@ body {
.site-title {
padding: 2rem 1.5rem;
text-align: center;
border-bottom: 1px solid var(--color-divider);
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.title-text {
@ -214,7 +267,7 @@ body {
/* Agent 列表样式 */
.agent-list {
flex: 1;
padding: 1rem;
padding: 0.75rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
@ -226,28 +279,33 @@ body {
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
color: var(--color-text-primary);
color: var(--color-text-secondary);
text-decoration: none;
border-radius: var(--border-radius);
transition: background-color 0.2s ease;
border-radius: 8px;
transition: all 0.2s ease;
}
.agent-item:hover {
background-color: var(--color-bg-secondary);
background-color: var(--color-bg-hover);
color: var(--color-text-primary);
}
.agent-item.router-link-active {
background-color: var(--color-accent-light);
background-color: var(--color-bg-active);
color: var(--color-accent);
}
.agent-icon {
font-size: 1.25rem;
width: 20px;
height: 20px;
flex-shrink: 0;
stroke: currentColor;
}
.agent-name {
font-size: 0.95rem;
font-weight: var(--font-weight-medium);
font-weight: 500;
letter-spacing: 0.01em;
}
/* 修改用户信息区域样式 */
@ -258,39 +316,48 @@ body {
width: var(--sidebar-width);
background-color: var(--color-bg-elevated);
border-radius: 0;
padding: 1rem;
padding: 1.25rem;
z-index: 100;
cursor: pointer;
transition: all 0.2s ease;
border-top: 1px solid var(--color-divider);
border: 1px solid var(--color-border);
box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.05);
}
.user-section:hover {
background-color: var(--color-bg-secondary);
transform: translateY(-1px);
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
}
.user-info-box {
display: flex;
align-items: center;
gap: 0.75rem;
gap: 1rem;
}
.user-avatar {
width: 2.5rem;
height: 2.5rem;
width: 2.75rem;
height: 2.75rem;
border-radius: 50%;
background: var(--color-accent-light);
background: var(--color-bg-hover);
display: flex;
align-items: center;
justify-content: center;
font-size: 1rem;
font-size: 1.1rem;
color: var(--color-accent);
font-weight: bold;
box-shadow: 0 2px 8px rgba(51, 85, 255, 0.2);
transition: all 0.2s ease;
}
.user-section:hover .user-avatar {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(51, 85, 255, 0.3);
}
.user-nickname {
font-size: 0.95rem;
font-size: 1rem;
font-weight: var(--font-weight-medium);
color: var(--color-text-primary);
}
@ -346,6 +413,19 @@ body {
.subtitle-text {
font-size: 0.8rem;
}
.agent-item {
padding: 0.875rem 1rem;
}
.agent-icon {
width: 18px;
height: 18px;
}
.agent-name {
font-size: 0.9rem;
}
}
/* 右侧对话区域样式 */
@ -412,27 +492,263 @@ body {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}
/* 移动端菜单按钮 */
.menu-button {
display: none;
position: fixed;
top: 1rem;
left: 1rem;
z-index: 1000;
background: none;
border: none;
color: var(--color-text-primary);
cursor: pointer;
padding: 0.75rem;
border-radius: var(--border-radius);
background-color: var(--color-bg-secondary);
border: 1px solid rgba(0, 0, 0, 0.06);
transition: all 0.2s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.menu-button:hover {
background-color: var(--color-bg-hover);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.menu-button:active {
transform: translateY(0);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* 遮罩层 */
.sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.2);
z-index: 90;
backdrop-filter: blur(2px);
opacity: 0;
transition: opacity 0.3s ease;
}
.sidebar-overlay.sidebar-open {
opacity: 1;
}
/* 移动端用户信息 */
.mobile-user-info {
display: none;
padding: 1rem;
border-top: 1px solid var(--color-border);
margin-top: auto;
}
.mobile-auth-link {
display: block;
padding: 0.75rem 1rem;
color: var(--color-text-primary);
text-decoration: none;
border-radius: var(--border-radius);
transition: all 0.2s ease;
text-align: center;
margin: 0.5rem 0;
background-color: var(--color-bg-secondary);
}
.mobile-auth-link:hover {
background-color: var(--color-bg-elevated);
}
.logout-button {
display: block;
width: 100%;
padding: 0.75rem 1rem;
margin-top: 1rem;
background-color: var(--color-bg-hover);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: var(--border-radius);
color: var(--color-text-primary);
cursor: pointer;
transition: all 0.2s ease;
}
.logout-button:hover {
background-color: var(--color-bg-active);
border-color: var(--color-accent);
color: var(--color-accent);
}
/* 响应式设计 */
@media (max-width: 768px) {
:root {
--sidebar-width: 100%;
.menu-button {
display: block;
z-index: 1001;
}
.sidebar {
position: fixed;
left: 0;
left: -100%;
top: 0;
z-index: 100;
transform: translateX(-100%);
transition: transform 0.3s ease;
bottom: 0;
width: 80% !important;
max-width: 300px;
z-index: 1002;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background-color: var(--color-bg-elevated);
box-shadow: 4px 0 16px rgba(0, 0, 0, 0.1);
transform: translateX(0);
opacity: 0;
}
.sidebar-open {
transform: translateX(0);
left: 0;
opacity: 1;
}
.sidebar-overlay {
display: block;
z-index: 1000;
}
.mobile-user-info {
display: block;
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.user-section {
display: none;
}
.chat-container {
margin-left: 0;
padding-top: 4rem;
}
.agent-item {
transform: translateX(-10px);
opacity: 0;
animation: slideIn 0.3s ease forwards;
}
.agent-item:nth-child(1) {
animation-delay: 0.1s;
}
.agent-item:nth-child(2) {
animation-delay: 0.2s;
}
@keyframes slideIn {
from {
transform: translateX(-10px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
}
/* 桌面端用户信息样式 */
.desktop-user-info {
display: flex;
flex-direction: column;
padding: 1.25rem;
margin-top: auto;
border-top: 1px solid rgba(0, 0, 0, 0.06);
background-color: var(--color-bg-secondary);
}
.desktop-user-info .user-info-box {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.desktop-user-info .user-avatar {
width: 2.75rem;
height: 2.75rem;
border-radius: 50%;
background: var(--color-bg-hover);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.1rem;
color: var(--color-accent);
font-weight: bold;
box-shadow: 0 2px 8px rgba(51, 85, 255, 0.2);
transition: all 0.2s ease;
}
.desktop-user-info .user-nickname {
font-size: 1rem;
font-weight: var(--font-weight-medium);
color: var(--color-text-primary);
}
.desktop-user-info .auth-link {
display: block;
padding: 0.75rem 1rem;
color: var(--color-text-primary);
text-decoration: none;
border-radius: var(--border-radius);
transition: all 0.2s ease;
text-align: center;
margin: 0.5rem 0;
background-color: var(--color-bg-hover);
}
.desktop-user-info .auth-link:hover {
background-color: var(--color-bg-active);
color: var(--color-accent);
}
.desktop-user-info .logout-button {
display: block;
width: 100%;
padding: 0.75rem 1rem;
background-color: var(--color-bg-hover);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: var(--border-radius);
color: var(--color-text-primary);
cursor: pointer;
transition: all 0.2s ease;
font-size: 0.95rem;
}
.desktop-user-info .logout-button:hover {
background-color: var(--color-bg-active);
border-color: var(--color-accent);
color: var(--color-accent);
}
/* 移动端适配 */
@media (max-width: 768px) {
.desktop-user-info {
display: none;
}
.mobile-user-info {
display: block;
}
}
</style>

View File

@ -432,7 +432,7 @@ onUnmounted(() => {
<style scoped>
.ai-agent-view {
width: 100%;
height: calc(100vh - var(--header-height));
height: 100%;
position: relative;
display: flex;
flex-direction: column;
@ -580,6 +580,7 @@ onUnmounted(() => {
min-width: 0;
min-height: 0;
background-color: var(--color-bg-primary);
height: 100%;
}
.chat-window {
@ -591,12 +592,14 @@ onUnmounted(() => {
margin: 0 auto;
box-sizing: border-box;
width: 100%;
position: relative;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 2rem 0.5rem;
padding-bottom: 2rem;
scroll-behavior: smooth;
display: flex;
flex-direction: column;
@ -683,12 +686,13 @@ onUnmounted(() => {
.input-container {
padding: 1.5rem 2rem;
background-color: var(--color-bg-primary);
border-top: 1px solid var(--color-border);
width: 100%;
max-width: 900px;
margin: 0 auto;
box-sizing: border-box;
}
.input-wrapper {
/* max-width: 48rem; */
margin: 0 auto;
position: relative;
display: flex;
align-items: flex-end;
@ -697,20 +701,19 @@ onUnmounted(() => {
.message-input {
flex: 1;
height: 3.5rem;
min-height: 2.5rem;
max-height: 8rem;
padding: 0.75rem 1rem;
padding-right: 3rem;
height: 3rem;
min-height: 3rem;
max-height: 6rem;
padding: 0.75rem 3rem 0.75rem 1rem;
background-color: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
color: var(--color-text-primary);
font-size: 1rem;
line-height: 1rem;
line-height: 1.4;
resize: none;
outline: none;
transition: border-color 0.2s ease;
transition: all 0.2s ease;
}
.message-input::placeholder {
@ -827,42 +830,79 @@ onUnmounted(() => {
.agent-selector-button {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
background-color: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
gap: 0.75rem;
padding: 0.75rem 1.25rem;
background-color: #ffffff;
border: 1px solid rgba(51, 85, 255, 0.2);
border-radius: 12px;
color: var(--color-text-primary);
cursor: pointer;
transition: all 0.2s ease;
font-weight: 500;
box-shadow: 0 2px 8px rgba(51, 85, 255, 0.08);
min-width: 160px;
}
.agent-selector-button:hover {
background-color: var(--color-bg-secondary);
border-color: var(--color-accent);
background-color: rgba(51, 85, 255, 0.04);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(51, 85, 255, 0.12);
}
.agent-selector-button .agent-icon {
font-size: 1.25rem;
color: var(--color-accent);
}
.agent-selector-button .agent-name {
font-size: 0.95rem;
color: var(--color-text-primary);
flex: 1;
}
.agent-selector-button::after {
content: '▼';
font-size: 0.8rem;
color: var(--color-accent);
opacity: 0.8;
transition: transform 0.2s ease;
}
.agent-selector-menu {
position: absolute;
top: 100%;
top: calc(100% + 0.5rem);
right: 0;
margin-top: 0.5rem;
background-color: var(--color-bg-elevated);
border: 1px solid var(--color-border);
border-radius: var(--border-radius);
min-width: 200px;
max-width: 300px;
background-color: #ffffff;
border: 1px solid rgba(51, 85, 255, 0.15);
border-radius: 12px;
min-width: 280px;
max-width: 320px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
box-shadow: 0 4px 20px rgba(51, 85, 255, 0.15);
animation: slideDown 0.2s ease;
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.agent-menu-item {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
padding: 1rem;
cursor: pointer;
transition: all 0.2s ease;
border-bottom: 1px solid var(--color-border);
border-bottom: 1px solid rgba(51, 85, 255, 0.08);
background-color: #ffffff;
}
.agent-menu-item:last-child {
@ -870,15 +910,23 @@ onUnmounted(() => {
}
.agent-menu-item:hover {
background-color: var(--color-bg-secondary);
background-color: rgba(51, 85, 255, 0.04);
}
.agent-menu-item.active {
background-color: var(--color-bg-secondary);
background-color: rgba(51, 85, 255, 0.08);
}
.agent-menu-item .agent-icon {
font-size: 1.25rem;
font-size: 1.5rem;
color: var(--color-accent);
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(51, 85, 255, 0.08);
border-radius: 8px;
}
.agent-menu-item .agent-info {
@ -887,50 +935,118 @@ onUnmounted(() => {
}
.agent-menu-item .agent-name {
font-weight: 500;
font-weight: 600;
color: var(--color-text-primary);
margin-bottom: 0.25rem;
font-size: 0.95rem;
}
.agent-menu-item .agent-description {
font-size: 0.75rem;
font-size: 0.85rem;
color: var(--color-text-secondary);
line-height: 1.4;
}
.agent-loading {
padding: 1rem;
text-align: center;
color: var(--color-text-secondary);
}
/* 移动端适配 */
@media (max-width: 768px) {
.agent-selector {
top: 0.5rem;
.ai-agent-view {
height: 100%;
}
.main-container {
height: 100%;
padding-bottom: env(safe-area-inset-bottom);
}
.messages-container {
padding: 1rem 0.5rem;
padding-bottom: calc(5rem + env(safe-area-inset-bottom));
}
.input-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 0.75rem;
padding-bottom: calc(0.75rem + env(safe-area-inset-bottom));
background-color: var(--color-bg-elevated);
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
z-index: 100;
border-top: 1px solid var(--color-border);
}
.input-wrapper {
max-width: 900px;
margin: 0 auto;
}
.message-input {
font-size: 16px; /* 防止 iOS 自动缩放 */
padding: 0.6rem 2.5rem 0.6rem 0.75rem;
min-height: 2.5rem;
height: 2.5rem;
}
.send-button {
width: 1.8rem;
height: 1.8rem;
right: 0.5rem;
bottom: 0.35rem;
}
.send-icon {
font-size: 0.9rem;
}
.agent-selector {
top: 0.75rem;
right: 0.75rem;
}
.agent-selector-button {
padding: 0.6rem 1rem;
min-width: 140px;
font-size: 0.9rem;
}
.agent-selector-menu {
min-width: 260px;
max-width: calc(100vw - 2rem);
right: -0.75rem;
}
.agent-menu-item {
padding: 0.875rem;
}
.agent-menu-item .agent-icon {
font-size: 1.25rem;
width: 28px;
height: 28px;
}
}
@media (max-width: 480px) {
.agent-selector {
max-height: 50px;
.messages-container {
padding: 0.75rem 0.5rem;
padding-bottom: calc(4rem + env(safe-area-inset-bottom));
}
.agent-menu-item {
padding: 0.4rem;
min-width: 100px;
.input-container {
padding: 0.5rem;
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom));
}
.agent-name {
font-size: 0.8rem;
}
.message {
padding: 0.75rem;
}
.input-field {
font-size: 0.9rem;
.message-content {
padding: 0.75rem;
font-size: 0.95rem;
}
}

View File

@ -11,8 +11,8 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
<div class="home-view">
<section class="hero-section">
<div class="hero-content">
<h1 class="hero-title"><span class="accent">AI Agent for Web3</span></h1>
<p class="hero-subtitle">立刻加入开启 Web3 + AI 新时代</p>
<h1 class="hero-title"><span class="accent">Tradus</span></h1>
<p class="hero-subtitle">AI Agent for trading</p>
<div class="hero-actions">
<!-- 未登录状态显示登录和注册按钮 -->
<template v-if="!isAuthenticated">
@ -48,11 +48,12 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
.hero-section {
text-align: center;
padding: 2rem;
padding: 6rem 2rem;
position: relative;
overflow: hidden;
width: 100%;
max-width: 900px;
max-width: 1200px;
margin: 0 auto;
}
.hero-section::before {
@ -62,7 +63,7 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at top right, rgba(59, 130, 246, 0.05), transparent 70%);
background: radial-gradient(circle at top right, rgba(51, 85, 255, 0.03), transparent 70%);
}
.hero-content {
@ -71,14 +72,12 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
}
.hero-title {
font-size: 3.5rem;
font-size: 5rem;
font-weight: 800;
margin-bottom: 1.5rem;
line-height: 1.2;
background: linear-gradient(135deg, var(--color-accent) 0%, #3355ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1.1;
letter-spacing: -0.02em;
color: #3355ff;
}
.accent {
@ -89,21 +88,24 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
.accent::after {
content: '';
position: absolute;
bottom: 5px;
bottom: 8px;
left: 0;
width: 100%;
height: 8px;
background-color: var(--color-accent-light);
height: 12px;
background-color: rgba(51, 85, 255, 0.1);
z-index: -1;
border-radius: 4px;
opacity: 0.3;
border-radius: 6px;
opacity: 0.5;
transform: skewX(-12deg);
}
.hero-subtitle {
font-size: 1.2rem;
color: var(--color-text-secondary);
font-size: 1.5rem;
color: #6c757d;
max-width: 700px;
margin: 0 auto 3rem;
margin: 0 auto 4rem;
letter-spacing: -0.01em;
font-weight: 400;
}
.hero-actions {
@ -113,92 +115,120 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)
margin-top: 2rem;
}
.discord-link {
margin-top: 3rem;
}
.discord-text {
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--color-text-secondary);
text-decoration: none;
font-size: 0.9rem;
transition: color 0.2s ease;
justify-content: center;
}
.discord-text:hover {
color: var(--color-text-primary);
}
.discord-icon {
width: 16px;
height: 16px;
}
.btn {
padding: 0.8rem 1.6rem;
border-radius: 6px;
padding: 1rem 2rem;
border-radius: 8px;
font-weight: 600;
font-size: 1rem;
font-size: 1.1rem;
cursor: pointer;
transition: all 0.2s ease;
border: none;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 160px;
}
.btn-primary {
background-color: #3355ff;
color: white;
font-weight: var(--font-weight-bold);
border: none;
box-shadow: 0 4px 6px rgba(51, 85, 255, 0.1);
}
.btn-primary:hover {
background-color: #2244ee;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(51, 85, 255, 0.3);
box-shadow: 0 6px 12px rgba(51, 85, 255, 0.2);
}
.btn-secondary {
background-color: transparent;
color: var(--color-text-primary);
border: 1px solid var(--color-border);
background-color: rgba(51, 85, 255, 0.1);
color: #3355ff;
border: none;
}
.btn-secondary:hover {
background-color: rgba(255, 255, 255, 0.05);
background-color: rgba(51, 85, 255, 0.15);
transform: translateY(-2px);
}
.discord-link {
margin-top: 4rem;
opacity: 0.8;
transition: opacity 0.3s ease;
}
.discord-link:hover {
opacity: 1;
}
.discord-text {
display: inline-flex;
align-items: center;
gap: 0.75rem;
color: #6c757d;
text-decoration: none;
font-size: 1rem;
transition: all 0.3s ease;
padding: 0.75rem 1.5rem;
border-radius: 8px;
background-color: rgba(108, 117, 125, 0.1);
}
.discord-text:hover {
color: #3355ff;
background-color: rgba(51, 85, 255, 0.1);
transform: translateY(-1px);
}
.discord-icon {
width: 20px;
height: 20px;
}
@media (max-width: 768px) {
.hero-section {
padding: 4rem 1.5rem;
}
.hero-title {
font-size: 2.5rem;
font-size: 3.5rem;
}
.hero-subtitle {
font-size: 1.25rem;
margin-bottom: 3rem;
}
.btn {
padding: 0.875rem 1.75rem;
font-size: 1rem;
margin-bottom: 2rem;
}
.hero-actions {
flex-direction: column;
align-items: center;
gap: 1rem;
}
.hero-section {
padding: 2rem 1rem;
min-width: 140px;
}
}
@media (max-width: 480px) {
.hero-title {
font-size: 2rem;
.hero-section {
padding: 3rem 1rem;
}
.hero-section {
padding: 1.5rem 1rem;
.hero-title {
font-size: 2.75rem;
}
.hero-subtitle {
font-size: 1.1rem;
margin-bottom: 2.5rem;
}
.hero-actions {
flex-direction: column;
gap: 1rem;
}
.btn {
width: 100%;
}
}
</style>