|
|
@ -55,6 +55,8 @@ Page({ |
|
|
pageSize: 20, |
|
|
pageSize: 20, |
|
|
hasMore: true, |
|
|
hasMore: true, |
|
|
total: 0, |
|
|
total: 0, |
|
|
|
|
|
// 记录最早消息的时间戳,用于加载更早的消息
|
|
|
|
|
|
earliestMsgTime: 0, |
|
|
|
|
|
|
|
|
// 时间显示间隔
|
|
|
// 时间显示间隔
|
|
|
timeInterval: 5, |
|
|
timeInterval: 5, |
|
|
@ -66,7 +68,18 @@ Page({ |
|
|
// WebSocket状态
|
|
|
// WebSocket状态
|
|
|
socketConnected: false, |
|
|
socketConnected: false, |
|
|
reconnectCount: 0, |
|
|
reconnectCount: 0, |
|
|
maxReconnectCount: 5 |
|
|
|
|
|
|
|
|
maxReconnectCount: 5, |
|
|
|
|
|
|
|
|
|
|
|
// 第一次加载完成标记
|
|
|
|
|
|
firstLoadComplete: false, |
|
|
|
|
|
// 是否有新消息
|
|
|
|
|
|
hasNewMessage: false, |
|
|
|
|
|
|
|
|
|
|
|
// 消息ID集合,用于去重
|
|
|
|
|
|
messageIds: new Set(), |
|
|
|
|
|
|
|
|
|
|
|
// 正在发送中的消息ID集合
|
|
|
|
|
|
sendingMessages: new Set() |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
onLoad: function(options) { |
|
|
onLoad: function(options) { |
|
|
@ -82,7 +95,15 @@ Page({ |
|
|
if (options.id) { |
|
|
if (options.id) { |
|
|
this.setData({ |
|
|
this.setData({ |
|
|
otherUserId: options.id, |
|
|
otherUserId: options.id, |
|
|
currentExpertId: options.id |
|
|
|
|
|
|
|
|
currentExpertId: options.id, |
|
|
|
|
|
// 初始页码设置为1
|
|
|
|
|
|
page: 1, |
|
|
|
|
|
messageList: [], |
|
|
|
|
|
hasMore: true, |
|
|
|
|
|
earliestMsgTime: 0, |
|
|
|
|
|
firstLoadComplete: false, |
|
|
|
|
|
messageIds: new Set(), |
|
|
|
|
|
sendingMessages: new Set() |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// 先创建对话,然后获取聊天记录
|
|
|
// 先创建对话,然后获取聊天记录
|
|
|
@ -164,14 +185,21 @@ Page({ |
|
|
this.setData({ |
|
|
this.setData({ |
|
|
conversationId: conversationData.id || conversationData.conversationId || id, |
|
|
conversationId: conversationData.id || conversationData.conversationId || id, |
|
|
conversation: conversationData, |
|
|
conversation: conversationData, |
|
|
otherUserId: id // 确保对方用户ID正确
|
|
|
|
|
|
|
|
|
otherUserId: id, |
|
|
|
|
|
// 重置分页参数
|
|
|
|
|
|
page: 1, |
|
|
|
|
|
hasMore: true, |
|
|
|
|
|
messageList: [], |
|
|
|
|
|
earliestMsgTime: 0, |
|
|
|
|
|
firstLoadComplete: false, |
|
|
|
|
|
messageIds: new Set(), |
|
|
|
|
|
sendingMessages: new Set() |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 获取聊天记录(从第一页开始)
|
|
|
|
|
|
this.getChatHistory(id, false); |
|
|
|
|
|
|
|
|
// 获取聊天记录
|
|
|
|
|
|
this.getChatHistory(id); |
|
|
|
|
|
|
|
|
|
|
|
// 连接WebSocket(确保用户ID已加载)
|
|
|
|
|
|
|
|
|
// 连接WebSocket
|
|
|
const userId = this.getCurrentUserId(); |
|
|
const userId = this.getCurrentUserId(); |
|
|
if (userId) { |
|
|
if (userId) { |
|
|
console.log('用户ID已存在,立即连接WebSocket'); |
|
|
console.log('用户ID已存在,立即连接WebSocket'); |
|
|
@ -199,50 +227,83 @@ Page({ |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 获取聊天记录
|
|
|
// 获取聊天记录
|
|
|
getChatHistory(id) { |
|
|
|
|
|
|
|
|
getChatHistory(id, isLoadMore = false) { |
|
|
|
|
|
// 如果是加载更多且没有更多数据,直接返回
|
|
|
|
|
|
if (isLoadMore && !this.data.hasMore) { |
|
|
|
|
|
console.log('没有更多消息了'); |
|
|
|
|
|
this.setData({ loadingMore: false }); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果不是加载更多,显示加载提示
|
|
|
|
|
|
if (!isLoadMore) { |
|
|
|
|
|
wx.showLoading({ title: '加载中...' }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const params = { |
|
|
|
|
|
otherUserId: id, |
|
|
|
|
|
page: this.data.page, |
|
|
|
|
|
pageSize: this.data.pageSize |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
console.log('请求聊天记录参数:', params); |
|
|
|
|
|
|
|
|
http.direct({ |
|
|
http.direct({ |
|
|
data: { |
|
|
|
|
|
otherUserId: id, |
|
|
|
|
|
page: this.data.page, |
|
|
|
|
|
pageSize: this.data.pageSize |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
data: params, |
|
|
success: res => { |
|
|
success: res => { |
|
|
console.log('获取聊天记录响应:', res); |
|
|
console.log('获取聊天记录响应:', res); |
|
|
wx.hideLoading(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isLoadMore) { |
|
|
|
|
|
wx.hideLoading(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (res && res.code === 200) { |
|
|
if (res && res.code === 200) { |
|
|
// 处理返回的消息数据
|
|
|
// 处理返回的消息数据
|
|
|
this.processChatHistory(res); |
|
|
|
|
|
|
|
|
this.processChatHistory(res, isLoadMore); |
|
|
} else { |
|
|
} else { |
|
|
// 如果没有聊天记录,显示空状态
|
|
|
// 如果没有聊天记录,显示空状态
|
|
|
this.setData({ |
|
|
this.setData({ |
|
|
messageList: [], |
|
|
messageList: [], |
|
|
loading: false, |
|
|
loading: false, |
|
|
hasMore: false |
|
|
|
|
|
|
|
|
loadingMore: false, |
|
|
|
|
|
hasMore: false, |
|
|
|
|
|
firstLoadComplete: true |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (!isLoadMore) { |
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: res?.msg || '获取聊天记录失败', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
fail: err => { |
|
|
fail: err => { |
|
|
console.error('获取聊天记录失败:', err); |
|
|
console.error('获取聊天记录失败:', err); |
|
|
wx.hideLoading(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isLoadMore) { |
|
|
|
|
|
wx.hideLoading(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
wx.showToast({ |
|
|
wx.showToast({ |
|
|
title: '获取聊天记录失败', |
|
|
|
|
|
|
|
|
title: '网络错误', |
|
|
icon: 'none' |
|
|
icon: 'none' |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ |
|
|
this.setData({ |
|
|
messageList: [], |
|
|
messageList: [], |
|
|
loading: false |
|
|
|
|
|
|
|
|
loading: false, |
|
|
|
|
|
loadingMore: false, |
|
|
|
|
|
firstLoadComplete: true |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 处理聊天历史数据
|
|
|
// 处理聊天历史数据
|
|
|
processChatHistory(response) { |
|
|
|
|
|
|
|
|
processChatHistory(response, isLoadMore = false) { |
|
|
let messages = []; |
|
|
let messages = []; |
|
|
let total = 0; |
|
|
let total = 0; |
|
|
let hasMore = false; |
|
|
|
|
|
|
|
|
|
|
|
// 根据实际返回的数据结构调整这里
|
|
|
// 根据实际返回的数据结构调整这里
|
|
|
if (response.rows && Array.isArray(response.rows)) { |
|
|
if (response.rows && Array.isArray(response.rows)) { |
|
|
@ -256,26 +317,79 @@ Page({ |
|
|
total = messages.length; |
|
|
total = messages.length; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 格式化消息数据,适配页面渲染
|
|
|
|
|
|
const formattedMessages = this.formatMessages(messages); |
|
|
|
|
|
|
|
|
console.log('处理消息数据:', { |
|
|
|
|
|
messageCount: messages.length, |
|
|
|
|
|
total, |
|
|
|
|
|
isLoadMore, |
|
|
|
|
|
currentPage: this.data.page |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
// 处理消息时间显示
|
|
|
|
|
|
const processedMessages = this.processMessageTimes(formattedMessages); |
|
|
|
|
|
|
|
|
// 格式化消息数据
|
|
|
|
|
|
const formattedMessages = this.formatMessages(messages); |
|
|
|
|
|
|
|
|
// 判断是否还有更多数据
|
|
|
// 判断是否还有更多数据
|
|
|
hasMore = this.data.page * this.data.pageSize < total; |
|
|
|
|
|
|
|
|
const hasMore = this.data.page * this.data.pageSize < total; |
|
|
|
|
|
|
|
|
|
|
|
// 记录最早消息的时间戳(用于加载更多)
|
|
|
|
|
|
let earliestTime = this.data.earliestMsgTime; |
|
|
|
|
|
if (formattedMessages.length > 0) { |
|
|
|
|
|
// 因为接口返回的是正序,第一条就是最早的
|
|
|
|
|
|
earliestTime = formattedMessages[0].timestamp; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let newMessageList; |
|
|
|
|
|
let targetScrollTop = 0; |
|
|
|
|
|
|
|
|
|
|
|
// 构建消息ID集合
|
|
|
|
|
|
const messageIds = new Set(this.data.messageIds); |
|
|
|
|
|
formattedMessages.forEach(msg => { |
|
|
|
|
|
if (msg.id) { |
|
|
|
|
|
messageIds.add(msg.id); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
if (isLoadMore) { |
|
|
|
|
|
// 加载更多:新加载的消息(更早的)应该放在现有消息列表的前面
|
|
|
|
|
|
newMessageList = [...formattedMessages, ...this.data.messageList]; |
|
|
|
|
|
|
|
|
|
|
|
// 记录新消息的总高度,用于滚动定位
|
|
|
|
|
|
targetScrollTop = formattedMessages.length * 120; // 估算每条消息高度
|
|
|
|
|
|
} else { |
|
|
|
|
|
// 首次加载
|
|
|
|
|
|
newMessageList = formattedMessages; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 重新处理消息时间显示
|
|
|
|
|
|
const processedMessages = this.processMessageTimes(newMessageList); |
|
|
|
|
|
|
|
|
this.setData({ |
|
|
this.setData({ |
|
|
messageList: processedMessages, |
|
|
messageList: processedMessages, |
|
|
|
|
|
messageIds: messageIds, |
|
|
loading: false, |
|
|
loading: false, |
|
|
loadingMore: false, |
|
|
loadingMore: false, |
|
|
hasMore: hasMore, |
|
|
hasMore: hasMore, |
|
|
total: total |
|
|
|
|
|
|
|
|
total: total, |
|
|
|
|
|
earliestMsgTime: earliestTime, |
|
|
|
|
|
firstLoadComplete: true |
|
|
}, () => { |
|
|
}, () => { |
|
|
// 滚动到底部
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.scrollToBottom(true); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
|
|
|
if (isLoadMore) { |
|
|
|
|
|
// 加载更多后,调整滚动位置以保持在当前查看的位置
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.setData({ |
|
|
|
|
|
scrollAnimate: false, |
|
|
|
|
|
scrollTop: targetScrollTop |
|
|
|
|
|
}, () => { |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.setData({ scrollAnimate: true }); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
}); |
|
|
|
|
|
}, 50); |
|
|
|
|
|
} else { |
|
|
|
|
|
// 首次加载,滚动到底部(显示最新消息)
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.scrollToBottom(false); |
|
|
|
|
|
}, 100); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
@ -313,7 +427,43 @@ Page({ |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 加载更多消息
|
|
|
|
|
|
loadMoreMessages: function() { |
|
|
|
|
|
// 防止重复加载
|
|
|
|
|
|
if (this.data.loadingMore) { |
|
|
|
|
|
console.log('正在加载中,请稍后'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有更多数据
|
|
|
|
|
|
if (!this.data.hasMore) { |
|
|
|
|
|
console.log('没有更多消息了'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查对方用户ID是否存在
|
|
|
|
|
|
if (!this.data.otherUserId) { |
|
|
|
|
|
console.error('对方用户ID不存在'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
console.log('开始加载更多消息,当前页码:', this.data.page); |
|
|
|
|
|
|
|
|
|
|
|
// 设置加载状态
|
|
|
|
|
|
this.setData({ |
|
|
|
|
|
loadingMore: true |
|
|
|
|
|
}, () => { |
|
|
|
|
|
// 页码+1,加载更早的消息
|
|
|
|
|
|
const nextPage = this.data.page + 1; |
|
|
|
|
|
|
|
|
|
|
|
this.setData({ |
|
|
|
|
|
page: nextPage |
|
|
|
|
|
}, () => { |
|
|
|
|
|
// 调用获取聊天记录方法,传入true表示是加载更多操作
|
|
|
|
|
|
this.getChatHistory(this.data.otherUserId, true); |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
// 加载用户信息
|
|
|
// 加载用户信息
|
|
|
loadUserInfo: function() { |
|
|
loadUserInfo: function() { |
|
|
@ -365,18 +515,6 @@ Page({ |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 加载更多消息
|
|
|
|
|
|
loadMoreMessages: function() { |
|
|
|
|
|
if (this.data.loadingMore || !this.data.hasMore || !this.data.otherUserId) return; |
|
|
|
|
|
|
|
|
|
|
|
this.setData({ |
|
|
|
|
|
loadingMore: true, |
|
|
|
|
|
page: this.data.page + 1 |
|
|
|
|
|
}, () => { |
|
|
|
|
|
this.getChatHistory(this.data.otherUserId); |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// ========== WebSocket相关方法 ==========
|
|
|
// ========== WebSocket相关方法 ==========
|
|
|
|
|
|
|
|
|
// 连接WebSocket
|
|
|
// 连接WebSocket
|
|
|
@ -507,7 +645,7 @@ Page({ |
|
|
reconnectCount: this.data.reconnectCount + 1 |
|
|
reconnectCount: this.data.reconnectCount + 1 |
|
|
}); |
|
|
}); |
|
|
this.connectWebSocket(); |
|
|
this.connectWebSocket(); |
|
|
}, 3000); // 3秒后重连
|
|
|
|
|
|
|
|
|
}, 3000); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 开始心跳
|
|
|
// 开始心跳
|
|
|
@ -525,7 +663,7 @@ Page({ |
|
|
timestamp: Date.now() |
|
|
timestamp: Date.now() |
|
|
})); |
|
|
})); |
|
|
} |
|
|
} |
|
|
}, 30000); // 30秒发送一次心跳
|
|
|
|
|
|
|
|
|
}, 30000); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 发送WebSocket消息
|
|
|
// 发送WebSocket消息
|
|
|
@ -538,16 +676,13 @@ Page({ |
|
|
}, |
|
|
}, |
|
|
fail: (err) => { |
|
|
fail: (err) => { |
|
|
console.error('WebSocket消息发送失败:', err); |
|
|
console.error('WebSocket消息发送失败:', err); |
|
|
// 加入队列,等待重发
|
|
|
|
|
|
socketMsgQueue.push(data); |
|
|
socketMsgQueue.push(data); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} else { |
|
|
} else { |
|
|
console.log('WebSocket未连接,消息加入队列'); |
|
|
console.log('WebSocket未连接,消息加入队列'); |
|
|
// 队列存储
|
|
|
|
|
|
socketMsgQueue.push(data); |
|
|
socketMsgQueue.push(data); |
|
|
|
|
|
|
|
|
// 尝试重连
|
|
|
|
|
|
if (!isManualClose) { |
|
|
if (!isManualClose) { |
|
|
this.connectWebSocket(); |
|
|
this.connectWebSocket(); |
|
|
} |
|
|
} |
|
|
@ -559,29 +694,24 @@ Page({ |
|
|
console.log('处理消息类型:', data.type); |
|
|
console.log('处理消息类型:', data.type); |
|
|
|
|
|
|
|
|
switch (data.type) { |
|
|
switch (data.type) { |
|
|
case 'chat': // 聊天消息
|
|
|
|
|
|
case 'message': // 兼容其他类型
|
|
|
|
|
|
// 新消息
|
|
|
|
|
|
|
|
|
case 'chat': |
|
|
|
|
|
case 'message': |
|
|
this.handleNewMessage(data); |
|
|
this.handleNewMessage(data); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 'message_status': |
|
|
case 'message_status': |
|
|
// 消息状态更新(已读、送达等)
|
|
|
|
|
|
this.handleMessageStatus(data); |
|
|
this.handleMessageStatus(data); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 'typing': |
|
|
case 'typing': |
|
|
// 对方正在输入
|
|
|
|
|
|
this.handleTypingStatus(data); |
|
|
this.handleTypingStatus(data); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 'online_status': |
|
|
case 'online_status': |
|
|
// 在线状态变更
|
|
|
|
|
|
this.handleOnlineStatus(data); |
|
|
this.handleOnlineStatus(data); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case 'heartbeat_ack': |
|
|
case 'heartbeat_ack': |
|
|
// 心跳响应
|
|
|
|
|
|
console.log('收到心跳响应'); |
|
|
console.log('收到心跳响应'); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
@ -592,99 +722,127 @@ Page({ |
|
|
|
|
|
|
|
|
// 处理新消息
|
|
|
// 处理新消息
|
|
|
handleNewMessage(data) { |
|
|
handleNewMessage(data) { |
|
|
console.log('处理新消息:', data); |
|
|
|
|
|
|
|
|
console.log('处理新消息 - 完整数据:', data); |
|
|
|
|
|
|
|
|
// 获取当前用户ID
|
|
|
|
|
|
const currentUserId = this.getCurrentUserId(); |
|
|
|
|
|
|
|
|
// 提取消息内容
|
|
|
|
|
|
let messageData = data.data || data; |
|
|
|
|
|
|
|
|
// 检查消息是否属于当前对话
|
|
|
|
|
|
const conversationId = data.conversationId || data.chatId || data.roomId; |
|
|
|
|
|
const senderId = data.senderId || data.fromUserId || data.userId; |
|
|
|
|
|
const receiverId = data.receiverId || data.toUserId; |
|
|
|
|
|
|
|
|
// 获取消息ID
|
|
|
|
|
|
const messageId = messageData.id || messageData.messageId || 'msg_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); |
|
|
|
|
|
|
|
|
console.log('消息归属检查:', { |
|
|
|
|
|
currentConversationId: this.data.conversationId, |
|
|
|
|
|
messageConversationId: conversationId, |
|
|
|
|
|
currentUserId: currentUserId, |
|
|
|
|
|
senderId: senderId, |
|
|
|
|
|
receiverId: receiverId, |
|
|
|
|
|
otherUserId: this.data.otherUserId |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
console.log('消息ID:', messageId); |
|
|
|
|
|
console.log('当前发送中消息集合:', this.data.sendingMessages); |
|
|
|
|
|
|
|
|
// 判断是否属于当前对话
|
|
|
|
|
|
let isCurrentConversation = false; |
|
|
|
|
|
|
|
|
// 检查是否是自己发送的消息(通过sendingMessages集合判断)
|
|
|
|
|
|
if (this.data.sendingMessages.has(messageId)) { |
|
|
|
|
|
console.log('收到自己发送的消息回执,跳过处理:', messageId); |
|
|
|
|
|
|
|
|
if (conversationId && conversationId === this.data.conversationId) { |
|
|
|
|
|
isCurrentConversation = true; |
|
|
|
|
|
} else if (!conversationId) { |
|
|
|
|
|
// 如果没有对话ID,则根据发送者和接收者判断
|
|
|
|
|
|
// 消息发送者是我,接收者是对方
|
|
|
|
|
|
if (senderId === currentUserId && receiverId === this.data.otherUserId) { |
|
|
|
|
|
isCurrentConversation = true; |
|
|
|
|
|
} |
|
|
|
|
|
// 消息发送者是对方,接收者是我
|
|
|
|
|
|
else if (senderId === this.data.otherUserId && receiverId === currentUserId) { |
|
|
|
|
|
isCurrentConversation = true; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 从发送中集合移除
|
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.delete(messageId); |
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
|
|
|
|
|
|
|
|
|
// 更新本地消息状态为成功
|
|
|
|
|
|
this.updateMessageStatus(messageId, 'success'); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (!isCurrentConversation) { |
|
|
|
|
|
console.log('消息不属于当前对话,忽略'); |
|
|
|
|
|
|
|
|
// 检查消息是否已存在(去重)
|
|
|
|
|
|
if (this.data.messageIds.has(messageId)) { |
|
|
|
|
|
console.log('消息已存在,跳过处理:', messageId); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 判断发送者是否是当前用户
|
|
|
|
|
|
const isMe = senderId === currentUserId; |
|
|
|
|
|
|
|
|
const userId = this.getCurrentUserId(); |
|
|
|
|
|
const senderId = messageData.senderId || messageData.fromUserId || messageData.userId; |
|
|
|
|
|
|
|
|
console.log('消息归属判断结果:', { isMe, isCurrentConversation }); |
|
|
|
|
|
|
|
|
// 判断是否是自己发送的消息
|
|
|
|
|
|
const isMe = senderId === userId; |
|
|
|
|
|
|
|
|
// 如果是自己发送的消息,检查是否已存在
|
|
|
|
|
|
|
|
|
console.log('消息归属判断:', { |
|
|
|
|
|
senderId: senderId, |
|
|
|
|
|
userId: userId, |
|
|
|
|
|
isMe: isMe, |
|
|
|
|
|
messageId: messageId |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 如果是自己发送的消息但不在sendingMessages中,说明是通过其他方式发送的
|
|
|
|
|
|
// 也跳过处理,避免重复
|
|
|
if (isMe) { |
|
|
if (isMe) { |
|
|
// 检查是否已存在相同ID的消息
|
|
|
|
|
|
const exists = this.data.messageList.some(msg => |
|
|
|
|
|
msg.id === data.messageId || msg.id === data.id |
|
|
|
|
|
); |
|
|
|
|
|
if (exists) { |
|
|
|
|
|
console.log('消息已存在,忽略重复添加'); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
console.log('是自己发送的消息,但不在发送中集合,可能已存在,跳过处理'); |
|
|
|
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建新消息对象
|
|
|
const newMessage = { |
|
|
const newMessage = { |
|
|
id: data.messageId || data.id || 'msg_' + Date.now() + Math.random(), |
|
|
|
|
|
|
|
|
id: messageId, |
|
|
isMe: isMe, |
|
|
isMe: isMe, |
|
|
sender: isMe ? 'user' : 'expert', |
|
|
sender: isMe ? 'user' : 'expert', |
|
|
senderId: senderId, |
|
|
senderId: senderId, |
|
|
contentType: data.contentType || 'text', |
|
|
|
|
|
type: data.contentType || 'text', |
|
|
|
|
|
content: data.content, |
|
|
|
|
|
timestamp: data.timestamp || Date.now(), |
|
|
|
|
|
status: 'success' |
|
|
|
|
|
|
|
|
contentType: messageData.contentType || messageData.type || 'text', |
|
|
|
|
|
type: messageData.type || messageData.contentType || 'text', |
|
|
|
|
|
content: messageData.content || '', |
|
|
|
|
|
timestamp: messageData.timestamp || Date.now(), |
|
|
|
|
|
status: 'success', |
|
|
|
|
|
progress: 100 |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
console.log('添加新消息到列表:', newMessage); |
|
|
|
|
|
|
|
|
console.log('创建的新消息对象:', newMessage); |
|
|
|
|
|
|
|
|
// 处理消息时间显示
|
|
|
|
|
|
const { messageList } = this.data; |
|
|
|
|
|
const processedMessage = this.processSingleMessageTime(newMessage, messageList); |
|
|
|
|
|
|
|
|
// 获取当前消息列表
|
|
|
|
|
|
const currentList = [...this.data.messageList]; |
|
|
|
|
|
console.log('当前消息列表长度:', currentList.length); |
|
|
|
|
|
|
|
|
// 添加新消息
|
|
|
|
|
|
messageList.push(processedMessage); |
|
|
|
|
|
|
|
|
// 添加新消息到列表末尾
|
|
|
|
|
|
currentList.push(newMessage); |
|
|
|
|
|
|
|
|
this.setData({ messageList }, () => { |
|
|
|
|
|
this.scrollToBottom(); |
|
|
|
|
|
|
|
|
// 更新消息ID集合
|
|
|
|
|
|
const messageIds = new Set(this.data.messageIds); |
|
|
|
|
|
messageIds.add(messageId); |
|
|
|
|
|
|
|
|
// 如果不是自己发的消息,发送已读回执
|
|
|
|
|
|
if (!newMessage.isMe) { |
|
|
|
|
|
this.sendReadReceipt(newMessage.id); |
|
|
|
|
|
|
|
|
// 重新处理时间显示
|
|
|
|
|
|
const processedMessages = this.processMessageTimes(currentList); |
|
|
|
|
|
|
|
|
// 播放提示音
|
|
|
|
|
|
this.playNotificationSound(); |
|
|
|
|
|
|
|
|
console.log('处理后的消息列表长度:', processedMessages.length); |
|
|
|
|
|
console.log('最后一条消息:', processedMessages[processedMessages.length - 1]); |
|
|
|
|
|
|
|
|
// 震动提示
|
|
|
|
|
|
wx.vibrateShort({ |
|
|
|
|
|
type: 'light' |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
// 更新数据
|
|
|
|
|
|
this.setData({ |
|
|
|
|
|
messageList: processedMessages, |
|
|
|
|
|
messageIds: messageIds, |
|
|
|
|
|
hasNewMessage: !isMe // 如果不是自己发的,标记有新消息
|
|
|
|
|
|
}, () => { |
|
|
|
|
|
console.log('消息列表已更新,当前列表:', this.data.messageList); |
|
|
|
|
|
|
|
|
|
|
|
// 判断是否需要滚动到底部
|
|
|
|
|
|
const query = wx.createSelectorQuery(); |
|
|
|
|
|
query.select('#chatScroll').boundingClientRect(); |
|
|
|
|
|
query.select('.chat-bottom-space').boundingClientRect(); |
|
|
|
|
|
query.exec((res) => { |
|
|
|
|
|
if (res[0] && res[1]) { |
|
|
|
|
|
const scrollHeight = res[0].height; |
|
|
|
|
|
const bottomOffset = res[1].top - res[0].top; |
|
|
|
|
|
const scrollTop = this.data.lastScrollTop; |
|
|
|
|
|
|
|
|
|
|
|
// 如果在底部附近(距离底部小于200px)或是自己发的消息,则滚动到底部
|
|
|
|
|
|
const shouldScroll = isMe || (scrollTop + scrollHeight >= bottomOffset - 200); |
|
|
|
|
|
|
|
|
|
|
|
if (shouldScroll) { |
|
|
|
|
|
this.scrollToBottom(true); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// 如果获取不到位置信息,默认滚动到底部
|
|
|
|
|
|
if (isMe) { |
|
|
|
|
|
this.scrollToBottom(true); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 如果不是自己发的消息,震动提示
|
|
|
|
|
|
if (!isMe) { |
|
|
|
|
|
// wx.vibrateShort({ type: 'light' });
|
|
|
|
|
|
// 发送已读回执
|
|
|
|
|
|
this.sendReadReceipt(messageId); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
@ -699,21 +857,24 @@ Page({ |
|
|
messageList[index].status = data.status || 'success'; |
|
|
messageList[index].status = data.status || 'success'; |
|
|
this.setData({ messageList }); |
|
|
this.setData({ messageList }); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 如果收到成功状态,从发送中集合移除
|
|
|
|
|
|
if (data.status === 'success') { |
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.delete(messageId); |
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 处理正在输入状态
|
|
|
// 处理正在输入状态
|
|
|
handleTypingStatus(data) { |
|
|
handleTypingStatus(data) { |
|
|
const userId = data.userId || data.senderId; |
|
|
const userId = data.userId || data.senderId; |
|
|
if (userId === this.data.otherUserId) { |
|
|
if (userId === this.data.otherUserId) { |
|
|
this.setData({ |
|
|
|
|
|
'expertInfo.typing': true |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ 'expertInfo.typing': true }); |
|
|
|
|
|
|
|
|
clearTimeout(this.typingTimer); |
|
|
clearTimeout(this.typingTimer); |
|
|
this.typingTimer = setTimeout(() => { |
|
|
this.typingTimer = setTimeout(() => { |
|
|
this.setData({ |
|
|
|
|
|
'expertInfo.typing': false |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ 'expertInfo.typing': false }); |
|
|
}, 3000); |
|
|
}, 3000); |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
@ -728,7 +889,7 @@ Page({ |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 发送消息 - 修复用户ID获取
|
|
|
|
|
|
|
|
|
// 发送消息到服务器
|
|
|
sendMessageToServer: function(content, type, messageId) { |
|
|
sendMessageToServer: function(content, type, messageId) { |
|
|
const receiverId = this.data.otherUserId; |
|
|
const receiverId = this.data.otherUserId; |
|
|
const senderId = this.getCurrentUserId(); |
|
|
const senderId = this.getCurrentUserId(); |
|
|
@ -747,16 +908,25 @@ Page({ |
|
|
title: '发送失败,用户信息错误', |
|
|
title: '发送失败,用户信息错误', |
|
|
icon: 'none' |
|
|
icon: 'none' |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// 发送失败,从发送中集合移除
|
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.delete(messageId); |
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
|
|
|
|
|
|
|
|
|
// 更新消息状态为失败
|
|
|
|
|
|
this.updateMessageStatus(messageId, 'failed'); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const message = { |
|
|
const message = { |
|
|
type: 'chat', // 指定为chat类型
|
|
|
|
|
|
receiverId: receiverId, // 接收者ID,就是对方的ID
|
|
|
|
|
|
senderId: senderId, // 发送者ID
|
|
|
|
|
|
content: content, // 消息内容
|
|
|
|
|
|
contentType: type || 'text', // 内容类型
|
|
|
|
|
|
timestamp: Date.now() |
|
|
|
|
|
|
|
|
type: 'chat', |
|
|
|
|
|
receiverId: receiverId, |
|
|
|
|
|
senderId: senderId, |
|
|
|
|
|
content: content, |
|
|
|
|
|
contentType: type || 'text', |
|
|
|
|
|
timestamp: Date.now(), |
|
|
|
|
|
messageId: messageId |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const messageStr = JSON.stringify(message); |
|
|
const messageStr = JSON.stringify(message); |
|
|
@ -769,10 +939,7 @@ Page({ |
|
|
icon: 'none' |
|
|
icon: 'none' |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
// 尝试重连
|
|
|
|
|
|
this.connectWebSocket(); |
|
|
this.connectWebSocket(); |
|
|
|
|
|
|
|
|
// 加入队列
|
|
|
|
|
|
socketMsgQueue.push(messageStr); |
|
|
socketMsgQueue.push(messageStr); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
@ -819,6 +986,10 @@ Page({ |
|
|
|
|
|
|
|
|
console.log('发送文本消息,ID:', messageId); |
|
|
console.log('发送文本消息,ID:', messageId); |
|
|
|
|
|
|
|
|
|
|
|
// 将消息ID添加到发送中集合
|
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.add(messageId); |
|
|
|
|
|
|
|
|
// 创建本地消息
|
|
|
// 创建本地消息
|
|
|
const newMessage = { |
|
|
const newMessage = { |
|
|
id: messageId, |
|
|
id: messageId, |
|
|
@ -835,18 +1006,32 @@ Page({ |
|
|
// 添加到列表
|
|
|
// 添加到列表
|
|
|
this.addMessageToList(newMessage); |
|
|
this.addMessageToList(newMessage); |
|
|
|
|
|
|
|
|
|
|
|
// 更新发送中集合
|
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
|
|
|
|
|
|
// 清空输入框
|
|
|
// 清空输入框
|
|
|
this.setData({ |
|
|
|
|
|
inputValue: '' |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ inputValue: '' }); |
|
|
|
|
|
|
|
|
// 通过WebSocket发送到服务器
|
|
|
// 通过WebSocket发送到服务器
|
|
|
this.sendMessageToServer(content, 'text', messageId); |
|
|
this.sendMessageToServer(content, 'text', messageId); |
|
|
|
|
|
|
|
|
// 模拟发送成功回调(实际应该通过WebSocket接收消息状态)
|
|
|
|
|
|
|
|
|
// 设置超时,如果5秒后还没有收到回执,认为发送失败
|
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.updateMessageStatus(messageId, 'success'); |
|
|
|
|
|
}, 500); |
|
|
|
|
|
|
|
|
if (this.data.sendingMessages.has(messageId)) { |
|
|
|
|
|
console.log('消息发送超时:', messageId); |
|
|
|
|
|
this.updateMessageStatus(messageId, 'timeout'); |
|
|
|
|
|
|
|
|
|
|
|
// 从发送中集合移除
|
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.delete(messageId); |
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
|
|
|
|
|
|
|
|
|
wx.showToast({ |
|
|
|
|
|
title: '发送超时', |
|
|
|
|
|
icon: 'none' |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}, 5000); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 上传图片后发送
|
|
|
// 上传图片后发送
|
|
|
@ -866,6 +1051,11 @@ Page({ |
|
|
// 通用文件上传
|
|
|
// 通用文件上传
|
|
|
uploadFile: function(tempFilePath, fileName, fileSize = 0, type = 'file', thumbPath = '') { |
|
|
uploadFile: function(tempFilePath, fileName, fileSize = 0, type = 'file', thumbPath = '') { |
|
|
const messageId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); |
|
|
const messageId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); |
|
|
|
|
|
|
|
|
|
|
|
// 将消息ID添加到发送中集合
|
|
|
|
|
|
const sendingMessages = new Set(this.data.sendingMessages); |
|
|
|
|
|
sendingMessages.add(messageId); |
|
|
|
|
|
|
|
|
const message = { |
|
|
const message = { |
|
|
id: messageId, |
|
|
id: messageId, |
|
|
isMe: true, |
|
|
isMe: true, |
|
|
@ -883,10 +1073,11 @@ Page({ |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
this.addMessageToList(message); |
|
|
this.addMessageToList(message); |
|
|
|
|
|
this.setData({ sendingMessages: sendingMessages }); |
|
|
this.simulateUpload(messageId, type, tempFilePath); |
|
|
this.simulateUpload(messageId, type, tempFilePath); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 上传
|
|
|
|
|
|
|
|
|
// 模拟上传
|
|
|
simulateUpload: function(messageId, type, tempFilePath) { |
|
|
simulateUpload: function(messageId, type, tempFilePath) { |
|
|
let progress = 0; |
|
|
let progress = 0; |
|
|
const uploadInterval = setInterval(() => { |
|
|
const uploadInterval = setInterval(() => { |
|
|
@ -897,7 +1088,6 @@ Page({ |
|
|
clearInterval(uploadInterval); |
|
|
clearInterval(uploadInterval); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
// 上传完成,更新消息状态
|
|
|
|
|
|
this.updateMessageStatus(messageId, 'success'); |
|
|
this.updateMessageStatus(messageId, 'success'); |
|
|
|
|
|
|
|
|
const { messageList } = this.data; |
|
|
const { messageList } = this.data; |
|
|
@ -906,9 +1096,7 @@ Page({ |
|
|
delete messageList[index].progress; |
|
|
delete messageList[index].progress; |
|
|
this.setData({ messageList }); |
|
|
this.setData({ messageList }); |
|
|
|
|
|
|
|
|
// 上传完成后,通过WebSocket发送消息
|
|
|
|
|
|
|
|
|
|
|
|
const fileUrl = tempFilePath; // 上传后的URL
|
|
|
|
|
|
|
|
|
const fileUrl = tempFilePath; |
|
|
this.sendMessageToServer(fileUrl, type, messageId); |
|
|
this.sendMessageToServer(fileUrl, type, messageId); |
|
|
} |
|
|
} |
|
|
}, 200); |
|
|
}, 200); |
|
|
@ -925,12 +1113,27 @@ Page({ |
|
|
|
|
|
|
|
|
// 添加消息到列表
|
|
|
// 添加消息到列表
|
|
|
addMessageToList: function(message) { |
|
|
addMessageToList: function(message) { |
|
|
const { messageList } = this.data; |
|
|
|
|
|
const processedMessage = this.processSingleMessageTime(message, messageList); |
|
|
|
|
|
|
|
|
const { messageList, messageIds } = this.data; |
|
|
|
|
|
|
|
|
messageList.push(processedMessage); |
|
|
|
|
|
|
|
|
// 检查是否已存在
|
|
|
|
|
|
if (messageIds.has(message.id)) { |
|
|
|
|
|
console.log('消息已存在,不重复添加:', message.id); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 新消息添加到末尾
|
|
|
|
|
|
messageList.push(message); |
|
|
|
|
|
|
|
|
this.setData({ messageList }, () => { |
|
|
|
|
|
|
|
|
// 更新消息ID集合
|
|
|
|
|
|
messageIds.add(message.id); |
|
|
|
|
|
|
|
|
|
|
|
// 重新处理时间显示
|
|
|
|
|
|
const processedMessages = this.processMessageTimes(messageList); |
|
|
|
|
|
|
|
|
|
|
|
this.setData({ |
|
|
|
|
|
messageList: processedMessages, |
|
|
|
|
|
messageIds: messageIds |
|
|
|
|
|
}, () => { |
|
|
this.scrollToBottom(); |
|
|
this.scrollToBottom(); |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
@ -946,15 +1149,10 @@ Page({ |
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 输入处理(带防抖)
|
|
|
|
|
|
|
|
|
// 输入处理
|
|
|
onInput: function(e) { |
|
|
onInput: function(e) { |
|
|
this.setData({ |
|
|
|
|
|
inputValue: e.detail.value |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ inputValue: e.detail.value }); |
|
|
|
|
|
|
|
|
// 发送正在输入状态(防抖)
|
|
|
|
|
|
clearTimeout(this.typingDebounce); |
|
|
clearTimeout(this.typingDebounce); |
|
|
this.typingDebounce = setTimeout(() => { |
|
|
this.typingDebounce = setTimeout(() => { |
|
|
this.sendTypingStatus(); |
|
|
this.sendTypingStatus(); |
|
|
@ -963,9 +1161,7 @@ Page({ |
|
|
|
|
|
|
|
|
// 输入框获得焦点
|
|
|
// 输入框获得焦点
|
|
|
onInputFocus: function() { |
|
|
onInputFocus: function() { |
|
|
this.setData({ |
|
|
|
|
|
inputFocus: true |
|
|
|
|
|
}, () => { |
|
|
|
|
|
|
|
|
this.setData({ inputFocus: true }, () => { |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.scrollToBottom(); |
|
|
this.scrollToBottom(); |
|
|
}, 200); |
|
|
}, 200); |
|
|
@ -974,9 +1170,7 @@ Page({ |
|
|
|
|
|
|
|
|
// 输入框失去焦点
|
|
|
// 输入框失去焦点
|
|
|
onInputBlur: function() { |
|
|
onInputBlur: function() { |
|
|
this.setData({ |
|
|
|
|
|
inputFocus: false |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ inputFocus: false }); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 清除输入
|
|
|
// 清除输入
|
|
|
@ -1000,10 +1194,25 @@ Page({ |
|
|
this.setData({ isScrolling: false }); |
|
|
this.setData({ isScrolling: false }); |
|
|
}, 200); |
|
|
}, 200); |
|
|
|
|
|
|
|
|
// 加载更多
|
|
|
|
|
|
if (scrollTop <= 100 && !this.data.loadingMore && this.data.hasMore) { |
|
|
|
|
|
|
|
|
// 当滚动到顶部附近时加载更多
|
|
|
|
|
|
if (scrollTop <= 50 && !this.data.loadingMore && this.data.hasMore && this.data.firstLoadComplete) { |
|
|
|
|
|
console.log('触发加载更多,当前滚动位置:', scrollTop); |
|
|
this.loadMoreMessages(); |
|
|
this.loadMoreMessages(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 当滚动到底部时,清除新消息标记
|
|
|
|
|
|
const query = wx.createSelectorQuery(); |
|
|
|
|
|
query.select('#chatScroll').boundingClientRect(); |
|
|
|
|
|
query.select('.chat-bottom-space').boundingClientRect(); |
|
|
|
|
|
query.exec((res) => { |
|
|
|
|
|
if (res[0] && res[1]) { |
|
|
|
|
|
const scrollHeight = res[0].height; |
|
|
|
|
|
const bottomOffset = res[1].top - res[0].top; |
|
|
|
|
|
if (scrollTop + scrollHeight >= bottomOffset - 50) { |
|
|
|
|
|
this.setData({ hasNewMessage: false }); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 滚动到底部
|
|
|
// 滚动到底部
|
|
|
@ -1011,25 +1220,21 @@ Page({ |
|
|
if (this.data.isScrolling) return; |
|
|
if (this.data.isScrolling) return; |
|
|
|
|
|
|
|
|
this.setData({ |
|
|
this.setData({ |
|
|
scrollAnimate: animate |
|
|
|
|
|
|
|
|
scrollAnimate: animate, |
|
|
|
|
|
hasNewMessage: false |
|
|
}, () => { |
|
|
}, () => { |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.setData({ |
|
|
|
|
|
scrollTop: 999999 |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ scrollTop: 999999 }); |
|
|
}, 50); |
|
|
}, 50); |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 键盘高度变化
|
|
|
// 键盘高度变化
|
|
|
onKeyboardHeightChange: function(res) { |
|
|
onKeyboardHeightChange: function(res) { |
|
|
this.setData({ |
|
|
|
|
|
keyboardHeight: res.height |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ keyboardHeight: res.height }); |
|
|
|
|
|
|
|
|
if (res.height > 0) { |
|
|
if (res.height > 0) { |
|
|
this.setData({ showMediaSheet: false }); |
|
|
this.setData({ showMediaSheet: false }); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.scrollToBottom(); |
|
|
this.scrollToBottom(); |
|
|
}, 100); |
|
|
}, 100); |
|
|
@ -1046,9 +1251,7 @@ Page({ |
|
|
|
|
|
|
|
|
// 隐藏多媒体选择面板
|
|
|
// 隐藏多媒体选择面板
|
|
|
hideMediaActionSheet: function() { |
|
|
hideMediaActionSheet: function() { |
|
|
this.setData({ |
|
|
|
|
|
showMediaSheet: false |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
this.setData({ showMediaSheet: false }); |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 选择图片
|
|
|
// 选择图片
|
|
|
@ -1115,12 +1318,11 @@ Page({ |
|
|
processMessageTimes: function(messages) { |
|
|
processMessageTimes: function(messages) { |
|
|
if (!messages || messages.length === 0) return []; |
|
|
if (!messages || messages.length === 0) return []; |
|
|
|
|
|
|
|
|
const sortedMessages = [...messages].sort((a, b) => a.timestamp - b.timestamp); |
|
|
|
|
|
const processedMessages = []; |
|
|
const processedMessages = []; |
|
|
let lastShowTime = null; |
|
|
let lastShowTime = null; |
|
|
|
|
|
|
|
|
for (let i = 0; i < sortedMessages.length; i++) { |
|
|
|
|
|
const msg = { ...sortedMessages[i] }; |
|
|
|
|
|
|
|
|
for (let i = 0; i < messages.length; i++) { |
|
|
|
|
|
const msg = { ...messages[i] }; |
|
|
|
|
|
|
|
|
if (i === 0) { |
|
|
if (i === 0) { |
|
|
msg.showTime = true; |
|
|
msg.showTime = true; |
|
|
@ -1141,27 +1343,6 @@ Page({ |
|
|
return processedMessages; |
|
|
return processedMessages; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 处理单条消息时间
|
|
|
|
|
|
processSingleMessageTime: function(message, messageList) { |
|
|
|
|
|
const msg = { ...message }; |
|
|
|
|
|
|
|
|
|
|
|
if (messageList.length === 0) { |
|
|
|
|
|
msg.showTime = true; |
|
|
|
|
|
this.setData({ lastShowTimeStamp: msg.timestamp }); |
|
|
|
|
|
return msg; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const lastShowTime = this.data.lastShowTimeStamp; |
|
|
|
|
|
const timeDiffMinutes = (msg.timestamp - lastShowTime) / (1000 * 60); |
|
|
|
|
|
|
|
|
|
|
|
msg.showTime = timeDiffMinutes >= this.data.timeInterval; |
|
|
|
|
|
if (msg.showTime) { |
|
|
|
|
|
this.setData({ lastShowTimeStamp: msg.timestamp }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return msg; |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 格式化时间
|
|
|
// 格式化时间
|
|
|
formatTime: function(timestamp) { |
|
|
formatTime: function(timestamp) { |
|
|
if (!timestamp) return ''; |
|
|
if (!timestamp) return ''; |
|
|
@ -1188,21 +1369,6 @@ Page({ |
|
|
return size.toFixed(1) + units[unitIndex]; |
|
|
return size.toFixed(1) + units[unitIndex]; |
|
|
}, |
|
|
}, |
|
|
|
|
|
|
|
|
// 播放提示音
|
|
|
|
|
|
playNotificationSound() { |
|
|
|
|
|
try { |
|
|
|
|
|
const innerAudioContext = wx.createInnerAudioContext(); |
|
|
|
|
|
innerAudioContext.src = '/assets/sounds/notification.mp3'; |
|
|
|
|
|
innerAudioContext.play(); |
|
|
|
|
|
|
|
|
|
|
|
innerAudioContext.onEnded(() => { |
|
|
|
|
|
innerAudioContext.destroy(); |
|
|
|
|
|
}); |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.log('播放提示音失败:', e); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
// 阻止事件冒泡
|
|
|
// 阻止事件冒泡
|
|
|
stopPropagation: function() {} |
|
|
stopPropagation: function() {} |
|
|
}); |
|
|
}); |