Ai_GirlFriend/xuniYou/pages/chat/simple.vue

290 lines
5.6 KiB
Vue
Raw Normal View History

<template>
<view class="chat-page">
<!-- 顶部 Tab -->
<main-tabs :current="1"></main-tabs>
<!-- 聊天内容区域 -->
<scroll-view
class="message-container"
scroll-y="true"
:scroll-top="scrollTop"
scroll-with-animation="true">
<view class="message-list">
<view
v-for="(msg, index) in messages"
:key="index"
class="message-item"
:class="msg.role === 'user' ? 'message-right' : 'message-left'">
<image
class="avatar"
:src="msg.role === 'user' ? userAvatar : loverAvatar"
mode="aspectFill">
</image>
<view class="message-bubble">
<text class="message-text">{{ msg.content }}</text>
</view>
</view>
</view>
</scroll-view>
<!-- 底部输入框 -->
<view class="input-bar">
<input
class="message-input"
v-model="inputText"
placeholder="输入消息..."
confirm-type="send"
@confirm="sendMessage"
/>
<view class="send-btn" @click="sendMessage">
<text>发送</text>
</view>
</view>
</view>
</template>
<script>
import MainTabs from '@/components/main-tabs.vue';
import { SessionInit, SessionSend } from '@/utils/api.js';
export default {
components: {
MainTabs
},
data() {
return {
messages: [],
inputText: '',
scrollTop: 0,
sessionId: null,
userAvatar: '',
loverAvatar: '',
sending: false
}
},
onLoad() {
// 获取用户头像
const userInfo = uni.getStorageSync('userinfo');
this.userAvatar = userInfo?.avatar || '/static/images/avatar.png';
// 获取恋人头像
const loverInfo = uni.getStorageSync('loverBasicList');
this.loverAvatar = loverInfo?.image_url || '/static/images/avatar.png';
// 初始化会话
this.initSession();
},
methods: {
// 初始化会话
initSession() {
uni.showLoading({ title: '加载中...' });
SessionInit().then(res => {
uni.hideLoading();
if (res.code === 1) {
this.sessionId = res.data.session_id;
// 加载历史消息只显示最近10条
const allMessages = res.data.messages || [];
this.messages = allMessages.slice(-10).map(msg => ({
role: msg.role === 'lover' ? 'ai' : 'user',
content: msg.content
}));
// 滚动到底部
this.$nextTick(() => {
this.scrollToBottom();
});
} else {
uni.showToast({ title: res.msg || '加载失败', icon: 'none' });
}
}).catch(err => {
uni.hideLoading();
console.error('初始化会话失败:', err);
uni.showToast({ title: '网络错误', icon: 'none' });
});
},
// 发送消息
sendMessage() {
if (!this.inputText.trim()) {
return;
}
if (this.sending) {
return;
}
if (!this.sessionId) {
uni.showToast({ title: '会话未初始化', icon: 'none' });
return;
}
const userMessage = this.inputText.trim();
this.inputText = '';
// 添加用户消息到列表
this.messages.push({
role: 'user',
content: userMessage
});
// 滚动到底部
this.$nextTick(() => {
this.scrollToBottom();
});
// 添加"思考中"提示
const thinkingIndex = this.messages.length;
this.messages.push({
role: 'ai',
content: '思考中...'
});
this.sending = true;
// 发送到后端
SessionSend({
session_id: this.sessionId,
message: userMessage
}).then(res => {
this.sending = false;
if (res.code === 1) {
// 移除"思考中"
this.messages.splice(thinkingIndex, 1);
// 添加 AI 回复
this.messages.push({
role: 'ai',
content: res.data.reply || '...'
});
// 滚动到底部
this.$nextTick(() => {
this.scrollToBottom();
});
} else {
// 移除"思考中"
this.messages.splice(thinkingIndex, 1);
uni.showToast({ title: res.msg || '发送失败', icon: 'none' });
}
}).catch(err => {
this.sending = false;
// 移除"思考中"
this.messages.splice(thinkingIndex, 1);
console.error('发送消息失败:', err);
uni.showToast({ title: '发送失败', icon: 'none' });
});
},
// 滚动到底部
scrollToBottom() {
this.scrollTop = 999999;
}
}
}
</script>
<style scoped>
.chat-page {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
background: #f5f5f5;
}
.message-container {
flex: 1;
margin-top: calc(80rpx + var(--status-bar-height));
margin-bottom: 120rpx;
padding: 20rpx;
}
.message-list {
width: 100%;
}
.message-item {
display: flex;
margin-bottom: 30rpx;
align-items: flex-start;
}
.message-left {
flex-direction: row;
}
.message-right {
flex-direction: row-reverse;
}
.avatar {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
flex-shrink: 0;
}
.message-bubble {
max-width: 500rpx;
padding: 20rpx 25rpx;
border-radius: 20rpx;
margin: 0 20rpx;
}
.message-left .message-bubble {
background: #fff;
border-top-left-radius: 5rpx;
}
.message-right .message-bubble {
background: linear-gradient(135deg, #9F47FF 0%, #0053FA 100%);
}
.message-text {
font-size: 28rpx;
line-height: 1.6;
word-wrap: break-word;
}
.message-left .message-text {
color: #333;
}
.message-right .message-text {
color: #fff;
}
.input-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
padding: 20rpx;
background: #fff;
border-top: 1rpx solid #e5e5e5;
z-index: 100;
}
.message-input {
flex: 1;
height: 80rpx;
padding: 0 25rpx;
background: #f5f5f5;
border-radius: 40rpx;
font-size: 28rpx;
}
.send-btn {
margin-left: 20rpx;
padding: 20rpx 40rpx;
background: linear-gradient(135deg, #9F47FF 0%, #0053FA 100%);
color: #fff;
border-radius: 40rpx;
font-size: 28rpx;
}
</style>