From 908502d5c14f713702508f4604599678ac038002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=96=B9=E6=88=90?= Date: Fri, 31 Oct 2025 00:44:58 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=81=8A=E5=A4=A9):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8F=91=E9=80=81=E6=AC=A2=E8=BF=8E=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增首次进入聊天页面自动发送"你好"消息功能 - 使用本地存储确保每个用户只发送一次欢迎消息 - 优化智能滚动逻辑,保持用户浏览位置 - 支持静默登录和已登录用户两种场景 --- pages/contact/index.js | 96 +++++++++++++++++++++++++++++++++++++++--- 测试说明.md | 84 +++++++++++++++++++++++++++++++----- 2 files changed, 164 insertions(+), 16 deletions(-) diff --git a/pages/contact/index.js b/pages/contact/index.js index d3fc2c7..73fb627 100644 --- a/pages/contact/index.js +++ b/pages/contact/index.js @@ -10,7 +10,7 @@ Page({ messages: [], inputText: '', scrollToId: '', - // 使用本地头像 + // 头像 userAvatar: '/static/user.png', serviceAvatar: '/static/contact.png', showGetUser: false, @@ -20,14 +20,16 @@ Page({ page_size: 100, openid: '', total: 0, - // 是否滚动在底部 + // 滚动状态 isAtBottom: true, - // 正在加载更多(顶部分页) + // 加载状态 loadingMore: false, - // 新消息提醒相关状态 + // 新消息提醒 showNewMessageTip: false, // 是否显示新消息提醒 newMessageCount: 0, // 新消息数量 lastMessageId: '', // 最后一条消息的ID,用于检测新消息 + // 欢迎消息标记 + hasWelcomeMessageSent: false, // 是否已发送欢迎消息 }, /** @@ -45,7 +47,10 @@ Page({ showGetUser: false, userInfo: wx.getStorageSync('user_info'), }); - this.getMessages() + this.getMessages().then(() => { + // 在获取消息完成后发送欢迎消息 + this.sendWelcomeMessage(); + }); // start polling when page loads and user is present this.startPolling(); } else { @@ -262,7 +267,10 @@ Page({ "user_id": resp.openid, "user_name": resp.user_name || '微信用户' }).then(resp => { - that.getMessages() + that.getMessages().then(() => { + // 在获取消息完成后发送欢迎消息 + that.sendWelcomeMessage(); + }); // start polling once user info exists 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() { const text = this.data.inputText && this.data.inputText.trim(); if (!text) return; diff --git a/测试说明.md b/测试说明.md index bedfc02..549905c 100644 --- a/测试说明.md +++ b/测试说明.md @@ -1,16 +1,27 @@ -# 自动滚动修复测试说明 +# 聊天功能测试说明 -## 修复内容 +## 功能更新内容 + +### 1. 自动滚动修复 已修复聊天页面自动刷新后自动滚动到底部的问题,现在实现智能滚动: -### 修复的问题 +#### 修复的问题 - ✅ 轮询刷新时不再强制滚动到底部 - ✅ 用户在底部时,新消息会自动滚动显示 - ✅ 用户在上方浏览历史消息时,保持当前位置 - ✅ 添加了延迟处理确保滚动生效 +### 2. 自动发送欢迎消息 🆕 +用户进入聊天页面时会自动发送"你好"消息给服务器: + +#### 新增功能 +- ✅ 用户首次进入聊天页面时自动发送"你好"消息 +- ✅ 使用本地存储确保每个用户只发送一次欢迎消息 +- ✅ 支持静默登录和已登录用户两种场景 +- ✅ 发送失败时不保存标记,下次可重试 + ### 修改的文件 -- `pages/contact/index.js` - 修改了 `getMessages()` 函数的滚动逻辑 +- `pages/contact/index.js` - 修改了滚动逻辑和添加了欢迎消息功能 ## 测试步骤 @@ -20,13 +31,29 @@ ### 2. 测试场景 -#### 场景1:用户在底部时的自动滚动 +#### 场景1:首次进入自动发送欢迎消息 🆕 +1. 清除小程序缓存(开发者工具 -> 清缓存 -> 清除数据缓存) +2. 重新进入聊天页面 +3. **预期结果**: + - 页面加载完成后自动发送"你好"消息 + - 控制台显示"发送欢迎消息: 你好" + - 消息列表中出现"你好"消息 + - 消息自动滚动到视图中 + +#### 场景2:重复进入不发送欢迎消息 +1. 在已发送过欢迎消息的情况下 +2. 退出聊天页面再重新进入 +3. **预期结果**: + - 不会再次发送"你好"消息 + - 控制台显示"该用户的欢迎消息已发送过,跳过" + +#### 场景3:用户在底部时的自动滚动 1. 进入聊天页面 2. 滚动到最底部 3. 等待新消息到达(轮询刷新) 4. **预期结果**:新消息自动滚动到视图中 -#### 场景2:用户在上方时保持位置 +#### 场景4:用户在上方时保持位置 1. 进入聊天页面 2. 向上滚动查看历史消息 3. 等待新消息到达(轮询刷新) @@ -35,7 +62,7 @@ - 显示新消息提醒气泡 - 点击气泡可滚动到最新消息 -#### 场景3:用户发送消息时的自动滚动 +#### 场景5:用户发送消息时的自动滚动 1. 在聊天页面发送文本或图片消息 2. **预期结果**:自动滚动到刚发送的消息 @@ -44,16 +71,26 @@ - 滚动状态变化 - 自动滚动触发情况 - scrollToId 设置情况 +- 欢迎消息发送状态 🆕 ### 4. 关键日志信息 + +#### 滚动相关日志 - `用户在底部,准备自动滚动到消息ID: xxx` - 触发自动滚动 - `用户不在底部或无消息,保持当前位置` - 保持位置 - `用户向上滚动,设置isAtBottom为false` - 状态变化 - `用户滚动到底部,当前isAtBottom状态: xxx` - 到达底部 +#### 欢迎消息相关日志 🆕 +- `发送欢迎消息: 你好` - 开始发送欢迎消息 +- `欢迎消息发送成功` - 欢迎消息发送到服务器成功 +- `欢迎消息发送失败: xxx` - 欢迎消息发送失败 +- `该用户的欢迎消息已发送过,跳过` - 重复进入时跳过发送 +- `用户信息不存在,无法发送欢迎消息` - 用户信息异常 + ## 技术实现 -### 核心逻辑 +### 1. 智能滚动逻辑 ```javascript // 智能滚动:先更新数据,再延迟设置滚动 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`: 标记用户是否在聊天底部 - `scrollToId`: 控制滚动到指定消息 -- 延迟50ms确保DOM更新后再滚动 \ No newline at end of file +- `hasWelcomeMessageSent`: 当前会话是否已发送欢迎消息 +- `welcome_sent_${openid}`: 本地存储标记,确保每个用户只发送一次 +- 延迟50ms确保DOM更新后再滚动 + +### 4. 触发时机 +- **已登录用户**: 在 `onLoad` 中调用 `getMessages().then(() => sendWelcomeMessage())` +- **静默登录用户**: 在 `silentLogin` 成功后调用 `getMessages().then(() => sendWelcomeMessage())` \ No newline at end of file