|
@@ -0,0 +1,519 @@
|
|
|
|
|
+const _app = getApp()
|
|
|
|
|
+
|
|
|
|
|
+// 办公助手服务配置
|
|
|
|
|
+const ServiceConfig = {
|
|
|
|
|
+ // 样例API地址,请替换为您的真实服务地址
|
|
|
|
|
+ apiUrl: 'https://kt.colexiu.com/edu-app/open/coze/agent',
|
|
|
|
|
+ // 请求超时时间(毫秒)
|
|
|
|
|
+ timeout: 60000,
|
|
|
|
|
+ // 请求头配置
|
|
|
|
|
+ headers: {
|
|
|
|
|
+ 'Content-Type': 'application/json'
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 用户信息管理
|
|
|
|
|
+const UserManager = {
|
|
|
|
|
+ // 获取用户唯一标识
|
|
|
|
|
+ getUserIdentifier: function () {
|
|
|
|
|
+ return new Promise((resolve, _reject) => {
|
|
|
|
|
+ // 尝试从缓存获取用户ID
|
|
|
|
|
+ const cachedUserId = tt.getStorageSync('user_id')
|
|
|
|
|
+ if (cachedUserId) {
|
|
|
|
|
+ resolve(cachedUserId)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 调用登录API获取用户标识
|
|
|
|
|
+ tt.login({
|
|
|
|
|
+ force: false, // 不强制调起登录框
|
|
|
|
|
+ success: function (res) {
|
|
|
|
|
+ console.log('登录成功:', res)
|
|
|
|
|
+
|
|
|
|
|
+ if (res.isLogin && res.code) {
|
|
|
|
|
+ // 已登录用户,使用code作为临时标识
|
|
|
|
|
+ // 实际应用中,应该将code发送到服务端换取openid
|
|
|
|
|
+ const userId = 'user_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9)
|
|
|
|
|
+
|
|
|
|
|
+ // 缓存用户ID
|
|
|
|
|
+ tt.setStorageSync('user_id', userId)
|
|
|
|
|
+ resolve(userId)
|
|
|
|
|
+ } else if (res.anonymousCode) {
|
|
|
|
|
+ // 匿名用户,使用anonymousCode作为标识
|
|
|
|
|
+ const anonymousUserId = 'anonymous_' + res.anonymousCode.substr(0, 16)
|
|
|
|
|
+
|
|
|
|
|
+ // 缓存匿名用户ID
|
|
|
|
|
+ tt.setStorageSync('user_id', anonymousUserId)
|
|
|
|
|
+ resolve(anonymousUserId)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 生成默认用户ID
|
|
|
|
|
+ const defaultUserId = 'default_' + Date.now()
|
|
|
|
|
+ tt.setStorageSync('user_id', defaultUserId)
|
|
|
|
|
+ resolve(defaultUserId)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: function (err) {
|
|
|
|
|
+ console.error('登录失败:', err)
|
|
|
|
|
+ // 生成默认用户ID作为备选
|
|
|
|
|
+ const defaultUserId = 'default_' + Date.now()
|
|
|
|
|
+ tt.setStorageSync('user_id', defaultUserId)
|
|
|
|
|
+ resolve(defaultUserId)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 清除用户信息
|
|
|
|
|
+ clearUserInfo: function () {
|
|
|
|
|
+ tt.removeStorageSync('user_id')
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Page({
|
|
|
|
|
+ data: {
|
|
|
|
|
+ appName: '酷乐秀',
|
|
|
|
|
+ version: '1.0.0',
|
|
|
|
|
+ messageContent: '',
|
|
|
|
|
+ showReply: false,
|
|
|
|
|
+ replyContent: '',
|
|
|
|
|
+ isLoading: false,
|
|
|
|
|
+ apiError: false,
|
|
|
|
|
+ currentUserId: '',
|
|
|
|
|
+ chatMessages: [], // 聊天消息列表(按时间顺序)
|
|
|
|
|
+ scrollTop: 0, // 滚动位置
|
|
|
|
|
+ scrollIntoView: '' // 滚动锚点
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ onLoad: function () {
|
|
|
|
|
+ console.log('办公效率助手小程序已加载')
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ appName: '酷乐秀',
|
|
|
|
|
+ version: '1.0.0'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化用户标识
|
|
|
|
|
+ this.initUserIdentifier()
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化用户标识
|
|
|
|
|
+ initUserIdentifier: function () {
|
|
|
|
|
+ const that = this
|
|
|
|
|
+ UserManager.getUserIdentifier()
|
|
|
|
|
+ .then(userId => {
|
|
|
|
|
+ console.log('获取到用户ID:', userId)
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ currentUserId: userId
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(err => {
|
|
|
|
|
+ console.error('获取用户ID失败:', err)
|
|
|
|
|
+ // 生成默认用户ID
|
|
|
|
|
+ const defaultUserId = 'default_' + Date.now()
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ currentUserId: defaultUserId
|
|
|
|
|
+ })
|
|
|
|
|
+ tt.setStorageSync('user_id', defaultUserId)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ onShow: function () {
|
|
|
|
|
+ console.log('办公效率助手小程序页面显示')
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 页面初次渲染完成
|
|
|
|
|
+ onReady: function () {
|
|
|
|
|
+ console.log('页面初次渲染完成')
|
|
|
|
|
+ // 可以在这里添加需要在页面渲染完成后执行的逻辑
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 点击发送消息按钮(兼容两种方法名)
|
|
|
|
|
+ handleSendMessage: function () {
|
|
|
|
|
+ this.handleSendPrivateMessage()
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 点击发送消息按钮
|
|
|
|
|
+ handleSendPrivateMessage: function () {
|
|
|
|
|
+ const content = this.data.messageContent.trim()
|
|
|
|
|
+
|
|
|
|
|
+ if (!content) {
|
|
|
|
|
+ tt.showToast({
|
|
|
|
|
+ title: '请输入消息内容',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将用户消息添加到聊天记录
|
|
|
|
|
+ const userMessage = {
|
|
|
|
|
+ type: 'user',
|
|
|
|
|
+ content: content,
|
|
|
|
|
+ time: this.getCurrentTime(),
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ chatMessages: [...this.data.chatMessages, userMessage],
|
|
|
|
|
+ isLoading: true,
|
|
|
|
|
+ apiError: false,
|
|
|
|
|
+ messageContent: ''
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ // 滚动到底部
|
|
|
|
|
+ this.scrollToBottom()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 调用助手服务
|
|
|
|
|
+ this.callReplyService(content)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 调用助手服务
|
|
|
|
|
+ callReplyService: function (userMessage) {
|
|
|
|
|
+ const that = this
|
|
|
|
|
+
|
|
|
|
|
+ // 获取用户ID并调用服务
|
|
|
|
|
+ UserManager.getUserIdentifier()
|
|
|
|
|
+ .then(userId => {
|
|
|
|
|
+ console.log('调用助手服务,用户ID:', userId)
|
|
|
|
|
+
|
|
|
|
|
+ // 更新当前用户ID
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ currentUserId: userId
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 发起服务请求
|
|
|
|
|
+ tt.request({
|
|
|
|
|
+ url: ServiceConfig.apiUrl,
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ data: {
|
|
|
|
|
+ message: userMessage,
|
|
|
|
|
+ userId: userId, // 添加用户ID参数
|
|
|
|
|
+ appId: 'yyszkt_help',
|
|
|
|
|
+ timestamp: Date.now(),
|
|
|
|
|
+ // 可以根据需要添加更多参数
|
|
|
|
|
+ context: 'music_assistant', // 保持接口参数不变
|
|
|
|
|
+ language: 'zh-CN',
|
|
|
|
|
+ userType: userId.startsWith('anonymous_') ? 'anonymous' : 'registered'
|
|
|
|
|
+ },
|
|
|
|
|
+ header: ServiceConfig.headers,
|
|
|
|
|
+ timeout: ServiceConfig.timeout,
|
|
|
|
|
+ success: function (res) {
|
|
|
|
|
+ console.log('服务调用成功:', res)
|
|
|
|
|
+
|
|
|
|
|
+ // 处理助手回复
|
|
|
|
|
+ let assistantReply = ''
|
|
|
|
|
+
|
|
|
|
|
+ if (res.statusCode === 200 && res.data) {
|
|
|
|
|
+ // 根据API响应格式处理回复
|
|
|
|
|
+ if (typeof res.data === 'string') {
|
|
|
|
|
+ assistantReply = res.data
|
|
|
|
|
+ } else if (res.data.reply) {
|
|
|
|
|
+ assistantReply = res.data.reply
|
|
|
|
|
+ } else if (res.data.choices && res.data.choices[0] && res.data.choices[0].message) {
|
|
|
|
|
+ assistantReply = res.data.choices[0].message.content
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assistantReply = '已收到您的消息,我这边正在为您整理建议。'
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // API调用失败,使用备用回复
|
|
|
|
|
+ assistantReply = that.generateFallbackResponse(userMessage)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将助手回复添加到聊天记录
|
|
|
|
|
+ const assistantReplyMessage = {
|
|
|
|
|
+ type: 'assistant',
|
|
|
|
|
+ content: assistantReply,
|
|
|
|
|
+ time: that.getCurrentTime(),
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ chatMessages: [...that.data.chatMessages, assistantReplyMessage],
|
|
|
|
|
+ replyContent: assistantReply,
|
|
|
|
|
+ showReply: true,
|
|
|
|
|
+ isLoading: false
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ // 滚动到底部
|
|
|
|
|
+ that.scrollToBottom()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 清空输入框
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ messageContent: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: function (err) {
|
|
|
|
|
+ console.error('服务调用失败:', err)
|
|
|
|
|
+
|
|
|
|
|
+ // 显示错误提示
|
|
|
|
|
+ tt.showToast({
|
|
|
|
|
+ title: '网络异常,使用本地建议',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 使用本地备用建议
|
|
|
|
|
+ const fallbackReply = that.generateFallbackResponse(userMessage)
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ replyContent: fallbackReply,
|
|
|
|
|
+ showReply: true,
|
|
|
|
|
+ isLoading: false,
|
|
|
|
|
+ apiError: true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 清空输入框
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ messageContent: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ complete: function () {
|
|
|
|
|
+ console.log('服务调用完成')
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(err => {
|
|
|
|
|
+ console.error('获取用户ID失败:', err)
|
|
|
|
|
+
|
|
|
|
|
+ // 使用默认用户ID继续调用
|
|
|
|
|
+ const defaultUserId = 'default_' + Date.now()
|
|
|
|
|
+ that.callReplyServiceWithUserId(userMessage, defaultUserId)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 使用指定用户ID调用服务
|
|
|
|
|
+ callReplyServiceWithUserId: function (userMessage, userId) {
|
|
|
|
|
+ const that = this
|
|
|
|
|
+
|
|
|
|
|
+ tt.request({
|
|
|
|
|
+ url: ServiceConfig.apiUrl,
|
|
|
|
|
+ method: 'POST',
|
|
|
|
|
+ data: {
|
|
|
|
|
+ message: userMessage,
|
|
|
|
|
+ userId: userId,
|
|
|
|
|
+ appId: 'yyszkt_help',
|
|
|
|
|
+ timestamp: Date.now(),
|
|
|
|
|
+ context: 'music_assistant',
|
|
|
|
|
+ language: 'zh-CN',
|
|
|
|
|
+ userType: userId.startsWith('anonymous_') ? 'anonymous' : 'registered'
|
|
|
|
|
+ },
|
|
|
|
|
+ header: ServiceConfig.headers,
|
|
|
|
|
+ timeout: ServiceConfig.timeout,
|
|
|
|
|
+ success: function (res) {
|
|
|
|
|
+ // 成功处理逻辑...
|
|
|
|
|
+ let assistantReply = ''
|
|
|
|
|
+
|
|
|
|
|
+ if (res.statusCode === 200 && res.data) {
|
|
|
|
|
+ if (typeof res.data === 'string') {
|
|
|
|
|
+ assistantReply = res.data
|
|
|
|
|
+ } else if (res.data.reply) {
|
|
|
|
|
+ assistantReply = res.data.reply
|
|
|
|
|
+ } else if (res.data.choices && res.data.choices[0] && res.data.choices[0].message) {
|
|
|
|
|
+ assistantReply = res.data.choices[0].message.content
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assistantReply = '已收到您的消息,我这边正在为您整理建议。'
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ assistantReply = that.generateFallbackResponse(userMessage)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 将助手回复添加到聊天记录
|
|
|
|
|
+ const assistantReplyMessage = {
|
|
|
|
|
+ type: 'assistant',
|
|
|
|
|
+ content: assistantReply,
|
|
|
|
|
+ time: that.getCurrentTime(),
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ chatMessages: [...that.data.chatMessages, assistantReplyMessage],
|
|
|
|
|
+ replyContent: assistantReply,
|
|
|
|
|
+ showReply: true,
|
|
|
|
|
+ isLoading: false
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ // 滚动到底部
|
|
|
|
|
+ that.scrollToBottom()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ messageContent: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: function (err) {
|
|
|
|
|
+ console.error('服务调用失败:', err)
|
|
|
|
|
+
|
|
|
|
|
+ tt.showToast({
|
|
|
|
|
+ title: '网络异常,使用本地建议',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const fallbackReply = that.generateFallbackResponse(userMessage)
|
|
|
|
|
+
|
|
|
|
|
+ // 将助手回复添加到聊天记录
|
|
|
|
|
+ const assistantReplyMessage = {
|
|
|
|
|
+ type: 'assistant',
|
|
|
|
|
+ content: fallbackReply,
|
|
|
|
|
+ time: that.getCurrentTime(),
|
|
|
|
|
+ timestamp: Date.now()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ chatMessages: [...that.data.chatMessages, assistantReplyMessage],
|
|
|
|
|
+ replyContent: fallbackReply,
|
|
|
|
|
+ showReply: true,
|
|
|
|
|
+ isLoading: false,
|
|
|
|
|
+ apiError: true
|
|
|
|
|
+ }, () => {
|
|
|
|
|
+ // 滚动到底部
|
|
|
|
|
+ that.scrollToBottom()
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ messageContent: ''
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ complete: function () {
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 生成备用回复(当API调用失败时使用)
|
|
|
|
|
+ generateFallbackResponse: function (userMessage) {
|
|
|
|
|
+ return this.generateReplyResponse(userMessage)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 生成助手回复内容(本地备用)
|
|
|
|
|
+ generateReplyResponse: function (userMessage) {
|
|
|
|
|
+
|
|
|
|
|
+ return '当前客服不在线,暂无法回复消息,请稍等。'
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭助手回复区域
|
|
|
|
|
+ handleCloseReply: function () {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ showReply: false,
|
|
|
|
|
+ replyContent: '',
|
|
|
|
|
+ apiError: false
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 重新获取用户ID(用于调试或重置)
|
|
|
|
|
+ refreshUserIdentifier: function () {
|
|
|
|
|
+ const that = this
|
|
|
|
|
+ UserManager.clearUserInfo()
|
|
|
|
|
+
|
|
|
|
|
+ tt.showLoading({
|
|
|
|
|
+ title: '重新获取用户信息...',
|
|
|
|
|
+ mask: true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ UserManager.getUserIdentifier()
|
|
|
|
|
+ .then(userId => {
|
|
|
|
|
+ tt.hideLoading()
|
|
|
|
|
+ that.setData({
|
|
|
|
|
+ currentUserId: userId
|
|
|
|
|
+ })
|
|
|
|
|
+ tt.showToast({
|
|
|
|
|
+ title: '用户信息更新成功',
|
|
|
|
|
+ icon: 'success',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(_err => {
|
|
|
|
|
+ tt.hideLoading()
|
|
|
|
|
+ tt.showToast({
|
|
|
|
|
+ title: '用户信息更新失败',
|
|
|
|
|
+ icon: 'none',
|
|
|
|
|
+ duration: 2000
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 输入框内容变化
|
|
|
|
|
+ handleInputChange: function (e) {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ messageContent: e.detail.value
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 跳转产品介绍
|
|
|
|
|
+ handleGoProduct: function () {
|
|
|
|
|
+ tt.redirectTo({
|
|
|
|
|
+ url: '/pages/product/index'
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 跳转申请试用
|
|
|
|
|
+ handleGoTrial: function () {
|
|
|
|
|
+ tt.redirectTo({
|
|
|
|
|
+ url: '/pages/trial/index'
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 获取当前时间
|
|
|
|
|
+ getCurrentTime: function () {
|
|
|
|
|
+ const now = new Date()
|
|
|
|
|
+ const hours = now.getHours().toString().padStart(2, '0')
|
|
|
|
|
+ const minutes = now.getMinutes().toString().padStart(2, '0')
|
|
|
|
|
+ return `${hours}:${minutes}`
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 滚动到底部 - 完全重写的专业级实现
|
|
|
|
|
+ scrollToBottom: function () {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ scrollIntoView: ''
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ scrollIntoView: 'bottom-anchor'
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 20)
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ scrollTop: this.data.scrollTop + 9999
|
|
|
|
|
+ })
|
|
|
|
|
+ }, 120)
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.ensureLastMessageInView(0)
|
|
|
|
|
+ }, 180)
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ // 确保最后一条消息完整显示在消息区可视范围内
|
|
|
|
|
+ ensureLastMessageInView: function (retryCount) {
|
|
|
|
|
+ const MAX_RETRY = 5
|
|
|
|
|
+ if (retryCount >= MAX_RETRY) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const query = tt.createSelectorQuery()
|
|
|
|
|
+ query.selectAll('.message-item').boundingClientRect()
|
|
|
|
|
+ query.select('.chat-container').boundingClientRect()
|
|
|
|
|
+ query.exec((res) => {
|
|
|
|
|
+ const messageRects = res[0]
|
|
|
|
|
+ const chatRect = res[1]
|
|
|
|
|
+
|
|
|
|
|
+ if (!messageRects || !messageRects.length || !chatRect) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const lastMessageRect = messageRects[messageRects.length - 1]
|
|
|
|
|
+ const safeBottom = chatRect.bottom - 16
|
|
|
|
|
+ const overlapHeight = lastMessageRect.bottom - safeBottom
|
|
|
|
|
+
|
|
|
|
|
+ if (overlapHeight > 0) {
|
|
|
|
|
+ this.setData({
|
|
|
|
|
+ scrollIntoView: '',
|
|
|
|
|
+ scrollTop: this.data.scrollTop + overlapHeight + 24
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ this.ensureLastMessageInView(retryCount + 1)
|
|
|
|
|
+ }, 60)
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+})
|