优化CozeAPI调用保存逻辑和前端图标修复

- 修复前端TrendingUpOutlined图标导入错误,改为LineChartOutlined
- 优化CozeAPI调用记录保存逻辑:
  * 正确保存创建人和更新人字段为当前用户ID
  * 正确传递和保存message_id字段
  * 新增带messageId的WebSocket聊天方法重载
- 修复WebSocket处理器中的用户消息保存逻辑
- 确保CozeApiCallService正确设置创建人和更新人字段
- 改进AI回复保存时的创建人设置逻辑
This commit is contained in:
2025-07-26 10:46:47 +08:00
parent 0dfabc35d7
commit 6903ac1c0d
8 changed files with 856 additions and 90 deletions
+426 -51
View File
@@ -3,59 +3,72 @@
<!-- 头部导航 -->
<AppHeader />
<div style="padding: 100px 20px 20px; background: white; text-align: center;">
<h1 style="color: #4A90E2; font-size: 3rem; margin-bottom: 20px;">
你好我是开开
</h1>
<p style="font-size: 1.5rem; color: #888; margin-bottom: 40px;">
你的情绪陪伴使者
</p>
<img
src="https://r2.flowith.net/files/1517c93c-849d-4a9b-94b6-d61aa295a8a1/1752600429516-image-1752600425876-cnlfpkbrh@1024x1024.png"
alt="开开"
style="width: 300px; height: auto; margin-bottom: 40px; border-radius: 20px;"
/>
<div>
<a-button
type="primary"
size="large"
@click="$router.push('/chat')"
style="background: #F5A623; border: none; border-radius: 20px; padding: 12px 32px; font-size: 18px;"
>
开始一段对话
</a-button>
<!-- Hero Section -->
<section class="hero-section">
<div class="wave-background">
<div class="wave"></div>
<div class="wave"></div>
<div class="wave"></div>
</div>
</div>
<div style="padding: 80px 20px; background: #F7F8FA;">
<div style="text-align: center; margin-bottom: 60px;">
<h2 style="font-size: 2rem; color: #333; margin-bottom: 16px;">发现你的专属陪伴</h2>
<p style="font-size: 18px; color: #888;">
开开博学多才从不炫耀愿意用最温柔的方式陪伴每一个需要倾听的生命
</p>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 32px; max-width: 1200px; margin: 0 auto;">
<div style="background: white; padding: 32px; border-radius: 16px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<h3 style="color: #333; margin-bottom: 16px;">智能对话</h3>
<p style="color: #888; line-height: 1.6;">从日常闲聊到情感咨询开开随时倾听理解并回应你的每个想法</p>
<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 style="background: white; padding: 32px; border-radius: 16px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<h3 style="color: #333; margin-bottom: 16px;">情绪日记</h3>
<p style="color: #888; line-height: 1.6;">记录你的点滴心情与生活开开会给予温暖的回应</p>
<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 style="background: white; padding: 32px; border-radius: 16px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<h3 style="color: #333; margin-bottom: 16px;">个人展板</h3>
<p style="color: #888; line-height: 1.6;">自由定义你的个性标签构建独一无二的数字人格</p>
</div>
<div style="background: white; padding: 32px; border-radius: 16px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
<h3 style="color: #333; margin-bottom: 16px;">话题追踪</h3>
<p style="color: #888; line-height: 1.6;">自动总结你关心的事助你洞察自我</p>
<div class="hero-action animate-fade-in-up delay-700">
<a-button
type="primary"
size="large"
@click="$router.push('/chat')"
class="start-chat-btn"
>
开始一段对话
</a-button>
</div>
</div>
</div>
</section>
<!-- 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` }"
>
<div class="feature-image-container">
<img :src="feature.image" :alt="feature.alt" class="feature-image" />
</div>
<div class="feature-content">
<div class="feature-header">
<component :is="feature.icon" class="feature-icon" />
<h3 class="feature-title">{{ feature.title }}</h3>
</div>
<p class="feature-description">{{ feature.description }}</p>
</div>
</div>
</div>
</div>
</section>
<!-- 底部 -->
<AppFooter />
@@ -63,14 +76,376 @@
</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'
// 功能特性数据
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: '充满活力的开开'
}
]
// 滚动动画观察器
let scrollObserver: IntersectionObserver | null = null
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)
})
}
</script>
<style lang="scss" scoped>
@use "@/assets/styles/variables.scss" as *;
.home-page {
min-height: 100vh;
background: #f5f5f5;
.home-page {
min-height: 100vh;
background: #f5f5f5;
}
/* 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;
@media (max-width: 768px) {
padding: 100px 16px 60px;
min-height: 80vh;
}
}
.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;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.scroll-target {
opacity: 0;
transform: translateY(30px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out;
&.visible {
opacity: 1;
transform: translateY(0);
}
}
</style>