瀏覽代碼

用户在线咨询红娘

mazhenhang 1 月之前
父節點
當前提交
7021e09a97

+ 284 - 86
LiangZhiYUMao/pages/matchmaker-workbench/message.vue

@@ -8,67 +8,43 @@
 		</view>
 
 		<scroll-view scroll-y class="content">
-			<!-- 系统通知 -->
-			<view class="message-item system-notification active">
-				<text class="message-type">系统通知</text>
-				<text class="message-time">刚刚</text>
-				<text class="message-content">您的线索审核已通过,获得20积分奖励,当前积分可兑换【资源查看权限】x1</text>
-				<text class="message-footer">完成线索采集,积分+20 (距黄金级还差72分)</text>
+			<!-- 加载中 -->
+			<view v-if="loading" class="loading-container">
+				<text>加载中...</text>
 			</view>
-
-			<!-- 撮合成功通知 -->
-			<view class="message-item match-success">
-				<view class="message-icon heart"></view>
-				<view class="message-body">
-					<text class="message-type">撮合成功通知</text>
-					<text class="message-content">您推荐的王先生和刘女士已成功匹配,获得50积分+100元现金奖励</text>
-				</view>
-				<text class="message-time">10分钟前</text>
-			</view>
-
-			<!-- 今天分组 -->
-			<view class="time-group">
-				<text class="time-label">今天</text>
-			</view>
-
-			<!-- 魏先生消息 -->
-			<view class="message-item user-message">
-				<view class="message-avatar">魏</view>
-				<view class="message-body">
-					<text class="message-type">魏先生</text>
-					<text class="message-content">您好,想了解一下李女士的详细情况,方便沟通吗?</text>
+			
+			<!-- 会话列表 -->
+			<view v-else-if="conversationList.length > 0">
+				<view 
+					v-for="conversation in conversationList" 
+					:key="conversation.conversationID"
+					class="message-item user-message"
+					@click="openChat(conversation)"
+				>
+					<image 
+						v-if="conversation.userProfile.avatar" 
+						:src="conversation.userProfile.avatar" 
+						class="message-avatar-img"
+					/>
+					<view v-else class="message-avatar">
+						{{ conversation.userProfile.nick || conversation.userProfile.userID.charAt(0) }}
+					</view>
+					<view class="message-body">
+						<text class="message-type">{{ conversation.userProfile.nick || conversation.userProfile.userID }}</text>
+						<text class="message-content">{{ getLastMessageText(conversation.lastMessage) }}</text>
+					</view>
+					<view class="message-right">
+						<text class="message-time">{{ formatTime(conversation.lastMessage.lastTime) }}</text>
+						<view v-if="conversation.unreadCount > 0" class="unread-badge">
+							{{ conversation.unreadCount > 99 ? '99+' : conversation.unreadCount }}
+						</view>
+					</view>
 				</view>
-				<text class="message-time">1小时前</text>
-			</view>
-
-			<!-- 昨日分组 -->
-			<view class="time-group">
-				<text class="time-label">昨日</text>
 			</view>
-
-			<!-- 张先生消息 -->
-			<view class="message-item user-message">
-				<view class="message-avatar">张</view>
-				<view class="message-body">
-					<text class="message-type">张先生</text>
-					<text class="message-content">您好,想了解一下王女士的详细情况,方便沟通吗?</text>
-				</view>
-				<text class="message-time">1小时前</text>
-			</view>
-
-			<!-- 更早分组 -->
-			<view class="time-group">
-				<text class="time-label">更早</text>
-			</view>
-
-			<!-- 高先生消息 -->
-			<view class="message-item user-message">
-				<view class="message-avatar">高</view>
-				<view class="message-body">
-					<text class="message-type">高先生</text>
-					<text class="message-content">您好,想了解一下陈女士的详细情况,方便沟通吗?</text>
-				</view>
-				<text class="message-time">1小时前</text>
+			
+			<!-- 空状态 -->
+			<view v-else class="empty-container">
+				<text>暂无消息</text>
 			</view>
 		</scroll-view>
 
@@ -101,65 +77,245 @@
 </template>
 
 <script>
