diff --git a/pages/contact/index.js b/pages/contact/index.js
index 391d0e1..d3fc2c7 100644
--- a/pages/contact/index.js
+++ b/pages/contact/index.js
@@ -24,6 +24,10 @@ Page({
isAtBottom: true,
// 正在加载更多(顶部分页)
loadingMore: false,
+ // 新消息提醒相关状态
+ showNewMessageTip: false, // 是否显示新消息提醒
+ newMessageCount: 0, // 新消息数量
+ lastMessageId: '', // 最后一条消息的ID,用于检测新消息
},
/**
@@ -68,12 +72,27 @@ Page({
// 根据ID进行排序,确保ID最大的(最新的)消息在最后
const sortedList = that.sortMessagesByID(list);
- that.setData({
+ // 智能滚动逻辑:用户在底部时自动滚动,在上方时保持位置
+ const updateData = {
messages: sortedList,
- total: res.total,
- // only auto-scroll if user is at bottom
- scrollToId: that.data.isAtBottom ? (sortedList[sortedList.length - 1] ? sortedList[sortedList.length - 1].id : '') : that.data.scrollToId
- });
+ total: res.total
+ };
+
+ that.setData(updateData);
+
+ // 如果用户在底部,延迟设置滚动ID确保滚动生效
+ if (that.data.isAtBottom && sortedList.length > 0) {
+ const lastMessageId = sortedList[sortedList.length - 1].id;
+ console.log('用户在底部,准备自动滚动到消息ID:', lastMessageId);
+ setTimeout(() => {
+ that.setData({
+ scrollToId: lastMessageId
+ });
+ console.log('已设置scrollToId:', lastMessageId);
+ }, 50);
+ } else {
+ console.log('用户不在底部或无消息,保持当前位置。isAtBottom:', that.data.isAtBottom, '消息数量:', sortedList.length);
+ }
return res; // 返回结果以支持链式调用
});
@@ -130,7 +149,7 @@ Page({
// 统一的消息处理函数
processMessages(messageList) {
- return messageList.map((item, index) => {
+ const processedMessages = messageList.map((item, index) => {
// 优先使用服务器返回的ID,如果没有则使用创建时间戳
if (item.id && !item.id.toString().startsWith('m') && !item.id.toString().startsWith('u')) {
item.id = 'm' + item.id;
@@ -154,6 +173,44 @@ Page({
return item;
});
+
+ // 检测新消息并显示提醒
+ this.checkNewMessages(processedMessages);
+
+ return processedMessages;
+ },
+
+ // 检测新消息的函数
+ checkNewMessages(newMessages) {
+ if (newMessages.length === 0) return;
+
+ const currentMessages = this.data.messages;
+ const currentLastMessageId = this.data.lastMessageId;
+ const sortedNewMessages = this.sortMessagesByID(newMessages);
+ const latestNewMessage = sortedNewMessages[sortedNewMessages.length - 1];
+
+ // 如果不在底部且有新消息
+ if (!this.data.isAtBottom && currentMessages.length > 0) {
+ // 找出真正的新消息(在当前消息列表中不存在的消息)
+ const currentMessageIds = new Set(currentMessages.map(msg => msg.id));
+ const realNewMessages = sortedNewMessages.filter(msg => !currentMessageIds.has(msg.id));
+
+ if (realNewMessages.length > 0) {
+ // 累加新消息数量(而不是重置)
+ const currentCount = this.data.newMessageCount || 0;
+ this.setData({
+ showNewMessageTip: true,
+ newMessageCount: currentCount + realNewMessages.length
+ });
+ }
+ }
+
+ // 更新最后一条消息ID
+ if (latestNewMessage) {
+ this.setData({
+ lastMessageId: latestNewMessage.id
+ });
+ }
},
// 消息排序函数
@@ -246,13 +303,15 @@ Page({
// e.detail.scrollTop increases when scrolling down. We want to detect upward scroll.
const scrollTop = e.detail.scrollTop || 0;
const last = this._lastScrollTop || 0;
- // If user scrolls up (new scrollTop < last), pause polling
+ // If user scrolls up (new scrollTop < last), mark as not at bottom but keep polling
if (scrollTop < last) {
// user scrolled up
if (this.data.isAtBottom) {
- // only act if we were previously at bottom
+ // only update state if we were previously at bottom, but keep polling active
+ console.log('用户向上滚动,设置isAtBottom为false');
this.setData({ isAtBottom: false });
- this.stopPolling();
+ // 注释掉停止轮询的逻辑,确保始终获取新消息
+ // this.stopPolling();
}
}
// detect reaching near top to load more
@@ -267,14 +326,31 @@ Page({
},
onScrollToLower() {
- // user scrolled to bottom (or very near). resume polling if needed
+ // user scrolled to bottom (or very near). update state and ensure polling is active
+ console.log('用户滚动到底部,当前isAtBottom状态:', this.data.isAtBottom);
if (!this.data.isAtBottom) {
- this.setData({ isAtBottom: true });
+ this.setData({
+ isAtBottom: true,
+ showNewMessageTip: false,
+ newMessageCount: 0
+ });
+ console.log('已设置isAtBottom为true');
+ // 确保轮询始终运行(即使之前已经在运行)
this.startPolling();
// also ensure we scroll to latest message next render
const lastId = this.data.messages[this.data.messages.length - 1] ? this.data.messages[this.data.messages.length - 1].id : '';
if (lastId) {
this.setData({ scrollToId: lastId });
+ console.log('设置scrollToId到最新消息:', lastId);
+ }
+ } else {
+ // 即使已经在底部,也要隐藏新消息提醒
+ if (this.data.showNewMessageTip) {
+ this.setData({
+ showNewMessageTip: false,
+ newMessageCount: 0
+ });
+ console.log('隐藏新消息提醒');
}
}
},
@@ -507,6 +583,30 @@ Page({
wx.stopPullDownRefresh();
}
},
+
+ // 点击新消息提醒,滚动到底部
+ scrollToBottom() {
+ const messages = this.data.messages;
+ if (messages.length > 0) {
+ const sortedMessages = this.sortMessagesByID(messages);
+ const latestMessage = sortedMessages[sortedMessages.length - 1];
+
+ this.setData({
+ scrollToId: latestMessage.id,
+ showNewMessageTip: false,
+ newMessageCount: 0,
+ isAtBottom: true
+ });
+
+ // 延迟一下确保滚动完成
+ setTimeout(() => {
+ this.setData({
+ scrollToId: ''
+ });
+ }, 100);
+ }
+ },
+
onReachBottom() { },
onShareAppMessage() { }
});
\ No newline at end of file
diff --git a/pages/contact/index.wxml b/pages/contact/index.wxml
index 75caa3c..6ea8533 100644
--- a/pages/contact/index.wxml
+++ b/pages/contact/index.wxml
@@ -33,6 +33,14 @@
+
+
+
+ {{newMessageCount}}条新消息
+ ↓
+
+
+
diff --git a/pages/contact/index.wxss b/pages/contact/index.wxss
index a1d71f5..b8b7b8e 100644
--- a/pages/contact/index.wxss
+++ b/pages/contact/index.wxss
@@ -314,4 +314,57 @@
order: 2; /* same as previous .bubble order for service */
margin-left: 8rpx; /* match bubble spacing */
margin-right: 0;
+}
+
+/* 新消息提醒样式 */
+.new-message-tip {
+ position: fixed;
+ bottom: 200rpx;
+ right: 30rpx;
+ z-index: 1000;
+ animation: tipFadeIn 0.3s ease-in-out;
+}
+
+.tip-content {
+ background: #07c160;
+ color: white;
+ padding: 16rpx 24rpx;
+ border-radius: 40rpx;
+ display: flex;
+ align-items: center;
+ box-shadow: 0 4rpx 12rpx rgba(7, 193, 96, 0.3);
+ font-size: 28rpx;
+}
+
+.tip-text {
+ margin-right: 8rpx;
+}
+
+.tip-arrow {
+ font-size: 24rpx;
+ font-weight: bold;
+ animation: bounce 1s infinite;
+}
+
+@keyframes tipFadeIn {
+ from {
+ opacity: 0;
+ transform: translateY(20rpx);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes bounce {
+ 0%, 20%, 50%, 80%, 100% {
+ transform: translateY(0);
+ }
+ 40% {
+ transform: translateY(-6rpx);
+ }
+ 60% {
+ transform: translateY(-3rpx);
+ }
}
\ No newline at end of file
diff --git a/测试说明.md b/测试说明.md
new file mode 100644
index 0000000..bedfc02
--- /dev/null
+++ b/测试说明.md
@@ -0,0 +1,73 @@
+# 自动滚动修复测试说明
+
+## 修复内容
+已修复聊天页面自动刷新后自动滚动到底部的问题,现在实现智能滚动:
+
+### 修复的问题
+- ✅ 轮询刷新时不再强制滚动到底部
+- ✅ 用户在底部时,新消息会自动滚动显示
+- ✅ 用户在上方浏览历史消息时,保持当前位置
+- ✅ 添加了延迟处理确保滚动生效
+
+### 修改的文件
+- `pages/contact/index.js` - 修改了 `getMessages()` 函数的滚动逻辑
+
+## 测试步骤
+
+### 1. 打开项目
+1. 使用微信开发者工具打开项目目录:`/Users/win/code2025/wx-chant`
+2. 确保项目配置正确,appid 已设置
+
+### 2. 测试场景
+
+#### 场景1:用户在底部时的自动滚动
+1. 进入聊天页面
+2. 滚动到最底部
+3. 等待新消息到达(轮询刷新)
+4. **预期结果**:新消息自动滚动到视图中
+
+#### 场景2:用户在上方时保持位置
+1. 进入聊天页面
+2. 向上滚动查看历史消息
+3. 等待新消息到达(轮询刷新)
+4. **预期结果**:
+ - 滚动位置保持不变
+ - 显示新消息提醒气泡
+ - 点击气泡可滚动到最新消息
+
+#### 场景3:用户发送消息时的自动滚动
+1. 在聊天页面发送文本或图片消息
+2. **预期结果**:自动滚动到刚发送的消息
+
+### 3. 调试信息
+已添加控制台日志,可在微信开发者工具的控制台中查看:
+- 滚动状态变化
+- 自动滚动触发情况
+- scrollToId 设置情况
+
+### 4. 关键日志信息
+- `用户在底部,准备自动滚动到消息ID: xxx` - 触发自动滚动
+- `用户不在底部或无消息,保持当前位置` - 保持位置
+- `用户向上滚动,设置isAtBottom为false` - 状态变化
+- `用户滚动到底部,当前isAtBottom状态: xxx` - 到达底部
+
+## 技术实现
+
+### 核心逻辑
+```javascript
+// 智能滚动:先更新数据,再延迟设置滚动
+that.setData(updateData);
+
+if (that.data.isAtBottom && sortedList.length > 0) {
+ setTimeout(() => {
+ that.setData({
+ scrollToId: lastMessageId
+ });
+ }, 50);
+}
+```
+
+### 状态管理
+- `isAtBottom`: 标记用户是否在聊天底部
+- `scrollToId`: 控制滚动到指定消息
+- 延迟50ms确保DOM更新后再滚动
\ No newline at end of file