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 |  280 ++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 202 insertions(+), 78 deletions(-)

diff --git a/mobile/pages/plus/business/chat/chat.vue b/mobile/pages/plus/business/chat/chat.vue
index 035848c..3c1447c 100644
--- a/mobile/pages/plus/business/chat/chat.vue
+++ b/mobile/pages/plus/business/chat/chat.vue
@@ -20,7 +20,7 @@
 					</view>
 					<view class="user-details" v-else>
 						<text class="user-name">{{ card.name}}</text>
-						<text class="user-status" >
+						<text class="user-status">
 							{{ card.unit[0]+' . '+card.position[0]}}
 						</text>
 					</view>
@@ -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>
@@ -192,7 +192,8 @@
 					nickName: '',
 					avatarUrl: ''
 				},
-				card:{},
+				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,22 +230,20 @@
 			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();
-
-			// 初始化WebSocket连接
-			this.initWebSocket();
+			
 		},
 		onUnload() {
+			this.is_exit = true;
 			// 清理定时器
 			if (this.typingTimer) {
 				clearTimeout(this.typingTimer);
@@ -247,7 +251,9 @@
 			if (this.readTimer) {
 				clearTimeout(this.readTimer);
 			}
-
+			if (this.reconnectTimer) {
+				clearTimeout(this.reconnectTimer);
+			}
 			// 关闭WebSocket
 			this.closeWebSocket();
 		},
@@ -272,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();
 				});
 			},
 
@@ -299,12 +309,12 @@
 						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];
 						}
@@ -313,13 +323,10 @@
 						self.loadMore = false;
 						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', {
@@ -332,6 +339,11 @@
 											if (msg.sender_id !== self.currentUser.user_id) {
 												msg.is_read = true;
 											}
+										});
+
+										// 滚动到底部
+										self.$nextTick(() => {
+											self.scrollToBottom();
 										});
 									}
 								});
@@ -347,28 +359,9 @@
 			async sendMessage() {
 				let self = this;
 				if (!this.inputMessage.trim()) return;
-
 				const content = self.inputMessage.trim();
-
-				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);
-						self.inputMessage = '';
-						// 滚动到底部
-						self.$nextTick(() => {
-							self.scrollToBottom();
-						});
-						// 发送WebSocket消息
-						self.sendWebSocketMessage(res.data);
-					} else {
-						self.showError(res.msg || '发送失败');
-					}
-				});
+				console.log(content);
+				self.sendWebSocketMessage(content);
 			},
 
 			// WebSocket相关方法
@@ -378,40 +371,42 @@
 					console.log('WebSocket已连接');
 					return;
 				}
-				console.log(currentUserId);
 				// 获取当前用户ID	
 				const currentUserId = this.currentUser.user_id;
 