+	import timManager from '@/utils/tim.js'
+	import TIM from '@/utils/tim-wx-sdk.js'
+	
 	export default {
 		data() {
 			return {
-				messages: [
-					{
-						id: 1,
-						type: 'system',
-						title: '系统通知',
-						content: '您的线索审核已通过,获得20积分奖励,当前积分可兑换【资源查看权限】x1',
-						footer: '完成线索采集,积分+20 (距黄金级还差72分)',
-						time: '刚刚',
-						isNew: true
-					},
-					{
-						id: 2,
-						type: 'matchSuccess',
-						title: '撮合成功通知',
-						content: '您推荐的王先生和刘女士已成功匹配,获得50积分+100元现金奖励',
-						time: '10分钟前',
-						isNew: false
-					},
-					{
-						id: 3,
-						type: 'user',
-						title: '王先生',
-						content: '您好,想了解一下李女士的详细情况,方便沟通吗?',
-						time: '1小时前',
-						isNew: false
-					}
-				]
+				loading: true,
+				conversationList: [],
+				matchmakerInfo: null,
+				imUserId: '',
+				totalUnreadCount: 0
+			}
+		},
+		
+		async onLoad() {
+			await this.initIM()
+		},
+		
+		onShow() {
+			// 页面显示时刷新会话列表
+			if (this.imUserId) {
+				this.loadConversationList()
 			}
 		},
+		
+		onUnload() {
+			// 页面卸载时移除监听
+			this.removeListeners()
+		},
+		
 		methods: {
+			// 初始化 IM
+			async initIM() {
+				try {
+					this.loading = true
+					
+					// 1. 获取当前登录用户ID
+					const userId = uni.getStorageSync('userId')
+					if (!userId) {
+						uni.showToast({ title: '请先登录', icon: 'none' })
+						return
+					}
+					
+					// 2. 获取红娘信息
+					const res = await uni.request({
+						url: 'http://localhost:8081/api/matchmaker/current',
+						method: 'GET',
+						data: { userId }
+					})
+					
+					if (res[1].data.code !== 200) {
+						uni.showToast({ title: '获取红娘信息失败', icon: 'none' })
+						return
+					}
+					
+					this.matchmakerInfo = res[1].data.data
+					this.imUserId = this.matchmakerInfo.imUserId  // m_1
+					
+					console.log('✅ 红娘信息:', this.matchmakerInfo)
+					
+					// 3. 获取 UserSig
+					const sigRes = await uni.request({
+						url: `http://localhost:1004/api/im/getUserSig?userId=${this.imUserId}`,
+						method: 'GET'
+					})
+					
+					if (sigRes[1].data.code !== 200) {
+						uni.showToast({ title: '获取UserSig失败', icon: 'none' })
+						return
+					}
+					
+					const userSig = sigRes[1].data.data
+					console.log('✅ 获取到 UserSig')
+					
+					// 4. 登录 IM
+					await timManager.login(this.imUserId, userSig)
+					console.log('✅ 红娘已登录 IM:', this.imUserId)
+					
+					// 5. 监听事件
+					this.addListeners()
+					
+					// 6. 加载会话列表
+					await this.loadConversationList()
+					
+				} catch (error) {
+					console.error('❌ 初始化 IM 失败:', error)
+					uni.showToast({ title: '初始化失败', icon: 'none' })
+				} finally {
+					this.loading = false
+				}
+			},
+			
+			// 加载会话列表
+			async loadConversationList() {
+				try {
+					const tim = timManager.getTim()
+					const { data } = await tim.getConversationList()
+					this.conversationList = data.conversationList
+					
+					// 计算总未读数
+					this.totalUnreadCount = this.conversationList.reduce((total, conv) => {
+						return total + conv.unreadCount
+					}, 0)
+					
+					console.log('✅ 会话列表:', this.conversationList)
+				} catch (error) {
+					console.error('❌ 加载会话列表失败:', error)
+				}
+			},
+			
+			// 添加事件监听
+			addListeners() {
+				const tim = timManager.getTim()
+				
+				// 监听新消息
+				tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived)
+				
+				// 监听会话列表更新
+				tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated)
+			},
+			
+			// 移除事件监听
+			removeListeners() {
+				const tim = timManager.getTim()
+				tim.off(TIM.EVENT.MESSAGE_RECEIVED, this.onMessageReceived)
+				tim.off(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onConversationListUpdated)
+			},
+			
+			// 收到新消息
+			onMessageReceived(event) {
+				console.log('📩 收到新消息:', event.data)
+				// 刷新会话列表
+				this.loadConversationList()
+			},
+			
+			// 会话列表更新
+			onConversationListUpdated(event) {
+				console.log('🔄 会话列表更新:', event.data)
+				this.conversationList = event.data
+				
+				// 更新总未读数
+				this.totalUnreadCount = this.conversationList.reduce((total, conv) => {
+					return total + conv.unreadCount
+				}, 0)
+			},
+			
+			// 打开聊天页面
+			openChat(conversation) {
+				const targetUserId = conversation.userProfile.userID
+				uni.navigateTo({
+					url: `/pages/message/chat?targetUserId=${targetUserId}&fromMatchmaker=true`
+				})
+			},
+			
+			// 获取最后一条消息的文本
+			getLastMessageText(lastMessage) {
+				if (!lastMessage) return ''
+				
+				switch (lastMessage.type) {
+					case TIM.TYPES.MSG_TEXT:
+						return lastMessage.payload.text
+					case TIM.TYPES.MSG_IMAGE:
+						return '[图片]'
+					case TIM.TYPES.MSG_AUDIO:
+						return '[语音]'
+					case TIM.TYPES.MSG_VIDEO:
+						return '[视频]'
+					case TIM.TYPES.MSG_FILE:
+						return '[文件]'
+					default:
+						return '[消息]'
+				}
+			},
+			
+			// 格式化时间
+			formatTime(timestamp) {
+				if (!timestamp) return ''
+				
+				const now = new Date()
+				const msgTime = new Date(timestamp * 1000)
+				const diff = now - msgTime
+				
+				// 一分钟内
+				if (diff < 60000) {
+					return '刚刚'
+				}
+				
+				// 一小时内
+				if (diff < 3600000) {
+					return Math.floor(diff / 60000) + '分钟前'
+				}
+				
+				// 今天
+				if (msgTime.toDateString() === now.toDateString()) {
+					return msgTime.getHours() + ':' + String(msgTime.getMinutes()).padStart(2, '0')
+				}
+				
+				// 昨天
+				const yesterday = new Date(now)
+				yesterday.setDate(yesterday.getDate() - 1)
+				if (msgTime.toDateString() === yesterday.toDateString()) {
+					return '昨天'
+				}
+				
+				// 更早
+				return (msgTime.getMonth() + 1) + '-' + msgTime.getDate()
+			},
+			
 			// 返回上一页
 			goBack() {
 				uni.navigateBack()
 			},
