From 04102f7237efefa744090ed7c25f7b5d0807b679 Mon Sep 17 00:00:00 2001
From: quanwei <419654421@qq.com>
Date: Thu, 05 Feb 2026 18:11:57 +0800
Subject: [PATCH] 完成运营中心提现和运营中心权限管理
---
mobile/pages/plus/business/chat/chat.vue | 258 +++++++++++++++++++++++++++++++++++++--------------
1 files changed, 187 insertions(+), 71 deletions(-)
diff --git a/mobile/pages/plus/business/chat/chat.vue b/mobile/pages/plus/business/chat/chat.vue
index 9a10aaa..3c1447c 100644
--- a/mobile/pages/plus/business/chat/chat.vue
+++ b/mobile/pages/plus/business/chat/chat.vue
@@ -59,12 +59,12 @@
<text class="message-text">{{ message.content }}</text>
</view>
</view>
- <view class="message-status" :class="message.is_read ? 'read-read' : 'read-sent'">
+ <!-- <view class="message-status" :class="message.is_read ? 'read-read' : 'read-sent'">
<text class="icon iconfont icon-eye "></text>
- </view>
+ </view> -->
</view>
<view class="message-info">
- <text class="message-time">{{ formatTime(message.create_time) }}</text>
+ <text class="message-time">{{ formatTime(message.send_time||message.create_time) }}</text>
</view>
</view>
</view>
@@ -73,7 +73,7 @@
<view class="message-mine" v-else>
<view class="message-content">
<view class="d-s-e">
- <view class="message-status" :class="message.is_read ? 'read-read' : 'read-sent'">
+ <view class="message-status" :class="message.is_read ? 'read-read' : 'read-sent'">
</view>
<view class="d-f">
<view class="message-bubble">
@@ -86,7 +86,7 @@
</view>
<view class="message-info">
- <text class="message-time">{{ formatTime(message.create_time) }}</text>
+ <text class="message-time">{{ formatTime(message.send_time||message.create_time) }}</text>
</view>
</view>
@@ -193,6 +193,7 @@
avatarUrl: ''
},
card: {},
+ wsUrl:"",
// 聊天数据
messages: [],
@@ -214,7 +215,12 @@
// 定时器
typingTimer: null,
- readTimer: null
+ readTimer: null,
+ reconnectTimer: null,
+ reconnectAttempts: 0,
+ maxReconnectAttempts: 5,
+ heartbeatTimer: null,
+ is_exit: false //是否退出
};
},
onLoad(options) {
@@ -224,24 +230,29 @@
this.businessCardId = parseInt(options.business_card_id) || 0;
this.conversationId = parseInt(options.conversation_id) || 0;
this.targetUser.nickName = options.nickName || '用户';
-
// 获取当前用户信息
this.getCurrentUser();
if (!this.conversationId) {
// 初始化会话
this.initConversation();
+ }else{
+ // 加载消息
+ this.loadMessages();
+ this.initWebSocket();
}
- // 加载消息
- this.loadMessages();
-
+
},
onUnload() {
+ this.is_exit = true;
// 清理定时器
if (this.typingTimer) {
clearTimeout(this.typingTimer);
}
if (this.readTimer) {
clearTimeout(this.readTimer);
+ }
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
}
// 关闭WebSocket
this.closeWebSocket();
@@ -257,8 +268,6 @@
let self = this;
self._get('user.user/detail', {}, res => {
self.currentUser = res.data.userInfo;
- // 初始化WebSocket连接
- self.initWebSocket();
})
},
@@ -269,6 +278,10 @@
business_card_id: this.businessCardId
}, res => {
this.conversationId = res.data.conversation.conversation_id;
+ this.loadMessages();
+ this.wsUrl = res.data.wsUrl;
+ // 初始化WebSocket连接
+ this.initWebSocket();
});
},
@@ -296,31 +309,24 @@
if (self.page === 1) {
// First page - sort messages by create_time ascending, newest at bottom
self.messages = newMessages.sort((a, b) => {
- return new Date(a.create_time) - new Date(b.create_time);
+ return a.send_time - b.send_time;
});
} else {
// For pagination, prepend older messages
const sortedMessages = newMessages.sort((a, b) => {
- return new Date(a.create_time) - new Date(b.create_time);
+ return a.send_time - b.send_time;
});
self.messages = [...sortedMessages, ...self.messages];
}
self.hasMore = self.messages.length < res.data.messages.total;
self.loadMore = false;
- // 滚动到底部
- self.$nextTick(() => {
- self.scrollToBottom();
- });
self.page++;
if (self.page == 2) {
+ console.log(res.data.heUser);
// 获取目标用户信息
this.targetUser = res.data.heUser;
this.card = res.data.card;
- // 滚动到底部
- self.$nextTick(() => {
- self.scrollToBottom();
- });
// 标记整个会话为已读
if (self.conversationId) {
self._post('plus.business.chat.chat/markAsRead', {
@@ -333,6 +339,11 @@
if (msg.sender_id !== self.currentUser.user_id) {
msg.is_read = true;
}
+ });
+
+ // 滚动到底部
+ self.$nextTick(() => {
+ self.scrollToBottom();
});
}
});
@@ -348,28 +359,9 @@
async sendMessage() {
let self = this;
if (!this.inputMessage.trim()) return;
-
const content = self.inputMessage.trim();
+ console.log(content);
self.sendWebSocketMessage(content);
- /* self._post('plus.business.chat.chat/sendMessage', {
- conversation_id: self.conversationId,
- business_card_id: self.businessCardId,
- content: content
- }, res => {
- if (res.code === 1) {
- // 添加到消息列表
- self.messages.push(res.data.message);
- self.inputMessage = '';
- // 滚动到底部
- self.$nextTick(() => {
- self.scrollToBottom();
- });
- // 发送WebSocket消息
- self.sendWebSocketMessage(res.data.ws_message);
- } else {
- self.showError(res.msg || '发送失败');
- }
- }); */
},
// WebSocket相关方法
@@ -383,26 +375,26 @@
const currentUserId = this.currentUser.user_id;
// 构建WebSocket连接URL - 使用名片聊天专用端口2349
- const wsUrl = `ws://localhost:2349?user_id=${currentUserId}`;
-
+ const wsUrl = `${this.wsUrl}:2349?user_id=${currentUserId}&usertype=supplier `;
try {
// 创建WebSocket连接
this.socketTask = uni.connectSocket({
url: wsUrl,
- success: () => {
- console.log('WebSocket连接成功');
- },
+ success: () => {},
fail: (err) => {
- console.error('WebSocket连接失败:', err);
+ // 尝试重连
+ this.reconnectWebSocket();
}
});
// 监听WebSocket打开事件
this.socketTask.onOpen(() => {
- console.log('WebSocket已打开');
this.isOnline = true;
+ this.reconnectAttempts = 0; // 重置重连计数
// 发送心跳包
this.startHeartbeat();
+ // 绑定用户ID
+ this.bindUserId();
});
// 监听WebSocket消息事件
@@ -425,6 +417,8 @@
this.socketTask.onError((err) => {
console.error('WebSocket错误:', err);
this.isOnline = false;
+ // 尝试重连
+ this.reconnectWebSocket();
});
// 监听WebSocket关闭事件
@@ -438,11 +432,55 @@
clearInterval(this.heartbeatTimer);
this.heartbeatTimer = null;
}
+
+ // 尝试重连
+ this.reconnectWebSocket();
});
} catch (error) {
console.error('初始化WebSocket失败:', error);
+ // 尝试重连
+ this.reconnectWebSocket();
}
+ },
+
+ // 绑定用户ID
+ bindUserId() {
+ if (this.socketTask && this.currentUser.user_id) {
+ const bindMsg = {
+ type: 'bind',
+ user_id: this.currentUser.user_id
+ };
+ try {
+ this.socketTask.send({
+ data: JSON.stringify(bindMsg)
+ });
+ console.log('用户ID绑定消息已发送');
+ } catch (error) {
+ console.log('发送用户ID绑定消息失败:', error);
+ }
+ }
+ },
+
+ // WebSocket重连机制
+ reconnectWebSocket() {
+ if (this.is_exit) {
+ console.log(this.is_exit);
+ return false;
+ }
+ this.reconnectAttempts++;
+ console.log(`尝试第${this.reconnectAttempts}次重连WebSocket`);
+
+ // 清除之前的重连定时器
+ if (this.reconnectTimer) {
+ clearTimeout(this.reconnectTimer);
+ }
+
+ // 设置重连延迟,指数退避策略
+ const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 10000);
+ this.reconnectTimer = setTimeout(() => {
+ this.initWebSocket();
+ }, delay);
},
// 处理WebSocket消息
@@ -451,6 +489,10 @@
case 'message':
// 收到新消息
this.handleNewMessage(data);
+ break;
+ case 'read':
+ // 收到已读确认
+ this.handleReadMessage(data);
break;
case 'ping':
// 心跳响应
@@ -468,7 +510,7 @@
// 处理新消息
handleNewMessage(data) {
// 检查消息是否属于当前会话
- if (data.business_card_id === this.businessCardId ||
+ if ((data.business_card_id && data.business_card_id === this.businessCardId) ||
(data.conversation_id && data.conversation_id === this.conversationId)) {
// 添加消息到列表
@@ -477,7 +519,8 @@
conversation_id: data.conversation_id,
sender_id: data.user_id,
content: data.content,
- create_time: Math.floor(Date.now() / 1000),
+ send_time: data.send_time,
+ create_time: data.create_time || Math.floor(Date.now() / 1000),
is_read: false
};
@@ -492,7 +535,6 @@
setTimeout(() => {
// 通过WebSocket发送已读标记
this.markMessageAsRead(newMessage.chat_id);
-
// 调用后端API标记消息为已读
this._post('plus.business.chat.chat/markAsRead', {
chat_id: newMessage.chat_id,
@@ -512,33 +554,110 @@
}
},
+ // 处理已读消息
+ handleReadMessage(data) {
+ // 筛选出当前用户发送的、尚未标记为已读的消息
+ const unreadMessages = this.messages.filter(msg => {
+ return msg.sender_id === this.currentUser.user_id && !msg.is_read;
+ });
+ if (unreadMessages.length === 0) {
+ console.log('没有需要标记已读的消息');
+ return;
+ }
+ console.log(`找到 ${unreadMessages.length} 条未读消息,开始批量标记`);
+ // 对每条未读消息调用markMessageAsRead方法
+ unreadMessages.forEach(msg => {
+ this.markMessageAsRead(msg.chat_id);
+ // 同时更新本地消息状态
+ msg.is_read = true;
+ });
+ console.log('所有未读消息已标记为已读');
+ },
+ sendMessages(message){
+ if(message==''){
+ return
+ }
+ this._post('plus.business.chat.chat/sendMessage',{
+ content:this.inputMessage,
+ conversation_id: this.conversationId,
+ business_card_id: this.businessCardId,
+ },res=>{
+ // 添加消息到本地列表
+ const localMessage = {
+ chat_id: Date.now(),
+ conversation_id: this.conversationId,
+ sender_id: this.currentUser.user_id,
+ content: this.inputMessage,
+ create_time: Math.floor(Date.now() / 1000),
+ send_time: (Date.now() / 1000),
+ is_read: false
+ };
+ this.messages.push(localMessage);
+ this.inputMessage = '';
+ })
+ },
// 发送WebSocket消息
sendWebSocketMessage(message) {
let self = this;
- if (!this.socketTask || !this.isOnline) {
- console.warn('WebSocket未连接,无法发送消息');
+ if (!this.socketTask) {
self.initWebSocket();
+ self.sendMessages(message);
+ // 等待连接建立后再发送消息
+ setTimeout(() => {
+ self.sendWebSocketMessage('');
+ }, 1000);
return;
}
+
const wsMessage = {
type: 'message',
user_id: this.currentUser.user_id,
to_user_id: this.targetUserId,
content: message,
- conversation_id: this.conversationId,
- business_card_id: this.businessCardId,
app_id: this.currentUser.grade.app_id
};
+
+ // 检查连接状态
+ if (!this.isOnline) {
+ self.initWebSocket();
+ // 等待连接建立后再发送消息
+ self.sendMessages(message);
+ setTimeout(() => {
+ self.sendWebSocketMessage('');
+ }, 1000);
+ return;
+ }
+ if(message==''){
+ return
+ }
try {
self.socketTask.send({
data: JSON.stringify(wsMessage)
});
- self.page = 1
- self.loadMessages()
+ // 添加消息到本地列表
+ const localMessage = {
+ chat_id: Date.now(),
+ conversation_id: this.conversationId,
+ sender_id: this.currentUser.user_id,
+ content: message,
+ create_time: Math.floor(Date.now() / 1000),
+ send_time: (Date.now() / 1000),
+ is_read: false
+ };
+ self.messages.push(localMessage);
self.inputMessage = '';
- console.log('WebSocket消息发送成功:', wsMessage);
+
+ // 滚动到底部 - 使用更强的保证方式
+ this.$nextTick(() => {
+ // 延迟一小段时间确保DOM更新完成
+ setTimeout(() => {
+ this.scrollToBottom();
+ }, 50);
+ });
} catch (error) {
- console.error('发送WebSocket消息失败:', error);
+ console.log('发送WebSocket消息失败:', error);
+ // 尝试重连
+ this.reconnectWebSocket();
}
},
@@ -562,10 +681,10 @@
data: JSON.stringify(heartbeatMsg)
});
} catch (error) {
- console.error('发送心跳失败:', error);
+ console.log('发送心跳失败:', error);
}
}
- }, 3000); // 30秒
+ }, 30000); // 30秒
},
// 标记消息为已读
@@ -587,7 +706,7 @@
data: JSON.stringify(readMsg)
});
} catch (error) {
- console.error('发送已读标记失败:', error);
+ console.log('发送已读标记失败:', error);
}
},
@@ -605,7 +724,7 @@
data: JSON.stringify(closeMsg)
});
} catch (error) {
- console.error('发送关闭消息失败:', error);
+ console.log('发送关闭消息失败:', error);
}
// 关闭WebSocket连接
@@ -620,16 +739,13 @@
}
this.isOnline = false;
- console.log('WebSocket连接已关闭');
},
// 滚动相关方法
scrollToBottom() {
- let self=this;
- this.$nextTick(() => {
- console.log(self.scrollTop);
- self.scrollTop = self.oldScrollTop + 1;
- });
+ console.log(this.scrollTop);
+ // 增加滚动距离确保到达底部
+ this.scrollTop = this.oldScrollTop + 10000;
},
onScroll(e) {
@@ -778,7 +894,7 @@
if (!timeStr) return '';
// 处理日期字符串,将yyyy-MM-dd转换为yyyy/MM/dd以兼容iOS
- const formattedTimeStr = typeof timeStr === 'string' ? timeStr.replace(/\-/g, '/') : timeStr;
+ const formattedTimeStr = typeof timeStr === 'string' ? timeStr.replace(/\-/g, '/') : timeStr * 1000;
const date = new Date(formattedTimeStr);
const now = new Date();
--
Gitblit v1.9.2