-				// 构建WebSocket连接URL
-				const wsUrl = `ws://localhost:8282?user_id=${currentUserId}`;
-
+				// 构建WebSocket连接URL - 使用名片聊天专用端口2349
+				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消息事件
 					this.socketTask.onMessage((res) => {
 						console.log('收到WebSocket消息:', res.data);
-
 						try {
 							const data = JSON.parse(res.data);
+							if (data.Online == 'on') {
+								this.isOnline = false;
+							} else {
+								this.isOnline = true;
+							}
 							this.handleWebSocketMessage(data);
 						} catch (error) {
 							console.error('解析WebSocket消息失败:', error);
@@ -422,6 +417,8 @@
 					this.socketTask.onError((err) => {
 						console.error('WebSocket错误:', err);
 						this.isOnline = false;
+						// 尝试重连
+						this.reconnectWebSocket();
 					});
 
 					// 监听WebSocket关闭事件
@@ -435,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消息
@@ -448,6 +489,10 @@
 					case 'message':
 						// 收到新消息
 						this.handleNewMessage(data);
+						break;
+					case 'read':
+						// 收到已读确认
+						this.handleReadMessage(data);
 						break;
 					case 'ping':
 						// 心跳响应
@@ -465,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)) {
 
 					// 添加消息到列表
@@ -474,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
 					};
 
@@ -489,7 +535,6 @@
 					setTimeout(() => {
 						// 通过WebSocket发送已读标记
 						this.markMessageAsRead(newMessage.chat_id);
-
 						// 调用后端API标记消息为已读
 						this._post('plus.business.chat.chat/markAsRead', {
 							chat_id: newMessage.chat_id,
@@ -509,10 +554,58 @@
 				}
 			},
 
+			// 处理已读消息
+			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) {
-				if (!this.socketTask || !this.isOnline) {
-					console.warn('WebSocket未连接,无法发送消息');
+				let self = this;
+				if (!this.socketTask) {
+					self.initWebSocket();
+					self.sendMessages(message);
+					// 等待连接建立后再发送消息
+					setTimeout(() => {
+						self.sendWebSocketMessage('');
+					}, 1000);
 					return;
 				}
 
@@ -520,19 +613,51 @@
 					type: 'message',
 					user_id: this.currentUser.user_id,
 					to_user_id: this.targetUserId,
-					content: message.content,
-					conversation_id: this.conversationId,
-					business_card_id: this.businessCardId,
-					chat_id: message.chat_id
+					content: message,
+					app_id: this.currentUser.grade.app_id
 				};
 
+				// 检查连接状态
+				if (!this.isOnline) {
+					self.initWebSocket();
+					// 等待连接建立后再发送消息
+					self.sendMessages(message);
+					setTimeout(() => {
+						self.sendWebSocketMessage('');
+					}, 1000);
+					return;
+				}
+				if(message==''){
+					return 
+				}
 				try {
-					this.socketTask.send({
+					self.socketTask.send({
 						data: JSON.stringify(wsMessage)
 					});
-					console.log('WebSocket消息发送成功:', wsMessage);
+					// 添加消息到本地列表
+					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 = '';
+
+					// 滚动到底部 - 使用更强的保证方式
+					this.$nextTick(() => {
+						// 延迟一小段时间确保DOM更新完成
+						setTimeout(() => {
+							this.scrollToBottom();
+						}, 50);
+					});
 				} catch (error) {
-					console.error('发送WebSocket消息失败:', error);
+					console.log('发送WebSocket消息失败:', error);
+					// 尝试重连
+					this.reconnectWebSocket();
 				}
 			},
 
@@ -551,13 +676,12 @@
 							user_id: this.currentUser.user_id,
 							to_user_id: this.targetUserId
 						};
-
 						try {
 							this.socketTask.send({
 								data: JSON.stringify(heartbeatMsg)
 							});
 						} catch (error) {
-							console.error('发送心跳失败:', error);
+							console.log('发送心跳失败:', error);
 						}
 					}
 				}, 30000); // 30秒
@@ -576,13 +700,13 @@
 					chat_id: chatId,
 					conversation_id: this.conversationId
 				};
-
+				console.log(readMsg);
 				try {
 					this.socketTask.send({
 						data: JSON.stringify(readMsg)
 					});
 				} catch (error) {
-					console.error('发送已读标记失败:', error);
+					console.log('发送已读标记失败:', error);
 				}
 			},
 
@@ -591,7 +715,8 @@
 					// 发送关闭消息
 					const closeMsg = {
 						type: 'close',
-						user_id: this.currentUser.user_id
+						user_id: this.currentUser.user_id,
+						to_user_id: this.targetUserId
 					};
 
 					try {
@@ -599,7 +724,7 @@
 							data: JSON.stringify(closeMsg)
 						});
 					} catch (error) {
-						console.error('发送关闭消息失败:', error);
+						console.log('发送关闭消息失败:', error);
 					}
 
 					// 关闭WebSocket连接
@@ -614,14 +739,13 @@
 				}
 
 				this.isOnline = false;
-				console.log('WebSocket连接已关闭');
 			},
 
 			// 滚动相关方法
 			scrollToBottom() {
-				this.$nextTick(() => {
-					this.scrollTop = this.oldScrollTop + 1;
-				});
+				console.log(this.scrollTop);
+				// 增加滚动距离确保到达底部
+				this.scrollTop = this.oldScrollTop + 10000;
 			},
 
 			onScroll(e) {
@@ -770,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