+			
 			// 导航到工作台
 			navigateToWorkbench() {
 				uni.redirectTo({
 					url: '/pages/matchmaker-workbench/index'
 				})
 			},
+			
 			// 导航到我的资源
 			navigateToMyResources() {
 				uni.redirectTo({
 					url: '/pages/matchmaker-workbench/my-resources'
 				})
 			},
+			
 			// 导航到排行榜
 			navigateToRanking() {
 				uni.redirectTo({
 					url: '/pages/matchmaker-workbench/ranking'
 				})
 			},
+			
 			// 导航到消息
 			navigateToMessage() {
 				// 已在消息页面,无需跳转
 			},
+			
 			// 导航到我的
 			navigateToMine() {
 				uni.redirectTo({
@@ -317,6 +473,7 @@
 			display: flex;
 			background: #FFFFFF;
 			border: 2rpx solid #E0E0E0;
+			align-items: center;
 
 			.message-avatar {
 				width: 60rpx;
@@ -330,10 +487,20 @@
 				align-items: center;
 				justify-content: center;
 				margin-right: 20rpx;
+				flex-shrink: 0;
+			}
+			
+			.message-avatar-img {
+				width: 60rpx;
+				height: 60rpx;
+				border-radius: 50%;
+				margin-right: 20rpx;
+				flex-shrink: 0;
 			}
 
 			.message-body {
 				flex: 1;
+				min-width: 0;
 			}
 
 			.message-type {
@@ -349,15 +516,46 @@
 				font-size: 26rpx;
 				color: #666;
 				line-height: 1.4;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				white-space: nowrap;
+			}
+			
+			.message-right {
+				display: flex;
+				flex-direction: column;
+				align-items: flex-end;
+				margin-left: 20rpx;
 			}
 
 			.message-time {
 				font-size: 24rpx;
 				color: #999;
-				margin-top: auto;
+				margin-bottom: 10rpx;
+			}
+			
+			.unread-badge {
+				background: #E91E63;
+				color: #FFFFFF;
+				font-size: 20rpx;
+				padding: 4rpx 10rpx;
+				border-radius: 20rpx;
+				min-width: 36rpx;
+				text-align: center;
 			}
 		}
 	}
+	
+	/* 加载和空状态 */
+	.loading-container,
+	.empty-container {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		padding: 100rpx 0;
+		color: #999;
+		font-size: 28rpx;
+	}
 
 	/* 时间分组 */
 	.time-group {

+ 26 - 3
LiangZhiYUMao/pages/matchmakers/detail.vue

@@ -306,9 +306,32 @@ export default {
 		 * 在线咨询
 		 */
 		consultMatchmaker() {
-			uni.showToast({
-				title: '功能开发中',
-				icon: 'none'
+			if (!this.matchmaker) {
+				uni.showToast({
+					title: '红娘信息未加载',
+					icon: 'none'
+				})
+				return
+			}
+			
+			// 目标用户信息(红娘)
+			// 给红娘 ID 加上 m_ 前缀,避免与普通用户 ID 冲突
+			const matchmakerId = this.matchmaker.id || this.matchmakerId
+			const targetUserId = 'm_' + matchmakerId
+			const targetUserName = this.matchmaker.real_name || '红娘'
+			const targetUserAvatar = this.getAvatarUrl(this.matchmaker.avatar_url)
+			
+			if (!targetUserId) {
+				uni.showToast({
+					title: '缺少红娘ID',
+					icon: 'none'
+				})
+				return
+			}
+			
+			// 跳转到聊天页面,携带对方用户信息和红娘标记
+			uni.navigateTo({
+				url: `/pages/message/chat?targetUserId=${encodeURIComponent(targetUserId)}&targetUserName=${encodeURIComponent(targetUserName)}&targetUserAvatar=${encodeURIComponent(targetUserAvatar)}&fromMatchmaker=1`
 			})
 		},
 

+ 57 - 39
LiangZhiYUMao/pages/message/chat.vue

@@ -307,6 +307,7 @@ export default {
 		isVip: false, // 是否VIP用户
 	    remainingCount: 5, // 剩余可发送消息数(非VIP默认5)
 	    hasMessageLimit: true, // 是否有发送限制(VIP为false)
+	    fromMatchmaker: false, // 是否来自红娘详情页的会话(用户与红娘聊天)
 	    
 	    // 语音录制相关
 	    recorderManager: null, // 录音管理器
@@ -390,6 +391,10 @@ export default {
     this.targetUserName = decodeURIComponent(options.targetUserName || '用户');
     this.targetUserAvatar = decodeURIComponent(options.targetUserAvatar || '/static/default-avatar.svg');
     
+    // 标记是否为用户与红娘的聊天,用于跳过每日5条限制和文本审核
+    // 支持两种格式:'1' 或 'true'
+    this.fromMatchmaker = options.fromMatchmaker === '1' || options.fromMatchmaker === 'true';
+    
     // 生成会话 ID
     this.conversationID = `C2C${this.targetUserId}`;
     
@@ -1112,48 +1117,52 @@ export default {
       const content = this.inputText;
       this.inputText = '';
       
-      // 1. 先进行消息内容审核
-      try {
-        const checkRes = await uni.request({
-          url: 'http://localhost:1004/api/chat/checkMessage',
-          method: 'POST',
-          data: {
-            userId: String(this.userId),
-            content: content
-          },
-          header: {
-            'Content-Type': 'application/json'
-          }
-        });
-        
-        if (checkRes[1].data.code !== 200) {
-          // 审核未通过,显示失败消息
-          const failedMessage = {
-            messageId: 'failed_' + Date.now(),
-            fromUserId: this.userId,
-            toUserId: this.targetUserId,
-            messageType: 1,
-            content: content,
-            sendStatus: 4, // 4表示发送失败
-            failReason: 'audit_failed', // 标记失败原因:审核失败
-            sendTime: new Date(),
-            fromUserName: '我'
-          };
-          
-          this.messages.push(failedMessage);
-          this.scrollToBottom();
-          
-          uni.showToast({
-            title: checkRes[1].data.message || '消息发送失败',
-            icon: 'none',
-            duration: 2000
+      // 1. 先进行消息内容审核(红娘聊天跳过审核)
+      if (!this.fromMatchmaker) {
+        try {
+          const checkRes = await uni.request({
+            url: 'http://localhost:1004/api/chat/checkMessage',
+            method: 'POST',
+            data: {
+              userId: String(this.userId),
+              content: content
+            },
+            header: {
+              'Content-Type': 'application/json'
+            }
           });
           
-          return;
+          if (checkRes[1].data.code !== 200) {
+            // 审核未通过,显示失败消息
+            const failedMessage = {
+              messageId: 'failed_' + Date.now(),
+              fromUserId: this.userId,
+              toUserId: this.targetUserId,
+              messageType: 1,
+              content: content,
+              sendStatus: 4, // 4表示发送失败
+              failReason: 'audit_failed', // 标记失败原因:审核失败
+              sendTime: new Date(),
+              fromUserName: '我'
+            };
+            
+            this.messages.push(failedMessage);
+            this.scrollToBottom();
+            
+            uni.showToast({
+              title: checkRes[1].data.message || '消息发送失败',
+              icon: 'none',
+              duration: 2000
+            });
+            
+            return;
+          }
+        } catch (error) {
+          console.error('❌ 消息审核失败:', error);
+          // 审核接口失败,为了不影响用户体验,继续发送
         }
-      } catch (error) {
-        console.error('❌ 消息审核失败:', error);
-        // 审核接口失败,为了不影响用户体验,继续发送
+      } else {
+        console.log('✅ 红娘聊天模式:跳过文本审核');
       }
       
       // 2. 检查是否被拉黑
@@ -2287,6 +2296,15 @@ export default {
 		     * 从后端获取VIP状态和今日剩余发送次数
 		     */
 		    async getUserMessageLimit() {
+		      // 用户与红娘的聊天:不做每日5条限制,直接视为无限制
+		      if (this.fromMatchmaker) {
+		        this.hasMessageLimit = false;
+		        this.isVip = true;
+		        this.remainingCount = 999;
+		        console.log('✅ 红娘聊天模式:无消息限制');
+		        return;
+		      }
+		      
 		      try {
 		        const [err, res] = await uni.request({
 		          url: 'http://localhost:1004/api/chat/getUserMessageLimit',

+ 98 - 11
service/admin/src/main/java/com/zhentao/service/impl/MarrApplyServiceImpl.java

@@ -2,17 +2,26 @@ package com.zhentao.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zhentao.entity.MarrApply;
+import com.zhentao.entity.Matchmaker;
 import com.zhentao.entity.Users;
 import com.zhentao.service.MarrApplyService;
 import com.zhentao.mapper.MarrApplyMapper;
+import com.zhentao.mapper.MatchmakerMapper;
 import com.zhentao.mapper.UsersMapper;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
 
+import java.time.LocalDateTime;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
 * @author 联想
@@ -25,6 +34,14 @@ public class MarrApplyServiceImpl extends ServiceImpl<MarrApplyMapper, MarrApply
 
     @Autowired
     private UsersMapper usersMapper;
+    
+    @Autowired
+    private MatchmakerMapper matchmakerMapper;
+    
+    private final RestTemplate restTemplate = new RestTemplate();
+    
+    // websocket 服务的 IM 接口地址
+    private static final String IM_SERVICE_URL = "http://localhost:1004/api/im";
 
     @Override
     public Page<MarrApply> pageQuery(Integer pageNum, Integer pageSize, String name, String phone) {
@@ -38,28 +55,98 @@ public class MarrApplyServiceImpl extends ServiceImpl<MarrApplyMapper, MarrApply
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean approve(Long applyId, Integer userId) {
-        // 1. 查询用户是否存在
+        System.out.println("========== 开始审核红娘申请 ==========");
+        System.out.println("申请ID: " + applyId + ", 用户ID: " + userId);
+        
+        // 1. 查询申请信息
+        MarrApply apply = this.getById(applyId);
+        if (apply == null) {
+            throw new RuntimeException("申请记录不存在");
+        }
+        
+        // 2. 查询用户是否存在
         Users user = usersMapper.selectById(userId);
         if (user == null) {
             throw new RuntimeException("用户不存在");
         }
         
-        // 2. 更新用户的isMatchmaker为1
-        user.setIsMatchmaker(1);
-        int userUpdateResult = usersMapper.updateById(user);
+        // 3. 更新用户的isMatchmaker为1
+        // 直接使用 MyBatis-Plus 的 update 方法
+        Users updateUser = new Users();
+        updateUser.setUserId(userId);
+        updateUser.setIsMatchmaker(1);
+        int userUpdateResult = usersMapper.updateById(updateUser);
         if (userUpdateResult <= 0) {
             throw new RuntimeException("更新用户红娘状态失败");
         }
+        System.out.println("✅ 已更新 users 表,is_matchmaker = 1");
         
-        // 3. 更新申请记录的更新人和更新时间
-        MarrApply apply = this.getById(applyId);
-        if (apply != null) {
-            apply.setUpdateTime(new Date());
-            // 这里可以从当前登录用户获取,暂时设置为"系统"
-            apply.setUpdateMan("系统");
-            this.updateById(apply);
+        // 4. 创建 matchmakers 记录
+        Matchmaker matchmaker = new Matchmaker();
+        
+        // 从 marr_apply 表获取数据
+        matchmaker.setRealName(apply.getName());           // 真实姓名
+        matchmaker.setPhone(apply.getPhone());             // 手机号
+        matchmaker.setEmail(apply.getEmail());             // 邮箱
+        matchmaker.setGender(apply.getGender());           // 性别
+        matchmaker.setProfile(apply.getIntroduction());    // 个人简介
+        
+        // 从 users 表获取数据
+        matchmaker.setUsername(user.getNickname() != null ? user.getNickname() : user.getPhone()); // 用户名(优先使用昵称,否则使用手机号)
+        matchmaker.setPassword(user.getPassword());        // 密码(使用用户的密码)
+        matchmaker.setBirthDate(user.getBirthDate());      // 出生日期(更准确)
+        
+        // 头像:根据性别强制设置默认头像
+        if (apply.getGender() != null && apply.getGender() == 1) {
+            // 男性默认头像
+            matchmaker.setAvatarUrl("http://115.190.125.125:9000/dynamic-comments/dynamics/5c645152-9940-41d3-83a9-69ee6e0c0aaa.png");
+        } else {
+            // 女性默认头像(包括性别为2或null的情况)
+            matchmaker.setAvatarUrl("http://115.190.125.125:9000/dynamic-comments/dynamics/c7fb04d7-ee4d-4b3d-bcef-f246da9c841f.png");
+        }
+        
+        // 设置默认值(无法从其他表获取的字段)
+        matchmaker.setMatchmakerType(1);                   // 默认类型:1-普通红娘
+        matchmaker.setLevel(1);                            // 默认等级:1级
+        matchmaker.setSuccessCouples(0);                   // 初始成功撮合数:0
+        matchmaker.setStatus(1);                           // 状态:1-正常
+        matchmaker.setCreateTime(LocalDateTime.now());
+        matchmaker.setUpdateTime(LocalDateTime.now());
+        
+        int insertResult = matchmakerMapper.insert(matchmaker);
+        if (insertResult <= 0) {
+            throw new RuntimeException("创建红娘记录失败");
         }
+        System.out.println("✅ 已创建 matchmakers 记录,matchmaker_id = " + matchmaker.getMatchmakerId());
+        
+        // 5. 导入到腾讯云 IM(使用 m_ + matchmaker_id)
+        String imUserId = "m_" + matchmaker.getMatchmakerId();
+        try {
+            Map<String, String> imParams = new HashMap<>();
+            imParams.put("userId", imUserId);
+            imParams.put("nickname", matchmaker.getRealName());
+            if (matchmaker.getAvatarUrl() != null && !matchmaker.getAvatarUrl().isEmpty()) {
+                imParams.put("faceUrl", matchmaker.getAvatarUrl());
+            }
+            
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.APPLICATION_JSON);
+            HttpEntity<Map<String, String>> request = new HttpEntity<>(imParams, headers);
+            
+            restTemplate.postForObject(IM_SERVICE_URL + "/importUser", request, Map.class);
+            System.out.println("✅ 已导入到腾讯云 IM: imUserId = " + imUserId);
+        } catch (Exception e) {
+            System.err.println("❌ 导入到 IM 失败: " + e.getMessage());
+            e.printStackTrace();
+            // 导入失败不影响审核流程,只记录日志
+        }
+        
+        // 6. 更新申请记录的更新人和更新时间
+        apply.setUpdateTime(new Date());
+        apply.setUpdateMan("系统");
+        this.updateById(apply);
         
+        System.out.println("========== 审核完成 ==========");
         return true;
     }
 

+ 139 - 0
service/homePage/src/main/java/com/zhentao/controller/MatchmakerController.java

@@ -7,9 +7,15 @@ import com.zhentao.entity.Matchmaker;
 import com.zhentao.service.MatchmakerService;
 import com.zhentao.vo.MatchmakerVO;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 红娘控制器
@@ -21,6 +27,11 @@ public class MatchmakerController {
     @Autowired
     private MatchmakerService matchmakerService;
     
+    private final RestTemplate restTemplate = new RestTemplate();
+    
+    // websocket 服务的 IM 接口地址
+    private static final String IM_SERVICE_URL = "http://localhost:1004/api/im";
+    
     /**
      * 分页查询红娘列表
      * 
@@ -65,6 +76,34 @@ public class MatchmakerController {
         }
     }
     
+    /**
+     * 获取当前登录红娘的信息(通过 userId 查询)
+     * 
+     * @param userId 用户ID
+     * @return 红娘信息
+     */
+    @GetMapping("/current")
+    public Result<Map<String, Object>> getCurrentMatchmaker(@RequestParam Integer userId) {
+        try {
+            Matchmaker matchmaker = matchmakerService.getMatchmakerByUserId(userId);
+            if (matchmaker == null) {
+                return Result.error("该用户不是红娘");
+            }
+            
+            Map<String, Object> result = new HashMap<>();
+            result.put("matchmakerId", matchmaker.getMatchmakerId());
+            result.put("realName", matchmaker.getRealName());
+            result.put("avatarUrl", matchmaker.getAvatarUrl());
+            result.put("userId", userId);
+            result.put("imUserId", "m_" + matchmaker.getMatchmakerId());  // IM 用户 ID
+            
+            return Result.success(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("获取红娘信息失败:" + e.getMessage());
+        }
+    }
+    
     /**
      * 获取全职红娘列表(首页展示)
      * 
@@ -109,8 +148,32 @@ public class MatchmakerController {
                 matchmaker.setStatus(1); // 1-正常
             }
             
+            // 保存红娘到数据库
             boolean success = matchmakerService.save(matchmaker);
             if (success) {
+                // 导入红娘到腾讯云 IM(使用 m_ + matchmaker_id)
+                String imUserId = "m_" + matchmaker.getMatchmakerId();
+                try {
+                    // 调用 websocket 服务的 IM 导入接口
+                    Map<String, String> imParams = new HashMap<>();
+                    imParams.put("userId", imUserId);
+                    imParams.put("nickname", matchmaker.getRealName());
+                    if (matchmaker.getAvatarUrl() != null && !matchmaker.getAvatarUrl().isEmpty()) {
+                        imParams.put("faceUrl", matchmaker.getAvatarUrl());
+                    }
+                    
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    HttpEntity<Map<String, String>> request = new HttpEntity<>(imParams, headers);
+                    
+                    restTemplate.postForObject(IM_SERVICE_URL + "/importUser", request, Map.class);
+                    System.out.println("✅ 红娘已导入到腾讯云 IM: matchmakerId=" + matchmaker.getMatchmakerId() + ", imUserId=" + imUserId);
+                } catch (Exception e) {
+                    System.err.println("❌ 导入红娘到 IM 失败: " + e.getMessage());
+                    e.printStackTrace();
+                    // 导入失败不影响红娘创建,只记录日志
+                }
+                
                 // 清除列表缓存
                 matchmakerService.clearMatchmakerCache(null);
                 return Result.success(matchmaker);
@@ -159,8 +222,27 @@ public class MatchmakerController {
     @DeleteMapping("/delete/{matchmakerId}")
     public Result<Void> deleteMatchmaker(@PathVariable Integer matchmakerId) {
         try {
+            // 先查询红娘信息(用于后续删除 IM 账号)
+            Matchmaker matchmaker = matchmakerService.getById(matchmakerId);
+            if (matchmaker == null) {
+                return Result.error("红娘不存在");
+            }
+            
+            // 删除数据库记录
             boolean success = matchmakerService.removeById(matchmakerId);
             if (success) {
+                // 从腾讯云 IM 删除红娘账号(使用 m_ + matchmaker_id)
+                String imUserId = "m_" + matchmakerId;
+                try {
+                    // 调用 websocket 服务的 IM 删除接口
+                    restTemplate.delete(IM_SERVICE_URL + "/deleteAccount?userId=" + imUserId);
+                    System.out.println("✅ 已从腾讯云 IM 删除红娘账号: matchmakerId=" + matchmakerId + ", imUserId=" + imUserId);
+                } catch (Exception e) {
+                    System.err.println("❌ 从 IM 删除账号失败: " + e.getMessage());
+                    e.printStackTrace();
+                    // 删除失败不影响数据库删除,只记录日志
+                }
+                
                 // 清除相关缓存
                 matchmakerService.clearMatchmakerCache(matchmakerId);
                 return Result.success(null);
@@ -190,5 +272,62 @@ public class MatchmakerController {
             return Result.error("获取排行榜失败:" + e.getMessage());
         }
     }
+    
+    /**
+     * 批量导入现有红娘到腾讯云 IM(一次性任务)
+     * 
+     * @return 导入结果
+     */
+    @PostMapping("/batch-import-to-im")
+    public Result<Map<String, Object>> batchImportMatchmakersToIM() {
+        try {
+            List<Matchmaker> matchmakers = matchmakerService.list();
+            
+            int successCount = 0;
+            int failCount = 0;
+            StringBuilder failedIds = new StringBuilder();
+            
+            for (Matchmaker matchmaker : matchmakers) {
+                String imUserId = "m_" + matchmaker.getMatchmakerId();
+                try {
+                    // 调用 websocket 服务的 IM 导入接口
+                    Map<String, String> imParams = new HashMap<>();
+                    imParams.put("userId", imUserId);
+                    imParams.put("nickname", matchmaker.getRealName());
+                    if (matchmaker.getAvatarUrl() != null && !matchmaker.getAvatarUrl().isEmpty()) {
+                        imParams.put("faceUrl", matchmaker.getAvatarUrl());
+                    }
+                    
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    HttpEntity<Map<String, String>> request = new HttpEntity<>(imParams, headers);
+                    
+                    restTemplate.postForObject(IM_SERVICE_URL + "/importUser", request, Map.class);
+                    successCount++;
+                    System.out.println("✅ 导入成功: matchmakerId=" + matchmaker.getMatchmakerId() + ", imUserId=" + imUserId);
+                    
+                    // 避免请求过快
+                    Thread.sleep(100);
+                } catch (Exception e) {
+                    failCount++;
+                    failedIds.append(matchmaker.getMatchmakerId()).append(",");
+                    System.err.println("❌ 导入失败: matchmakerId=" + matchmaker.getMatchmakerId() + ", error=" + e.getMessage());
+                }
+            }
+            
+            Map<String, Object> result = new HashMap<>();
+            result.put("total", matchmakers.size());
+            result.put("successCount", successCount);
+            result.put("failCount", failCount);
+            if (failCount > 0) {
+                result.put("failedIds", failedIds.toString());
+            }
+            
+            return Result.success(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return Result.error("批量导入失败:" + e.getMessage());
+        }
+    }
 }
 

+ 8 - 0
service/homePage/src/main/java/com/zhentao/service/MatchmakerService.java

@@ -48,5 +48,13 @@ public interface MatchmakerService extends IService<Matchmaker> {
      * @return 红娘排行榜列表
      */
     java.util.List<MatchmakerVO> getRankingList(Integer limit);
+    
+    /**
+     * 根据用户ID查询红娘信息
+     * 
+     * @param userId 用户ID
+     * @return 红娘实体
+     */
+    Matchmaker getMatchmakerByUserId(Integer userId);
 }
 

+ 8 - 0
service/homePage/src/main/java/com/zhentao/service/impl/MatchmakerServiceImpl.java

@@ -328,4 +328,12 @@ public class MatchmakerServiceImpl extends ServiceImpl<MatchmakerMapper, Matchma
         
         return rankingList;
     }
+    
+    @Override
+    public Matchmaker getMatchmakerByUserId(Integer userId) {
+        // 根据 user_id 查询红娘信息
+        return this.lambdaQuery()
+                .eq(Matchmaker::getUserId, userId.longValue())
+                .one();
+    }
 }