From 4ab2c2b23765c160b66ddfbc807b0f99be609368 Mon Sep 17 00:00:00 2001 From: 18631081161 <2088094923@qq.com> Date: Wed, 28 Jan 2026 19:42:20 +0800 Subject: [PATCH] =?UTF-8?q?=E8=81=8A=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miniapp/pages/chat/index.vue | 117 ++++++++++++++++-- miniapp/pages/index/index.vue | 17 ++- miniapp/pages/profile/detail.vue | 15 ++- .../Controllers/ChatController.cs | 15 ++- .../Services/ChatService.cs | 4 + 5 files changed, 157 insertions(+), 11 deletions(-) diff --git a/miniapp/pages/chat/index.vue b/miniapp/pages/chat/index.vue index 15bc159..9fe1f08 100644 --- a/miniapp/pages/chat/index.vue +++ b/miniapp/pages/chat/index.vue @@ -272,9 +272,13 @@ - + - + @@ -379,6 +383,12 @@ const hasMore = ref(true) const pageIndex = ref(1) const isInputFocused = ref(false) +// 交换状态 - 记录是否已成功交换过微信/照片 +const hasExchangedWeChat = ref(false) +const hasExchangedPhoto = ref(false) +const exchangedWeChat = ref('') // 已交换的微信号 +const exchangedPhotos = ref([]) // 已交换的照片列表 + // 输入模式:text | voice const inputMode = ref('text') @@ -528,6 +538,9 @@ const loadMessages = async (isLoadMore = false) => { scrollToBottom() } + // 检查是否有已成功交换的微信/照片 + checkExchangeStatus() + hasMore.value = newMessages.length >= 20 console.log('[Chat] 消息加载完成,标记会话已读:', sessionId.value) chatStore.markSessionAsRead(sessionId.value) @@ -546,6 +559,30 @@ const loadMoreMessages = () => { loadMessages(true) } +/** + * 检查消息列表中是否有已成功交换的微信/照片 + * 用于更新按钮状态 + */ +const checkExchangeStatus = () => { + // 遍历所有消息,查找已接受的交换请求 + for (const msg of messages.value) { + // 检查微信交换 + if (msg.messageType === MessageType.EXCHANGE_WECHAT && msg.status === ExchangeStatus.ACCEPTED) { + hasExchangedWeChat.value = true + if (msg.exchangedContent) { + exchangedWeChat.value = msg.exchangedContent + } + } + // 检查照片交换 + if (msg.messageType === MessageType.EXCHANGE_PHOTO && msg.status === ExchangeStatus.ACCEPTED) { + hasExchangedPhoto.value = true + if (msg.photos && msg.photos.length > 0) { + exchangedPhotos.value = msg.photos + } + } + } +} + // 发送文本消息 (Requirements 7.2) const handleSendMessage = async () => { const content = inputText.value.trim() @@ -760,6 +797,27 @@ const stopVoice = () => { // 交换微信 (Requirements 7.3) const handleExchangeWeChat = async () => { + // 如果已交换过,直接显示微信号 + if (hasExchangedWeChat.value && exchangedWeChat.value) { + uni.showModal({ + title: `${targetNickname.value}的微信号`, + content: exchangedWeChat.value, + confirmText: '复制', + success: (res) => { + if (res.confirm) { + uni.setClipboardData({ + data: exchangedWeChat.value, + success: () => { + uni.showToast({ title: '已复制微信号', icon: 'success' }) + } + }) + } + } + }) + return + } + + // 未交换过,发送交换请求 try { const res = await exchangeWeChat(sessionId.value, targetUserId.value) if (res && res.code === 0) { @@ -787,6 +845,16 @@ const handleExchangeWeChat = async () => { } const handleExchangePhoto = async () => { + // 如果已交换过,直接预览照片 + if (hasExchangedPhoto.value && exchangedPhotos.value.length > 0) { + uni.previewImage({ + urls: exchangedPhotos.value, + current: exchangedPhotos.value[0] + }) + return + } + + // 未交换过,发送交换请求 try { const res = await exchangePhoto(sessionId.value, targetUserId.value) if (res && res.code === 0) { @@ -828,12 +896,18 @@ const handleRespondExchange = async (messageId, accept) => { if (message.messageType === MessageType.EXCHANGE_WECHAT) { // 我是接收者,所以获取发送者的微信号 message.exchangedContent = exchangedData.SenderWeChat || exchangedData.senderWeChat + // 更新交换状态 + hasExchangedWeChat.value = true + exchangedWeChat.value = message.exchangedContent } else if (message.messageType === MessageType.EXCHANGE_PHOTO) { // 我是接收者,所以获取发送者的照片 const photos = exchangedData.SenderPhotos || exchangedData.senderPhotos || [] if (Array.isArray(photos)) { message.photos = photos message.photoCount = photos.length + // 更新交换状态 + hasExchangedPhoto.value = true + exchangedPhotos.value = photos } } } catch (e) { @@ -1110,44 +1184,71 @@ const handleReceiveMessage = (message) => { // 处理交换结果消息(5=交换微信结果,7=交换照片结果) if (message.messageType === MessageType.EXCHANGE_WECHAT_RESULT || message.messageType === MessageType.EXCHANGE_PHOTO_RESULT) { + console.log('[Chat] 收到交换结果消息:', message) // 更新原始请求消息的状态 if (message.extraData) { try { const extraData = typeof message.extraData === 'string' ? JSON.parse(message.extraData) : message.extraData + console.log('[Chat] 交换结果extraData:', extraData) + // 根据结果消息类型找到对应的请求消息类型 const requestType = message.messageType === MessageType.EXCHANGE_WECHAT_RESULT ? MessageType.EXCHANGE_WECHAT : MessageType.EXCHANGE_PHOTO - // 找到原始请求消息(我发起的,状态为待处理) - const requestMsg = messages.value.find(m => - m.messageType === requestType && - m.isMine && - m.status === ExchangeStatus.PENDING - ) + // 优先使用 RequestMessageId 精确匹配,兼容大小写 + const requestMessageId = extraData.RequestMessageId || extraData.requestMessageId + let requestMsg = null + + if (requestMessageId) { + // 通过 ID 精确匹配 + requestMsg = messages.value.find(m => m.id === requestMessageId) + console.log('[Chat] 通过ID匹配请求消息:', requestMessageId, requestMsg) + } + + // 如果没找到,回退到类型+状态匹配(我发起的,状态为待处理) + if (!requestMsg) { + requestMsg = messages.value.find(m => + m.messageType === requestType && + m.isMine && + m.status === ExchangeStatus.PENDING + ) + console.log('[Chat] 通过类型匹配请求消息:', requestMsg) + } if (requestMsg) { // 根据响应内容判断是同意还是拒绝 const isAgreed = message.content === '已同意交换' requestMsg.status = isAgreed ? ExchangeStatus.ACCEPTED : ExchangeStatus.REJECTED + console.log('[Chat] 更新请求消息状态:', isAgreed ? 'ACCEPTED' : 'REJECTED') if (isAgreed) { // 更新交换的数据 if (requestMsg.messageType === MessageType.EXCHANGE_WECHAT) { // 我是发起方,获取对方(接收者)的微信号 requestMsg.exchangedContent = extraData.ReceiverWeChat || extraData.receiverWeChat + // 更新交换状态 + hasExchangedWeChat.value = true + exchangedWeChat.value = requestMsg.exchangedContent } else if (requestMsg.messageType === MessageType.EXCHANGE_PHOTO) { // 我是发起方,获取对方(接收者)的照片 const photos = extraData.ReceiverPhotos || extraData.receiverPhotos || [] requestMsg.photos = photos requestMsg.photoCount = photos.length + // 更新交换状态 + hasExchangedPhoto.value = true + exchangedPhotos.value = photos } } console.log('[Chat] 已更新交换请求状态:', requestMsg) + } else { + console.warn('[Chat] 未找到对应的请求消息') } } catch (e) { console.error('[Chat] 解析交换结果数据失败:', e) } + } else { + console.warn('[Chat] 交换结果消息没有extraData') } return } diff --git a/miniapp/pages/index/index.vue b/miniapp/pages/index/index.vue index b54e697..7b27a36 100644 --- a/miniapp/pages/index/index.vue +++ b/miniapp/pages/index/index.vue @@ -719,8 +719,23 @@ export default { if (res.data.isUnlocked) { // 已解锁,直接跳转聊天页 navigateToPage(`/pages/chat/index?targetUserId=${userId}`) + } else if (userStore.isMember) { + // 会员直接解锁,不显示弹窗 + try { + uni.showLoading({ title: '解锁中...' }) + const unlockRes = await unlock(userId) + uni.hideLoading() + if (unlockRes?.code === 0) { + navigateToPage(`/pages/chat/index?targetUserId=${userId}`) + } else { + uni.showToast({ title: unlockRes?.message || '解锁失败', icon: 'none' }) + } + } catch (error) { + uni.hideLoading() + uni.showToast({ title: '解锁失败', icon: 'none' }) + } } else { - // 未解锁,显示解锁确认弹窗 + // 非会员,显示解锁确认弹窗 unlockTargetUserId.value = userId remainingUnlockQuota.value = res.data.remainingUnlockQuota || 0 showUnlockPopup.value = true diff --git a/miniapp/pages/profile/detail.vue b/miniapp/pages/profile/detail.vue index 5dd467b..32acf1c 100644 --- a/miniapp/pages/profile/detail.vue +++ b/miniapp/pages/profile/detail.vue @@ -576,7 +576,7 @@ const handleFavorite = async () => { } // 联系处理 -const handleContact = () => { +const handleContact = async () => { // 检查是否登录 if (!userStore.isLoggedIn) { uni.showModal({ @@ -598,8 +598,21 @@ const handleContact = () => { } if (isUnlocked.value) { + // 已解锁,直接跳转聊天页 uni.navigateTo({ url: `/pages/chat/index?targetUserId=${userId.value}` }) + } else if (userStore.isMember) { + // 会员直接解锁,不显示弹窗 + try { + const res = await unlock(userId.value) + if (res && (res.success || res.code === 0)) { + isUnlocked.value = true + uni.navigateTo({ url: `/pages/chat/index?targetUserId=${userId.value}` }) + } + } catch (error) { + uni.showToast({ title: '解锁失败', icon: 'none' }) + } } else { + // 非会员显示解锁弹窗 showUnlockPopup.value = true } } diff --git a/server/src/XiangYi.AppApi/Controllers/ChatController.cs b/server/src/XiangYi.AppApi/Controllers/ChatController.cs index fe8991c..0c50a0b 100644 --- a/server/src/XiangYi.AppApi/Controllers/ChatController.cs +++ b/server/src/XiangYi.AppApi/Controllers/ChatController.cs @@ -257,6 +257,19 @@ public class ChatController : ControllerBase // 通过 SignalR 推送交换响应结果给会话组(双方都能收到) var resultMessageType = result.RequestMessageType == 4 ? 5 : 7; // 4=ExchangeWeChatRequest->5=Result, 6=ExchangePhotoRequest->7=Result + + // 构建 ExtraData,确保始终包含 RequestMessageId(即使拒绝时也需要) + var extraDataForPush = result.ExchangedData; + if (string.IsNullOrEmpty(extraDataForPush)) + { + // 拒绝时 ExchangedData 为空,需要手动构建包含 RequestMessageId 的数据 + extraDataForPush = System.Text.Json.JsonSerializer.Serialize(new + { + RequestMessageId = result.RequestMessageId, + Status = result.IsAgreed ? 1 : 2 + }); + } + var messageResponse = new ChatMessageResponse { MessageId = result.ResultMessageId, @@ -265,7 +278,7 @@ public class ChatController : ControllerBase ReceiverId = result.RequesterId, MessageType = resultMessageType, Content = result.IsAgreed ? "已同意交换" : "已拒绝交换", - ExtraData = result.ExchangedData, + ExtraData = extraDataForPush, IsRead = false, CreateTime = DateTime.Now, IsSelf = false diff --git a/server/src/XiangYi.Application/Services/ChatService.cs b/server/src/XiangYi.Application/Services/ChatService.cs index feeb568..4ddcb3a 100644 --- a/server/src/XiangYi.Application/Services/ChatService.cs +++ b/server/src/XiangYi.Application/Services/ChatService.cs @@ -557,8 +557,10 @@ public class ChatService : IChatService extraData.SenderWeChat = senderProfile?.WeChatNo; extraData.ReceiverWeChat = receiverProfile?.WeChatNo; + // 包含 RequestMessageId 以便前端精确匹配 exchangedData = JsonSerializer.Serialize(new { + RequestMessageId = request.RequestMessageId, SenderWeChat = extraData.SenderWeChat, ReceiverWeChat = extraData.ReceiverWeChat }); @@ -572,8 +574,10 @@ public class ChatService : IChatService extraData.SenderPhotos = senderPhotos.OrderBy(p => p.Sort).Select(p => p.PhotoUrl).ToList(); extraData.ReceiverPhotos = receiverPhotos.OrderBy(p => p.Sort).Select(p => p.PhotoUrl).ToList(); + // 包含 RequestMessageId 以便前端精确匹配 exchangedData = JsonSerializer.Serialize(new { + RequestMessageId = request.RequestMessageId, SenderPhotos = extraData.SenderPhotos, ReceiverPhotos = extraData.ReceiverPhotos });