1.完成ai聊天页面新

This commit is contained in:
2025-08-14 11:42:34 +08:00
parent d3b5f50a2a
commit 114a30acb8
7 changed files with 881 additions and 42 deletions

View File

@@ -1,20 +1,18 @@
<template>
<view class="chat-container">
<!-- 状态栏占位 -->
<view class="status-bar-placeholder"></view>
<!-- 自定义导航栏 -->
<!-- <view class="status-bar-placeholder"></view>
<view class="custom-nav-bar">
<!-- 左侧历史记录图标触发抽屉 -->
<view class="nav-left" @click="toggleHistoryDrawer">
<image src="/static/history.svg" mode="aspectFit" class="nav-icon"></image>
</view>
<!-- 中间标题 -->
<view class="nav-title">智水AI辅导员</view>
</view>
</view> -->
<!-- 消息列表 -->
<scroll-view scroll-y class="message-list" :scroll-top="scrollTop" scroll-with-animation enable-passive="true"
<scroll-view scroll-y class="message-list" :scroll-top="scrollTop" scroll-with-animation="true"
show-scrollbar="false" enhanced="true" bounces="true"
@scroll="onScroll" @scrolltoupper="loadMoreHistory" upper-threshold="50">
<!-- 加载提示 -->
<view v-if="isLoadingHistory" class="loading-history">
@@ -86,17 +84,17 @@
<!-- 消息输入框 -->
<input v-model="inputMessage" placeholder="输入消息..." @confirm="sendMessage" confirm-type="send" />
<!-- 添加图片按钮 -->
<img src="/static/add.svg" class="add-icon" @click="selectImage" />
<!-- <img src="/static/add.svg" class="add-icon" @click="selectImage" /> -->
<!-- 发送消息按钮 -->
<img src="/static/send.svg" class="send-icon" @click="sendMessage" />
<button class="send-button" @click="sendMessage">发送</button>
</view>
<!-- 悬浮按钮固定在右下角 -->
<view class="ai-hover" @click="goHome">
<!-- <view class="ai-hover" @click="goHome">
<view class="ai-hover-content">
<text class="ai-hover-text">AI</text>
</view>
</view>
</view> -->
</view>
</template>
@@ -174,7 +172,7 @@
// 第二次尝试处理iOS等需要额外触发的设备
setTimeout(() => {
this.forceScrollToBottom(30); // 使用稍小的偏移量
this.forceScrollToBottom(); // 确保滚动到底部
// 第三次确保(针对动态内容加载的情况)
if (attempt < 2) {
@@ -210,6 +208,19 @@
});
},
/**
* 页面显示时触发
*/
onShow() {
// 页面显示时确保滚动到底部
this.$nextTick(() => {
setTimeout(() => {
console.log('onShow: 尝试滚动到底部');
this.forceScrollToBottom();
}, 200);
});
},
/* ---------- 方法 ---------- */
methods: {
/**
@@ -223,28 +234,53 @@
/**
* 强制滚动到底部
* @param {number} offset - 额外的偏移量,默认为50
* @param {number} offset - 额外的偏移量默认为0
*/
forceScrollToBottom(offset = 50) {
forceScrollToBottom(offset = 0) {
console.log('forceScrollToBottom: 开始执行滚动');
this.$nextTick(() => {
try {
const query = uni.createSelectorQuery().in(this);
query.select('.message-list').boundingClientRect(rect => {
if (rect) {
const targetScrollTop = rect.scrollHeight - rect.height - offset;
this.scrollTop = targetScrollTop;
// 双重确保滚动生效
setTimeout(() => {
this.scrollTop = targetScrollTop + 1;
query.select('.message-list').scrollOffset(res => {
if (res) {
console.log('forceScrollToBottom: 获取到scrollOffset', res);
console.log('forceScrollToBottom: 当前scrollTop', this.scrollTop);
// 使用scrollHeight如果没有则使用一个大值
const scrollHeight = res.scrollHeight || 99999;
const targetScrollTop = scrollHeight + 1000;
// 先重置scrollTop然后设置到底部
this.scrollTop = 0;
this.$nextTick(() => {
this.scrollTop = targetScrollTop;
console.log('forceScrollToBottom: 设置scrollTop为', targetScrollTop);
// 延迟再次确保滚动到底部
setTimeout(() => {
this.scrollTop = targetScrollTop;
}, 50);
}, 100);
const finalScrollTop = (res.scrollHeight || 99999) + 1000;
this.scrollTop = finalScrollTop;
console.log('forceScrollToBottom: 延迟设置scrollTop完成', finalScrollTop);
}, 100);
});
} else {
console.log('forceScrollToBottom: 未获取到scrollOffset');
// 直接使用备用方案
this.scrollTop = 0;
this.$nextTick(() => {
this.scrollTop = 99999;
console.log('forceScrollToBottom: 使用备用方案1');
});
}
}).exec();
} catch (error) {
console.error('滚动到底部失败:', error);
// 备用方案:直接设置一个很大的值
this.scrollTop = 0;
this.$nextTick(() => {
this.scrollTop = 99999;
console.log('forceScrollToBottom: 使用备用方案2');
});
}
});
},
@@ -620,6 +656,9 @@
});
this.inputMessage = '';
this.saveMessagesToLocal(); // 保存用户消息
// 立即滚动到底部显示用户消息
this.forceScrollToBottom();
// 添加AI消息占位
const aiIdx = this.messages.push({
@@ -703,7 +742,7 @@
}
// 最终完成后再次确保滚动到底部
this.forceScrollToTop();
this.forceScrollToBottom();
}
} catch (e) {
console.warn('JSON解析失败:', line, e);
@@ -741,13 +780,22 @@
this.$nextTick(() => {
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('.message-list').boundingClientRect(rect => {
if (rect) {
// 确保滚动到最底部
this.scrollTop = rect.scrollHeight;
}
}).exec();
try {
const query = uni.createSelectorQuery().in(this);
query.select('.message-list').scrollOffset(res => {
if (res && res.scrollHeight) {
// 使用大值确保滚动到最底部
this.scrollTop = res.scrollHeight + 1000;
} else {
// 备用方案
this.scrollTop = 99999;
}
}).exec();
} catch (error) {
console.error('滚动失败:', error);
// 备用方案
this.scrollTop = 99999;
}
}, isStreaming ? 50 : 100);
});
},