feat: 完成情绪博物馆项目重构和功能增强 - 新增日记评论和帖子功能 - 重构前端架构,优化用户体验 - 完善WebSocket通信机制 - 更新项目文档和部署配置

This commit is contained in:
2025-07-27 10:05:59 +08:00
parent 6903ac1c0d
commit cc886cd4d5
126 changed files with 21179 additions and 15734 deletions
+447 -398
View File
@@ -1,432 +1,415 @@
<template>
<div class="home-page">
<!-- 头部导航 -->
<AppHeader />
<!-- Header -->
<header
id="main-header"
class="fixed top-0 left-0 right-0 z-50 bg-white/80 backdrop-blur-lg transition-all duration-300"
:class="{ 'scrolled': isScrolled }"
>
<div class="container mx-auto px-6 py-4 flex justify-between items-center">
<router-link to="/" class="flex items-center space-x-2">
<svg width="32" height="32" viewBox="0 0 100 100" class="text-tech-blue">
<path fill="currentColor" d="M85.4,37.3C85.4,37.3,85.4,37.3,85.4,37.3c-2.8-9.9-10-17.7-19.1-21.2c-0.2-0.1-0.5-0.1-0.7-0.2c-0.1,0-0.2-0.1-0.3-0.1 c-1.2-0.4-2.5-0.8-3.7-1.1c-1-0.2-2-0.4-3-0.6c-1.1-0.2-2.1-0.3-3.2-0.4c-1.2-0.1-2.4-0.2-3.6-0.2c-0.1,0-0.2,0-0.3,0h-0.1 c-0.1,0-0.2,0-0.3,0c-1.2,0-2.4,0.1-3.6,0.2c-1.1,0.1-2.1,0.2-3.2,0.4c-1,0.2-2,0.4-3,0.6c-1.3,0.3-2.5,0.6-3.7,1.1 c-0.1,0-0.2,0.1-0.3,0.1c-0.2,0.1-0.5,0.1-0.7,0.2C21.6,19.6,14.4,27.4,11.6,37.3c0,0,0,0.1-0.1,0.1C8,47.7,8,58.8,11.5,69.2 c0,0.1,0.1,0.1,0.1,0.2c2.8,9.9,10,17.7,19.1,21.2c0.2,0.1,0.5,0.1,0.7,0.2c0.1,0,0.2,0.1,0.3,0.1c1.2,0.4,2.5,0.8,3.7,1.1 c1,0.2,2,0.4,3,0.6c1.1,0.2,2.1,0.3,3.2,0.4c1.2,0.1,2.4,0.2,3.6,0.2c0.1,0,0.2,0,0.3,0h0.1c0.1,0,0.2,0,0.3,0 c1.2,0,2.4-0.1,3.6-0.2c-1.1-0.1-2.1-0.2-3.2-0.4c1-0.2,2-0.4,3-0.6c1.3-0.3,2.5-0.6,3.7-1.1c0.1,0,0.2-0.1,0.3-0.1 c0.2-0.1,0.5-0.1,0.7-0.2c9.1-3.5,16.3-11.3,19.1-21.2c0-0.1,0.1-0.1,0.1-0.2C89,58.8,89,47.7,85.4,37.3z M50,77.9 c-15.4,0-27.9-12.5-27.9-27.9S34.6,22.1,50,22.1s27.9,12.5,27.9,27.9S65.4,77.9,50,77.9z"></path>
<path fill="var(--warm-orange)" d="M50,88.8c-21.4,0-38.8-17.4-38.8-38.8S28.6,11.2,50,11.2s38.8,17.4,38.8,38.8S71.4,88.8,50,88.8z M50,16.2 c-18.7,0-33.8,15.1-33.8,33.8S31.3,83.8,50,83.8s33.8-15.1,33.8-33.8S68.7,16.2,50,16.2z"></path>
</svg>
<span class="text-2xl font-bold text-tech-blue">开心APP</span>
</router-link>
<nav class="hidden lg:flex items-center space-x-8" id="nav-menu">
</nav>
<div class="flex items-center space-x-4">
<!-- 未登录状态 -->
<template v-if="!authStore.isLoggedIn">
<router-link
to="/login"
class="hidden sm:inline-block text-text-medium hover:text-tech-blue transition-colors"
>
登录
</router-link>
<router-link
to="/register"
class="hidden sm:inline-block text-text-medium hover:text-tech-blue transition-colors"
>
注册
</router-link>
<router-link
to="/chat"
class="bg-tech-blue text-white px-5 py-2.5 rounded-full font-semibold hover:bg-blue-600 transition-all duration-300 transform hover:scale-105 shadow-lg shadow-blue-500/20"
>
免费开始
</router-link>
</template>
<!-- Hero Section -->
<section class="hero-section">
<div class="wave-background">
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
</div>
<div class="hero-content">
<div class="hero-text">
<h1 class="hero-title animate-fade-in-up">
你好我是<span class="highlight">开开</span>
</h1>
<p class="hero-subtitle animate-fade-in-up delay-300">
你的情绪陪伴使者
</p>
</div>
<div class="hero-image animate-fade-in-up delay-500">
<img
src="https://r2.flowith.net/files/1517c93c-849d-4a9b-94b6-d61aa295a8a1/1752600429516-image-1752600425876-cnlfpkbrh@1024x1024.png"
alt="欢迎姿态的开开"
class="kaikai-image"
/>
</div>
<div class="hero-action animate-fade-in-up delay-700">
<a-button
type="primary"
size="large"
@click="$router.push('/chat')"
class="start-chat-btn"
<!-- 已登录状态 -->
<template v-else>
<router-link
to="/chat"
class="hidden sm:inline-block bg-tech-blue text-white px-4 py-2 rounded-full font-medium hover:bg-blue-600 transition-all duration-300"
>
开始对话
</router-link>
<UserDropdown />
</template>
<button
@click="toggleMobileMenu"
class="lg:hidden text-text-dark"
>
开始一段对话
</a-button>
<i data-lucide="menu" class="w-6 h-6"></i>
</button>
</div>
</div>
</section>
</header>
<!-- Features Section -->
<section class="features-section">
<div class="container">
<div class="features-header">
<h2 class="features-title scroll-target">核心功能</h2>
<p class="features-subtitle scroll-target">
开开博学多才可爱治愈愿意用最温柔的方式陪伴每一个需要倾听的生命
</p>
</div>
<div class="features-grid">
<div
v-for="(feature, index) in features"
:key="feature.title"
class="feature-card scroll-target"
:style="{ animationDelay: `${index * 100}ms` }"
<!-- Mobile Menu -->
<div
id="mobile-menu"
class="fixed inset-0 bg-white/90 backdrop-blur-xl z-40 p-8 lg:hidden transition-all duration-300"
:class="{ 'hidden': !mobileMenuOpen }"
>
<div class="flex justify-end mb-8">
<button @click="toggleMobileMenu" class="text-text-dark">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
</div>
<nav class="flex flex-col space-y-6 text-center" id="mobile-nav-menu">
<!-- 未登录状态 -->
<template v-if="!authStore.isLoggedIn">
<router-link
to="/login"
@click="toggleMobileMenu"
class="text-lg text-text-medium hover:text-tech-blue transition-colors py-2"
>
<div class="feature-image-container">
<img :src="feature.image" :alt="feature.alt" class="feature-image" />
登录
</router-link>
<router-link
to="/register"
@click="toggleMobileMenu"
class="text-lg text-text-medium hover:text-tech-blue transition-colors py-2"
>
注册
</router-link>
<router-link
to="/chat"
@click="toggleMobileMenu"
class="bg-tech-blue text-white px-6 py-3 rounded-full font-semibold mx-auto inline-block"
>
免费开始
</router-link>
</template>
<!-- 已登录状态 -->
<template v-else>
<div class="flex flex-col items-center space-y-4 mb-6">
<UserAvatar
:avatar="authStore.userInfo?.avatar"
:nickname="authStore.userInfo?.nickname || '用户'"
size="large"
/>
<div class="text-center">
<div class="text-lg font-semibold text-text-dark">{{ authStore.userInfo?.nickname || '用户' }}</div>
<div class="text-sm text-text-medium">{{ authStore.userInfo?.memberLevel || 'Lv.1' }}</div>
</div>
<div class="feature-content">
<div class="feature-header">
<component :is="feature.icon" class="feature-icon" />
<h3 class="feature-title">{{ feature.title }}</h3>
</div>
<router-link
to="/chat"
@click="toggleMobileMenu"
class="text-lg text-text-medium hover:text-tech-blue transition-colors py-2"
>
AI对话
</router-link>
<router-link
to="/profile"
@click="toggleMobileMenu"
class="text-lg text-text-medium hover:text-tech-blue transition-colors py-2"
>
个人中心
</router-link>
<router-link
to="/personal-dashboard"
@click="toggleMobileMenu"
class="text-lg text-text-medium hover:text-tech-blue transition-colors py-2"
>
个人仪表盘
</router-link>
<button
@click="handleMobileLogout"
class="text-lg text-red-500 hover:text-red-600 transition-colors py-2"
>
退出登录
</button>
</template>
</nav>
</div>
<main>
<!-- Hero Section -->
<section class="relative pt-32 pb-20 lg:pt-48 lg:pb-32 overflow-hidden bg-white">
<div class="absolute inset-0 z-0 opacity-20">
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
</div>
<div class="container mx-auto px-6 text-center relative z-10">
<div class="max-w-3xl mx-auto">
<h1 class="text-4xl md:text-6xl font-bold text-text-dark leading-tight mb-4 animate-fade-in-up" style="animation-delay: 0.1s;">
你好我是<span class="text-tech-blue">开开</span>
</h1>
<p class="text-xl md:text-2xl text-text-medium mb-8 animate-fade-in-up" style="animation-delay: 0.3s;">
你的情绪陪伴使者
</p>
</div>
<div class="mt-12 flex justify-center animate-fade-in-up" style="animation-delay: 0.5s;">
<img
src="https://r2.flowith.net/files/1517c93c-849d-4a9b-94b6-d61aa295a8a1/1752600429516-image-1752600425876-cnlfpkbrh@1024x1024.png"
alt="欢迎姿态的开开"
class="w-full max-w-sm h-auto drop-shadow-2xl"
style="object-fit: contain;"
>
</div>
<div class="mt-8">
<router-link
to="/chat"
class="bg-warm-orange text-white px-8 py-4 rounded-full font-bold text-lg hover:bg-orange-600 transition-all duration-300 transform hover:scale-105 inline-block shadow-lg shadow-orange-500/30 animate-fade-in-up"
style="animation-delay: 0.7s;"
>
开始一段对话
</router-link>
</div>
</div>
</section>
<!-- Features Section -->
<section class="py-20 lg:py-32 bg-light-gray">
<div class="container mx-auto px-6">
<div class="text-center max-w-3xl mx-auto mb-16">
<h2 class="text-3xl md:text-4xl font-bold text-text-dark mb-4 scroll-target">核心功能</h2>
<p class="text-lg text-text-medium scroll-target">
开开博学多才可爱治愈愿意用最温柔的方式陪伴每一个需要倾听的生命
</p>
</div>
<div id="features-grid" class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
<div
v-for="(feature, index) in features"
:key="index"
class="feature-card-bg rounded-2xl p-6 flex flex-col items-center text-center scroll-target"
:style="{ transitionDelay: `${index * 100}ms` }"
>
<div class="w-full aspect-square rounded-xl overflow-hidden mb-6 feature-card-image-container flex items-center justify-center">
<img
:src="feature.image"
:alt="feature.alt"
class="w-4/5 h-4/5 object-contain drop-shadow-lg"
>
</div>
<p class="feature-description">{{ feature.description }}</p>
<div class="flex items-center space-x-2 mb-3">
<i :data-lucide="feature.icon" class="w-5 h-5 text-tech-blue"></i>
<h3 class="text-xl font-bold text-text-dark">{{ feature.title }}</h3>
</div>
<p class="text-text-medium text-sm flex-grow">{{ feature.description }}</p>
</div>
</div>
</div>
</div>
</section>
</section>
</main>
<!-- 底部 -->
<AppFooter />
<!-- Footer -->
<footer class="bg-white">
<div class="container mx-auto px-6 py-12">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<div class="md:col-span-1">
<router-link to="/" class="flex items-center space-x-2">
<svg width="28" height="28" viewBox="0 0 100 100" class="text-tech-blue">
<path fill="currentColor" d="M85.4,37.3C85.4,37.3,85.4,37.3,85.4,37.3c-2.8-9.9-10-17.7-19.1-21.2c-0.2-0.1-0.5-0.1-0.7-0.2c-0.1,0-0.2-0.1-0.3-0.1 c-1.2-0.4-2.5-0.8-3.7-1.1c-1-0.2-2-0.4-3-0.6c-1.1-0.2-2.1-0.3-3.2-0.4c-1.2-0.1-2.4-0.2-3.6-0.2c-0.1,0-0.2,0-0.3,0h-0.1 c-0.1,0-0.2,0-0.3,0c-1.2,0-2.4,0.1-3.6,0.2c-1.1,0.1-2.1,0.2-3.2,0.4c-1,0.2-2,0.4-3,0.6c-1.3,0.3-2.5,0.6-3.7,1.1 c-0.1,0-0.2,0.1-0.3,0.1c-0.2,0.1-0.5,0.1-0.7,0.2C21.6,19.6,14.4,27.4,11.6,37.3c0,0,0,0.1-0.1,0.1C8,47.7,8,58.8,11.5,69.2 c0,0.1,0.1,0.1,0.1,0.2c2.8,9.9,10,17.7,19.1,21.2c0.2,0.1,0.5,0.1,0.7,0.2c0.1,0,0.2,0.1,0.3,0.1c1.2,0.4,2.5,0.8,3.7,1.1 c1,0.2,2,0.4,3,0.6c1.1,0.2,2.1,0.3,3.2,0.4c1.2,0.1,2.4,0.2,3.6,0.2c0.1,0,0.2,0,0.3,0h0.1c0.1,0,0.2,0,0.3,0 c1.2,0,2.4-0.1,3.6-0.2c-1.1-0.1-2.1-0.2-3.2-0.4c1-0.2,2-0.4,3-0.6c1.3-0.3,2.5-0.6,3.7-1.1c0.1,0,0.2-0.1,0.3-0.1 c0.2-0.1,0.5-0.1,0.7-0.2c9.1-3.5,16.3-11.3,19.1-21.2c0-0.1,0.1-0.1,0.1-0.2C89,58.8,89,47.7,85.4,37.3z M50,77.9 c-15.4,0-27.9-12.5-27.9-27.9S34.6,22.1,50,22.1s27.9,12.5,27.9,27.9S65.4,77.9,50,77.9z"></path>
<path fill="var(--warm-orange)" d="M50,88.8c-21.4,0-38.8-17.4-38.8-38.8S28.6,11.2,50,11.2s38.8,17.4,38.8,38.8S71.4,88.8,50,88.8z M50,16.2 c-18.7,0-33.8,15.1-33.8,33.8S31.3,83.8,50,83.8s33.8-15.1,33.8-33.8S68.7,16.2,50,16.2z"></path>
</svg>
<span class="text-xl font-bold text-tech-blue">开心APP</span>
</router-link>
<p class="mt-4 text-text-medium">陪伴理解记录共同成长</p>
</div>
<div>
<h3 class="font-semibold text-text-dark">产品</h3>
<ul class="mt-4 space-y-2">
<li><a href="#features-grid" class="text-text-medium hover:text-tech-blue">功能</a></li>
<li><router-link to="/settings" class="text-text-medium hover:text-tech-blue">定价</router-link></li>
<li><router-link to="/messages" class="text-text-medium hover:text-tech-blue">更新日志</router-link></li>
</ul>
</div>
<div>
<h3 class="font-semibold text-text-dark">公司</h3>
<ul class="mt-4 space-y-2">
<li><router-link to="/personal-dashboard" class="text-text-medium hover:text-tech-blue">关于我们</router-link></li>
<li><router-link to="/messages" class="text-text-medium hover:text-tech-blue">联系我们</router-link></li>
<li><router-link to="/settings" class="text-text-medium hover:text-tech-blue">加入我们</router-link></li>
</ul>
</div>
<div>
<h3 class="font-semibold text-text-dark">法律</h3>
<ul class="mt-4 space-y-2">
<li><router-link to="/settings" class="text-text-medium hover:text-tech-blue">隐私政策</router-link></li>
<li><router-link to="/settings" class="text-text-medium hover:text-tech-blue">服务条款</router-link></li>
</ul>
</div>
</div>
<div class="mt-12 border-t border-gray-200 pt-8 text-center text-text-medium">
<p>© 2025 开心APP. All Rights Reserved. 来自"开心"星球的温柔科技</p>
</div>
</div>
</footer>
<!-- 登录弹框已移除统一使用登录页面 -->
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { MessageOutlined, BookOutlined, UserOutlined, LineChartOutlined } from '@ant-design/icons-vue'
import AppHeader from '@/components/layout/AppHeader.vue'
import AppFooter from '@/components/layout/AppFooter.vue'
import { ref, onMounted, onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
import UserDropdown from '@/components/UserDropdown.vue'
import UserAvatar from '@/components/UserAvatar.vue'
// 功能特性数据
const features = [
{
icon: MessageOutlined,
title: '智能对话',
description: '从日常闲聊到情感咨询,开开随时倾听,理解并回应你的每个想法,是永不离线的好朋友。',
image: 'https://r2.flowith.net/files/o/1752574375721-happy_kaikai_character_design_index_0@1024x1024.png',
alt: '开心的开开'
},
{
icon: BookOutlined,
title: '情绪日记',
description: '记录你的点滴心情与生活,开开会给予温暖的回应。在安全的空间里,回顾与成长。',
image: 'https://r2.flowith.net/files/o/1752574488398-kaikai_supportive_comfort_character_index_3@1024x1024.png',
alt: '倾听中的开开'
},
{
icon: UserOutlined,
title: '个人展板',
description: '自由定义你的个性标签,开开还会自动收录你的"精彩语录",构建独一无二的数字人格。',
image: 'https://r2.flowith.net/files/o/1752574426392-kaikai_character_working_digital_workspace_index_4@1024x1024.png',
alt: '工作中的开开'
},
{
icon: LineChartOutlined,
title: '话题追踪',
description: '自动总结你关心的事,无论是生活琐事还是工作计划,都用时间线清晰整理,助你洞察自我。',
image: 'https://r2.flowith.net/files/o/1752574572161-kaikai_character_energetic_animation_index_2@1024x1024.png',
alt: '充满活力的开开'
}
]
const router = useRouter()
const authStore = useAuthStore()
// 滚动动画观察器
let scrollObserver: IntersectionObserver | null = null
// 响应式数据
const isScrolled = ref(false)
const mobileMenuOpen = ref(false)
onMounted(() => {
// 初始化滚动动画
initScrollAnimations()
})
onUnmounted(() => {
if (scrollObserver) {
scrollObserver.disconnect()
}
})
const initScrollAnimations = () => {
scrollObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible')
scrollObserver?.unobserve(entry.target)
}
})
},
{ threshold: 0.1 }
)
// 观察所有需要动画的元素
document.querySelectorAll('.scroll-target').forEach((target) => {
scrollObserver?.observe(target)
})
// 功能特性数据
const features = ref([
{
icon: 'message-circle',
title: '智能对话',
description: '从日常闲聊到情感咨询,开开随时倾听,理解并回应你的每个想法,是永不离线的好朋友。',
image: 'https://r2.flowith.net/files/o/1752574375721-happy_kaikai_character_design_index_0@1024x1024.png',
alt: '开心的开开'
},
{
icon: 'book-open-text',
title: '情绪日记',
description: '记录你的点滴心情与生活,开开会给予温暖的回应。在安全的空间里,回顾与成长。',
image: 'https://r2.flowith.net/files/o/1752574488398-kaikai_supportive_comfort_character_index_3@1024x1024.png',
alt: '倾听中的开开'
},
{
icon: 'user-round-cog',
title: '个人展板',
description: '自由定义你的个性标签,开开还会自动收录你的"精彩语录",构建独一无二的数字人格。',
image: 'https://r2.flowith.net/files/o/1752574426392-kaikai_character_working_digital_workspace_index_4@1024x1024.png',
alt: '工作中的开开'
},
{
icon: 'trending-up',
title: '话题追踪',
description: '自动总结你关心的事,无论是生活琐事还是工作计划,都用时间线清晰整理,助你洞察自我。',
image: 'https://r2.flowith.net/files/o/1752574572161-kaikai_character_energetic_animation_index_2@1024x1024.png',
alt: '充满活力的开开'
}
])
// 滚动监听
const handleScroll = () => {
isScrolled.value = window.scrollY > 10
}
// 移动端菜单切换
const toggleMobileMenu = () => {
mobileMenuOpen.value = !mobileMenuOpen.value
}
/**
* 处理移动端登出
*/
const handleMobileLogout = async () => {
try {
await authStore.logout()
toggleMobileMenu()
ElMessage.success('已退出登录')
} catch (error) {
console.error('登出失败:', error)
ElMessage.error('登出失败')
}
}
// 移除登录弹框相关方法
// 生命周期
onMounted(async () => {
window.addEventListener('scroll', handleScroll)
// 静默恢复本地认证状态(不进行API调用)
if (!authStore.isLoggedIn) {
console.log('🏠 首页静默恢复认证状态')
authStore.restoreLocalAuth()
}
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()
}
// 设置滚动观察器
const scrollObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible')
observer.unobserve(entry.target)
}
})
}, { threshold: 0.1 })
// 观察所有滚动目标
document.querySelectorAll('.scroll-target').forEach(target => {
scrollObserver.observe(target)
})
// 延迟初始化图标,确保DOM已渲染
setTimeout(() => {
if (window.lucide) {
window.lucide.createIcons()
}
}, 100)
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
</script>
<style lang="scss" scoped>
@use "@/assets/styles/variables.scss" as *;
.home-page {
min-height: 100vh;
background: #f5f5f5;
<style scoped>
/* 导入原始样式变量 */
:root {
--tech-blue: #4A90E2;
--warm-orange: #F5A623;
--white: #FFFFFF;
--light-gray: #F7F8FA;
--text-dark: #333333;
--text-medium: #888888;
}
/* Hero Section */
.hero-section {
position: relative;
padding: 128px 24px 80px;
background: white;
text-align: center;
overflow: hidden;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
/* 应用原始样式类 */
.bg-tech-blue { background-color: var(--tech-blue); }
.bg-warm-orange { background-color: var(--warm-orange); }
.bg-light-gray { background-color: var(--light-gray); }
.text-tech-blue { color: var(--tech-blue); }
.text-text-dark { color: var(--text-dark); }
.text-text-medium { color: var(--text-medium); }
.border-tech-blue { border-color: var(--tech-blue); }
@media (max-width: 768px) {
padding: 100px 16px 60px;
min-height: 80vh;
}
#main-header.scrolled {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
border-bottom-color: #e5e7eb;
}
.wave-background {
position: absolute;
inset: 0;
opacity: 0.2;
z-index: 0;
}
.wave {
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTQ0MCAxNDciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PHRpdGxlPmdyb3VwPC90aXRsZT48ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyBpZD0iQ29tcG9uZW50LS0tV2F2ZS1Cb3R0b20iIGZpbGw9IiM0QTkwRTIiPjxwYXRoIGQ9Ik0wLDc0LjgzMjk0MTIgQzM2MCw3NC44MzI5NDEyIDM2MCwxNDcgNzIwLDE0NyBDMTA4MCwxNDcgMTA4MCw3NC44MzI5NDEyIDE0NDAsNzQuODMyOTQxMiBMMTQ0MCwxNDcgTDAsMTQ3IEwwLDc0LjgzMjk0MTIgWiIgaWQ9IldhdmUiIG9wYWNpdHk9IjAuMSI+PC9wYXRoPjwvZz48L2c+PC9zdmc+");
position: absolute;
bottom: 0;
left: 0;
width: 200%;
height: 147px;
animation: wave 15s linear infinite;
&:nth-child(2) {
animation-direction: reverse;
animation-duration: 20s;
opacity: 0.8;
}
&:nth-child(3) {
animation-duration: 25s;
opacity: 0.5;
}
}
@keyframes wave {
0% { transform: translateX(0); }
50% { transform: translateX(-50%); }
100% { transform: translateX(0); }
}
.hero-content {
position: relative;
z-index: 10;
max-width: 768px;
margin: 0 auto;
}
.hero-title {
font-size: 4rem;
font-weight: 700;
color: $text-dark;
line-height: 1.2;
margin-bottom: 16px;
@media (max-width: 768px) {
font-size: 2.5rem;
}
.highlight {
color: $tech-blue;
}
}
.hero-subtitle {
font-size: 1.5rem;
color: $text-medium;
margin-bottom: 48px;
@media (max-width: 768px) {
font-size: 1.25rem;
margin-bottom: 32px;
}
}
.hero-image {
margin-bottom: 32px;
.kaikai-image {
width: 100%;
max-width: 400px;
height: auto;
border-radius: 20px;
filter: drop-shadow(0 20px 40px rgba(0, 0, 0, 0.1));
@media (max-width: 768px) {
max-width: 300px;
}
}
}
.start-chat-btn {
background: $warm-orange !important;
border: none !important;
border-radius: 50px !important;
padding: 16px 32px !important;
font-size: 18px !important;
font-weight: 600 !important;
height: auto !important;
box-shadow: 0 8px 24px rgba(245, 166, 35, 0.3) !important;
transition: all 0.3s ease !important;
&:hover {
background: #e6951f !important;
transform: translateY(-2px) !important;
box-shadow: 0 12px 32px rgba(245, 166, 35, 0.4) !important;
}
@media (max-width: 768px) {
padding: 12px 24px !important;
font-size: 16px !important;
}
}
/* Features Section */
.features-section {
padding: 80px 24px;
background: $light-gray;
@media (max-width: 768px) {
padding: 60px 16px;
}
}
.features-header {
text-align: center;
max-width: 768px;
margin: 0 auto 64px;
@media (max-width: 768px) {
margin-bottom: 48px;
}
}
.features-title {
font-size: 2.5rem;
font-weight: 700;
color: $text-dark;
margin-bottom: 16px;
@media (max-width: 768px) {
font-size: 2rem;
}
}
.features-subtitle {
font-size: 1.125rem;
color: $text-medium;
line-height: 1.6;
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 32px;
max-width: 1024px;
margin: 0 auto;
@media (max-width: 768px) {
grid-template-columns: 1fr;
gap: 24px;
}
}
.feature-card {
background: white;
border-radius: 16px;
padding: 32px;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #e5e7eb;
transition: all 0.3s ease;
opacity: 0;
transform: translateY(30px);
&:hover {
transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12);
}
&.visible {
opacity: 1;
transform: translateY(0);
}
@media (max-width: 768px) {
padding: 24px;
}
}
.feature-image-container {
width: 100%;
aspect-ratio: 1;
border-radius: 12px;
overflow: hidden;
margin-bottom: 24px;
background: linear-gradient(135deg, #eef5fe 0%, #f0f8ff 100%);
background-image: url('data:image/svg+xml;utf8,<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M-10 10 C 20 20, 40 0, 60 10 S 100 0, 120 10" stroke="%234A90E2" fill="none" stroke-width="2" stroke-opacity="0.2"/></svg>');
background-size: 50px;
background-repeat: repeat;
display: flex;
align-items: center;
justify-content: center;
}
.feature-image {
width: 80%;
height: 80%;
object-fit: contain;
filter: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.1));
}
.feature-content {
flex: 1;
}
.feature-header {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-bottom: 12px;
}
.feature-icon {
width: 20px;
height: 20px;
color: $tech-blue;
}
.feature-title {
font-size: 1.25rem;
font-weight: 600;
color: $text-dark;
margin: 0;
}
.feature-description {
color: $text-medium;
line-height: 1.6;
margin: 0;
}
/* 动画效果 */
.animate-fade-in-up {
animation: fade-in-up 0.8s ease-out forwards;
opacity: 0;
}
.delay-300 {
animation-delay: 0.3s;
}
.delay-500 {
animation-delay: 0.5s;
}
.delay-700 {
animation-delay: 0.7s;
}
@keyframes fade-in-up {
from {
opacity: 0;
@@ -442,10 +425,76 @@
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
&.visible {
.scroll-target.visible {
opacity: 1;
transform: translateY(0);
}
.wave {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiB2aWV3Qm94PSIwIDAgMTQ0MCAxNDciIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+PHRpdGxlPmdyb3VwPC90aXRsZT48ZyBpZD0iUGFnZS0xIiBzdHJva2U9Im5vbmUiIHN0cm9rZS13aWR0aD0iMSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyBpZD0iQ29tcG9uZW50LS0tV2F2ZS1Cb3R0b20iIGZpbGw9IiM0QTkwRTIiPjxwYXRoIGQ9Ik0wLDc0LjgzMjk0MTIgQzM2MCw3NC44MzI5NDEyIDM2MCwxNDcgNzIwLDE0NyBDMTA4MCwxNDcgMTA4MCw3NC44MzI5NDEyIDE0NDAsNzQuODMyOTQxMiBMMTQ0MCwxNDcgTDAsMTQ3IEwwLDc0LjgzMjk0MTIgWiIgaWQ9IldhdmUiIG9wYWNpdHk9IjAuMSI+PC9wYXRoPjwvZz48L2c+PC9zdmc+);
position: absolute;
bottom: 0;
left: 0;
width: 200%;
height: 147px;
animation: wave 15s linear infinite;
}
.wave:nth-of-type(2) {
animation-direction: reverse;
animation-duration: 20s;
opacity: 0.8;
}
.wave:nth-of-type(3) {
animation-duration: 25s;
opacity: 0.5;
}
@keyframes wave {
0% { transform: translateX(0); }
50% { transform: translateX(-50%); }
100% { transform: translateX(0); }
}
#login-modal:not(.hidden) {
animation: modal-fade-in 0.2s ease-out forwards;
}
#login-modal:not(.hidden) > div {
animation: modal-scale-up 0.2s ease-out forwards;
}
@keyframes modal-fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
@keyframes modal-scale-up {
from {
transform: scale(0.95);
}
to {
transform: scale(1);
}
}
/* 移除了验证码相关样式 */
/* 全局样式 */
body {
font-family: 'Noto Sans SC', sans-serif;
}
.home-page {
font-family: 'Noto Sans SC', sans-serif;
background-color: var(--light-gray);
color: var(--text-dark);
}
</style>