feat(聊天): 添加自动发送欢迎消息功能并优化滚动逻辑
- 新增首次进入聊天页面自动发送"你好"消息功能 - 使用本地存储确保每个用户只发送一次欢迎消息 - 优化智能滚动逻辑,保持用户浏览位置 - 支持静默登录和已登录用户两种场景
This commit is contained in:
parent
0af7fc4ec5
commit
908502d5c1
@ -10,7 +10,7 @@ Page({
|
|||||||
messages: [],
|
messages: [],
|
||||||
inputText: '',
|
inputText: '',
|
||||||
scrollToId: '',
|
scrollToId: '',
|
||||||
// 使用本地头像
|
// 头像
|
||||||
userAvatar: '/static/user.png',
|
userAvatar: '/static/user.png',
|
||||||
serviceAvatar: '/static/contact.png',
|
serviceAvatar: '/static/contact.png',
|
||||||
showGetUser: false,
|
showGetUser: false,
|
||||||
@ -20,14 +20,16 @@ Page({
|
|||||||
page_size: 100,
|
page_size: 100,
|
||||||
openid: '',
|
openid: '',
|
||||||
total: 0,
|
total: 0,
|
||||||
// 是否滚动在底部
|
// 滚动状态
|
||||||
isAtBottom: true,
|
isAtBottom: true,
|
||||||
// 正在加载更多(顶部分页)
|
// 加载状态
|
||||||
loadingMore: false,
|
loadingMore: false,
|
||||||
// 新消息提醒相关状态
|
// 新消息提醒
|
||||||
showNewMessageTip: false, // 是否显示新消息提醒
|
showNewMessageTip: false, // 是否显示新消息提醒
|
||||||
newMessageCount: 0, // 新消息数量
|
newMessageCount: 0, // 新消息数量
|
||||||
lastMessageId: '', // 最后一条消息的ID,用于检测新消息
|
lastMessageId: '', // 最后一条消息的ID,用于检测新消息
|
||||||
|
// 欢迎消息标记
|
||||||
|
hasWelcomeMessageSent: false, // 是否已发送欢迎消息
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +47,10 @@ Page({
|
|||||||
showGetUser: false,
|
showGetUser: false,
|
||||||
userInfo: wx.getStorageSync('user_info'),
|
userInfo: wx.getStorageSync('user_info'),
|
||||||
});
|
});
|
||||||
this.getMessages()
|
this.getMessages().then(() => {
|
||||||
|
// 在获取消息完成后发送欢迎消息
|
||||||
|
this.sendWelcomeMessage();
|
||||||
|
});
|
||||||
// start polling when page loads and user is present
|
// start polling when page loads and user is present
|
||||||
this.startPolling();
|
this.startPolling();
|
||||||
} else {
|
} else {
|
||||||
@ -262,7 +267,10 @@ Page({
|
|||||||
"user_id": resp.openid,
|
"user_id": resp.openid,
|
||||||
"user_name": resp.user_name || '微信用户'
|
"user_name": resp.user_name || '微信用户'
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
that.getMessages()
|
that.getMessages().then(() => {
|
||||||
|
// 在获取消息完成后发送欢迎消息
|
||||||
|
that.sendWelcomeMessage();
|
||||||
|
});
|
||||||
// start polling once user info exists
|
// start polling once user info exists
|
||||||
that.startPolling();
|
that.startPolling();
|
||||||
});
|
});
|
||||||
@ -373,6 +381,82 @@ Page({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 发送欢迎消息
|
||||||
|
sendWelcomeMessage() {
|
||||||
|
// 检查用户信息是否存在
|
||||||
|
if (!this.data.userInfo || !this.data.userInfo.openid) {
|
||||||
|
console.log('用户信息不存在,无法发送欢迎消息');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用用户ID作为标记,检查是否已经发送过欢迎消息
|
||||||
|
const welcomeKey = `welcome_sent_${this.data.userInfo.openid}`;
|
||||||
|
const hasWelcomeSent = wx.getStorageSync(welcomeKey);
|
||||||
|
|
||||||
|
if (hasWelcomeSent) {
|
||||||
|
console.log('该用户的欢迎消息已发送过,跳过');
|
||||||
|
this.setData({ hasWelcomeMessageSent: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const welcomeText = '你好';
|
||||||
|
const now = new Date();
|
||||||
|
const id = 'welcome_' + Date.now();
|
||||||
|
|
||||||
|
const msg = {
|
||||||
|
id,
|
||||||
|
content: {
|
||||||
|
messages: welcomeText
|
||||||
|
},
|
||||||
|
"msg_type": 1,
|
||||||
|
receiver_id: '',
|
||||||
|
send_time: "刚刚",
|
||||||
|
sender_id: this.data.userInfo.openid,
|
||||||
|
sender_name: this.data.userInfo.user_name
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加新消息并重新排序
|
||||||
|
const newMessages = this.data.messages.concat(msg);
|
||||||
|
const sortedMessages = this.sortMessagesByID(newMessages);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
messages: sortedMessages,
|
||||||
|
hasWelcomeMessageSent: true // 标记已发送欢迎消息
|
||||||
|
});
|
||||||
|
|
||||||
|
const accountInfo = wx.getAccountInfoSync();
|
||||||
|
const userInfo = wx.getStorageSync('user_info');
|
||||||
|
|
||||||
|
console.log('发送欢迎消息:', welcomeText);
|
||||||
|
|
||||||
|
// 发送到服务器
|
||||||
|
request('app/send_message', 'POST', {
|
||||||
|
"app_id": accountInfo.miniProgram.appId,
|
||||||
|
"content": JSON.stringify({
|
||||||
|
messages: welcomeText
|
||||||
|
}),
|
||||||
|
"from_user_id": userInfo.openid,
|
||||||
|
"from_user_name": userInfo.user_name,
|
||||||
|
"msg_type": 1
|
||||||
|
}).then(() => {
|
||||||
|
console.log('欢迎消息发送成功');
|
||||||
|
// 保存标记到本地存储,表示该用户已发送过欢迎消息
|
||||||
|
wx.setStorageSync(welcomeKey, true);
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('欢迎消息发送失败:', err);
|
||||||
|
// 如果发送失败,不保存标记,下次还可以重试
|
||||||
|
});
|
||||||
|
|
||||||
|
// 等待渲染,确保 scroll-into-view 生效
|
||||||
|
setTimeout(() => {
|
||||||
|
// 滚动到最新的消息(排序后的最后一条)
|
||||||
|
const latestMessage = sortedMessages[sortedMessages.length - 1];
|
||||||
|
this.setData({
|
||||||
|
scrollToId: latestMessage ? latestMessage.id : id
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
|
},
|
||||||
|
|
||||||
sendText() {
|
sendText() {
|
||||||
const text = this.data.inputText && this.data.inputText.trim();
|
const text = this.data.inputText && this.data.inputText.trim();
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|||||||
82
测试说明.md
82
测试说明.md
@ -1,16 +1,27 @@
|
|||||||
# 自动滚动修复测试说明
|
# 聊天功能测试说明
|
||||||
|
|
||||||
## 修复内容
|
## 功能更新内容
|
||||||
|
|
||||||
|
### 1. 自动滚动修复
|
||||||
已修复聊天页面自动刷新后自动滚动到底部的问题,现在实现智能滚动:
|
已修复聊天页面自动刷新后自动滚动到底部的问题,现在实现智能滚动:
|
||||||
|
|
||||||
### 修复的问题
|
#### 修复的问题
|
||||||
- ✅ 轮询刷新时不再强制滚动到底部
|
- ✅ 轮询刷新时不再强制滚动到底部
|
||||||
- ✅ 用户在底部时,新消息会自动滚动显示
|
- ✅ 用户在底部时,新消息会自动滚动显示
|
||||||
- ✅ 用户在上方浏览历史消息时,保持当前位置
|
- ✅ 用户在上方浏览历史消息时,保持当前位置
|
||||||
- ✅ 添加了延迟处理确保滚动生效
|
- ✅ 添加了延迟处理确保滚动生效
|
||||||
|
|
||||||
|
### 2. 自动发送欢迎消息 🆕
|
||||||
|
用户进入聊天页面时会自动发送"你好"消息给服务器:
|
||||||
|
|
||||||
|
#### 新增功能
|
||||||
|
- ✅ 用户首次进入聊天页面时自动发送"你好"消息
|
||||||
|
- ✅ 使用本地存储确保每个用户只发送一次欢迎消息
|
||||||
|
- ✅ 支持静默登录和已登录用户两种场景
|
||||||
|
- ✅ 发送失败时不保存标记,下次可重试
|
||||||
|
|
||||||
### 修改的文件
|
### 修改的文件
|
||||||
- `pages/contact/index.js` - 修改了 `getMessages()` 函数的滚动逻辑
|
- `pages/contact/index.js` - 修改了滚动逻辑和添加了欢迎消息功能
|
||||||
|
|
||||||
## 测试步骤
|
## 测试步骤
|
||||||
|
|
||||||
@ -20,13 +31,29 @@
|
|||||||
|
|
||||||
### 2. 测试场景
|
### 2. 测试场景
|
||||||
|
|
||||||
#### 场景1:用户在底部时的自动滚动
|
#### 场景1:首次进入自动发送欢迎消息 🆕
|
||||||
|
1. 清除小程序缓存(开发者工具 -> 清缓存 -> 清除数据缓存)
|
||||||
|
2. 重新进入聊天页面
|
||||||
|
3. **预期结果**:
|
||||||
|
- 页面加载完成后自动发送"你好"消息
|
||||||
|
- 控制台显示"发送欢迎消息: 你好"
|
||||||
|
- 消息列表中出现"你好"消息
|
||||||
|
- 消息自动滚动到视图中
|
||||||
|
|
||||||
|
#### 场景2:重复进入不发送欢迎消息
|
||||||
|
1. 在已发送过欢迎消息的情况下
|
||||||
|
2. 退出聊天页面再重新进入
|
||||||
|
3. **预期结果**:
|
||||||
|
- 不会再次发送"你好"消息
|
||||||
|
- 控制台显示"该用户的欢迎消息已发送过,跳过"
|
||||||
|
|
||||||
|
#### 场景3:用户在底部时的自动滚动
|
||||||
1. 进入聊天页面
|
1. 进入聊天页面
|
||||||
2. 滚动到最底部
|
2. 滚动到最底部
|
||||||
3. 等待新消息到达(轮询刷新)
|
3. 等待新消息到达(轮询刷新)
|
||||||
4. **预期结果**:新消息自动滚动到视图中
|
4. **预期结果**:新消息自动滚动到视图中
|
||||||
|
|
||||||
#### 场景2:用户在上方时保持位置
|
#### 场景4:用户在上方时保持位置
|
||||||
1. 进入聊天页面
|
1. 进入聊天页面
|
||||||
2. 向上滚动查看历史消息
|
2. 向上滚动查看历史消息
|
||||||
3. 等待新消息到达(轮询刷新)
|
3. 等待新消息到达(轮询刷新)
|
||||||
@ -35,7 +62,7 @@
|
|||||||
- 显示新消息提醒气泡
|
- 显示新消息提醒气泡
|
||||||
- 点击气泡可滚动到最新消息
|
- 点击气泡可滚动到最新消息
|
||||||
|
|
||||||
#### 场景3:用户发送消息时的自动滚动
|
#### 场景5:用户发送消息时的自动滚动
|
||||||
1. 在聊天页面发送文本或图片消息
|
1. 在聊天页面发送文本或图片消息
|
||||||
2. **预期结果**:自动滚动到刚发送的消息
|
2. **预期结果**:自动滚动到刚发送的消息
|
||||||
|
|
||||||
@ -44,16 +71,26 @@
|
|||||||
- 滚动状态变化
|
- 滚动状态变化
|
||||||
- 自动滚动触发情况
|
- 自动滚动触发情况
|
||||||
- scrollToId 设置情况
|
- scrollToId 设置情况
|
||||||
|
- 欢迎消息发送状态 🆕
|
||||||
|
|
||||||
### 4. 关键日志信息
|
### 4. 关键日志信息
|
||||||
|
|
||||||
|
#### 滚动相关日志
|
||||||
- `用户在底部,准备自动滚动到消息ID: xxx` - 触发自动滚动
|
- `用户在底部,准备自动滚动到消息ID: xxx` - 触发自动滚动
|
||||||
- `用户不在底部或无消息,保持当前位置` - 保持位置
|
- `用户不在底部或无消息,保持当前位置` - 保持位置
|
||||||
- `用户向上滚动,设置isAtBottom为false` - 状态变化
|
- `用户向上滚动,设置isAtBottom为false` - 状态变化
|
||||||
- `用户滚动到底部,当前isAtBottom状态: xxx` - 到达底部
|
- `用户滚动到底部,当前isAtBottom状态: xxx` - 到达底部
|
||||||
|
|
||||||
|
#### 欢迎消息相关日志 🆕
|
||||||
|
- `发送欢迎消息: 你好` - 开始发送欢迎消息
|
||||||
|
- `欢迎消息发送成功` - 欢迎消息发送到服务器成功
|
||||||
|
- `欢迎消息发送失败: xxx` - 欢迎消息发送失败
|
||||||
|
- `该用户的欢迎消息已发送过,跳过` - 重复进入时跳过发送
|
||||||
|
- `用户信息不存在,无法发送欢迎消息` - 用户信息异常
|
||||||
|
|
||||||
## 技术实现
|
## 技术实现
|
||||||
|
|
||||||
### 核心逻辑
|
### 1. 智能滚动逻辑
|
||||||
```javascript
|
```javascript
|
||||||
// 智能滚动:先更新数据,再延迟设置滚动
|
// 智能滚动:先更新数据,再延迟设置滚动
|
||||||
that.setData(updateData);
|
that.setData(updateData);
|
||||||
@ -67,7 +104,34 @@ if (that.data.isAtBottom && sortedList.length > 0) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 状态管理
|
### 2. 欢迎消息发送逻辑 🆕
|
||||||
|
```javascript
|
||||||
|
// 检查是否已发送过欢迎消息
|
||||||
|
const welcomeKey = `welcome_sent_${this.data.userInfo.openid}`;
|
||||||
|
const hasWelcomeSent = wx.getStorageSync(welcomeKey);
|
||||||
|
|
||||||
|
if (!hasWelcomeSent) {
|
||||||
|
// 发送欢迎消息到服务器
|
||||||
|
request('app/send_message', 'POST', {
|
||||||
|
"app_id": accountInfo.miniProgram.appId,
|
||||||
|
"content": JSON.stringify({ messages: '你好' }),
|
||||||
|
"from_user_id": userInfo.openid,
|
||||||
|
"from_user_name": userInfo.user_name,
|
||||||
|
"msg_type": 1
|
||||||
|
}).then(() => {
|
||||||
|
// 成功后保存标记
|
||||||
|
wx.setStorageSync(welcomeKey, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 状态管理
|
||||||
- `isAtBottom`: 标记用户是否在聊天底部
|
- `isAtBottom`: 标记用户是否在聊天底部
|
||||||
- `scrollToId`: 控制滚动到指定消息
|
- `scrollToId`: 控制滚动到指定消息
|
||||||
|
- `hasWelcomeMessageSent`: 当前会话是否已发送欢迎消息
|
||||||
|
- `welcome_sent_${openid}`: 本地存储标记,确保每个用户只发送一次
|
||||||
- 延迟50ms确保DOM更新后再滚动
|
- 延迟50ms确保DOM更新后再滚动
|
||||||
|
|
||||||
|
### 4. 触发时机
|
||||||
|
- **已登录用户**: 在 `onLoad` 中调用 `getMessages().then(() => sendWelcomeMessage())`
|
||||||
|
- **静默登录用户**: 在 `silentLogin` 成功后调用 `getMessages().then(() => sendWelcomeMessage())`
|
||||||
Loading…
x
Reference in New Issue
Block a user