using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using XiangYi.AppApi.Hubs;
using XiangYi.Application.DTOs.Requests;
using XiangYi.Application.DTOs.Responses;
using XiangYi.Application.Interfaces;
using XiangYi.Core.Constants;
using System.Security.Claims;
namespace XiangYi.AppApi.Controllers;
///
/// 聊天控制器
///
[ApiController]
[Route("api/app/chat")]
[Authorize]
public class ChatController : ControllerBase
{
private readonly IChatService _chatService;
private readonly IHubContext _hubContext;
private readonly ILogger _logger;
public ChatController(
IChatService chatService,
IHubContext hubContext,
ILogger logger)
{
_chatService = chatService;
_hubContext = hubContext;
_logger = logger;
}
///
/// 获取会话列表
///
/// 会话列表
[HttpGet("sessions")]
public async Task>> GetSessions()
{
var userId = GetCurrentUserId();
var result = await _chatService.GetSessionsAsync(userId);
return ApiResponse>.Success(result);
}
///
/// 获取消息列表
///
/// 会话ID
/// 页码
/// 每页数量
/// 消息列表
[HttpGet("messages")]
public async Task>> GetMessages(
[FromQuery] long sessionId,
[FromQuery] int pageIndex = 1,
[FromQuery] int pageSize = 20)
{
if (sessionId <= 0)
{
return ApiResponse>.Error(ErrorCodes.InvalidParameter, "会话ID无效");
}
var userId = GetCurrentUserId();
// 检查是否有权限访问会话
var canAccess = await _chatService.CanAccessSessionAsync(userId, sessionId);
if (!canAccess)
{
return ApiResponse>.Error(ErrorCodes.Forbidden, "无权访问该会话");
}
var request = new GetMessagesRequest
{
SessionId = sessionId,
PageIndex = pageIndex,
PageSize = pageSize
};
var result = await _chatService.GetMessagesAsync(userId, request);
// 标记消息已读
await _chatService.MarkMessagesAsReadAsync(userId, sessionId);
return ApiResponse>.Success(result);
}
///
/// 发送消息
///
/// 发送消息请求
/// 发送结果
[HttpPost("send")]
public async Task> SendMessage([FromBody] SendMessageRequest request)
{
if (request.SessionId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "会话ID无效");
}
if (request.ReceiverId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "接收者ID无效");
}
var userId = GetCurrentUserId();
// 检查是否有权限访问会话
var canAccess = await _chatService.CanAccessSessionAsync(userId, request.SessionId);
if (!canAccess)
{
return ApiResponse.Error(ErrorCodes.Forbidden, "无权访问该会话");
}
var result = await _chatService.SendMessageAsync(userId, request);
// 通过 SignalR 推送消息给会话中的所有用户
var messageResponse = new ChatMessageResponse
{
MessageId = result.MessageId,
SessionId = request.SessionId,
SenderId = userId,
ReceiverId = request.ReceiverId,
MessageType = request.MessageType,
Content = request.Content,
VoiceUrl = request.VoiceUrl,
VoiceDuration = request.VoiceDuration,
IsRead = false,
CreateTime = result.CreateTime,
IsSelf = false // 接收者收到时不是自己发的
};
// 推送给会话组(双方都能收到)
await _hubContext.SendMessageToSessionAsync(request.SessionId, messageResponse);
_logger.LogInformation("消息已通过SignalR推送到会话组: MessageId={MessageId}, SessionId={SessionId}",
result.MessageId, request.SessionId);
return ApiResponse.Success(result);
}
///
/// 请求交换微信
///
/// 交换微信请求
/// 交换请求结果
[HttpPost("exchangeWeChat")]
public async Task> ExchangeWeChat([FromBody] ExchangeWeChatRequest request)
{
if (request.SessionId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "会话ID无效");
}
if (request.ReceiverId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "接收者ID无效");
}
var userId = GetCurrentUserId();
// 检查是否有权限访问会话
var canAccess = await _chatService.CanAccessSessionAsync(userId, request.SessionId);
if (!canAccess)
{
return ApiResponse.Error(ErrorCodes.Forbidden, "无权访问该会话");
}
var result = await _chatService.ExchangeWeChatAsync(userId, request);
// 通过 SignalR 推送交换请求给会话组
var messageResponse = new ChatMessageResponse
{
MessageId = result.RequestMessageId,
SessionId = request.SessionId,
SenderId = userId,
ReceiverId = request.ReceiverId,
MessageType = 4, // ExchangeWeChatRequest
Content = "请求交换微信",
IsRead = false,
CreateTime = result.CreateTime,
IsSelf = false
};
await _hubContext.SendMessageToSessionAsync(request.SessionId, messageResponse);
_logger.LogInformation("交换微信请求已通过SignalR推送到会话组: MessageId={MessageId}, SessionId={SessionId}",
result.RequestMessageId, request.SessionId);
return ApiResponse.Success(result);
}
///
/// 请求交换照片
///
/// 交换照片请求
/// 交换请求结果
[HttpPost("exchangePhoto")]
public async Task> ExchangePhoto([FromBody] ExchangePhotoRequest request)
{
if (request.SessionId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "会话ID无效");
}
if (request.ReceiverId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "接收者ID无效");
}
var userId = GetCurrentUserId();
// 检查是否有权限访问会话
var canAccess = await _chatService.CanAccessSessionAsync(userId, request.SessionId);
if (!canAccess)
{
return ApiResponse.Error(ErrorCodes.Forbidden, "无权访问该会话");
}
var result = await _chatService.ExchangePhotoAsync(userId, request);
// 通过 SignalR 推送交换请求给会话组
var messageResponse = new ChatMessageResponse
{
MessageId = result.RequestMessageId,
SessionId = request.SessionId,
SenderId = userId,
ReceiverId = request.ReceiverId,
MessageType = 6, // ExchangePhotoRequest
Content = "请求交换照片",
IsRead = false,
CreateTime = result.CreateTime,
IsSelf = false
};
await _hubContext.SendMessageToSessionAsync(request.SessionId, messageResponse);
_logger.LogInformation("交换照片请求已通过SignalR推送到会话组: MessageId={MessageId}, SessionId={SessionId}",
result.RequestMessageId, request.SessionId);
return ApiResponse.Success(result);
}
///
/// 响应交换请求
///
/// 响应请求
/// 响应结果
[HttpPost("respondExchange")]
public async Task> RespondExchange([FromBody] RespondExchangeRequest request)
{
if (request.RequestMessageId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "请求消息ID无效");
}
var userId = GetCurrentUserId();
var result = await _chatService.RespondExchangeAsync(userId, request);
// 通过 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,
SessionId = result.SessionId,
SenderId = userId,
ReceiverId = result.RequesterId,
MessageType = resultMessageType,
Content = result.IsAgreed ? "已同意交换" : "已拒绝交换",
ExtraData = extraDataForPush,
IsRead = false,
CreateTime = DateTime.Now,
IsSelf = false
};
await _hubContext.SendMessageToSessionAsync(result.SessionId, messageResponse);
_logger.LogInformation("交换响应已通过SignalR推送到会话组: ResultMessageId={ResultMessageId}, SessionId={SessionId}, IsAgreed={IsAgreed}",
result.ResultMessageId, result.SessionId, result.IsAgreed);
return ApiResponse.Success(result);
}
///
/// 获取未读消息数
///
/// 未读消息数
[HttpGet("unreadCount")]
public async Task> GetUnreadCount()
{
var userId = GetCurrentUserId();
var count = await _chatService.GetUnreadCountAsync(userId);
return ApiResponse.Success(count);
}
///
/// 获取或创建会话
///
/// 目标用户ID
/// 会话ID
[HttpGet("session")]
public async Task> GetOrCreateSession([FromQuery] long targetUserId)
{
if (targetUserId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "目标用户ID无效");
}
var userId = GetCurrentUserId();
if (userId == targetUserId)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "不能与自己创建会话");
}
var sessionId = await _chatService.GetOrCreateSessionAsync(userId, targetUserId);
return ApiResponse.Success(sessionId);
}
///
/// 删除会话
///
/// 删除会话请求
/// 删除结果
[HttpPost("session/delete")]
public async Task DeleteSession([FromBody] DeleteSessionRequest request)
{
if (request.SessionId <= 0)
{
return ApiResponse.Error(ErrorCodes.InvalidParameter, "会话ID无效");
}
var userId = GetCurrentUserId();
// 检查是否有权限访问会话
var canAccess = await _chatService.CanAccessSessionAsync(userId, request.SessionId);
if (!canAccess)
{
return ApiResponse.Error(ErrorCodes.Forbidden, "无权访问该会话");
}
await _chatService.DeleteSessionAsync(userId, request.SessionId);
return ApiResponse.Success("删除成功");
}
///
/// 获取当前用户ID
///
private long GetCurrentUserId()
{
var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
return long.TryParse(userIdClaim, out var userId) ? userId : 0;
}
}
///
/// 删除会话请求
///
public class DeleteSessionRequest
{
///
/// 会话ID
///
public long SessionId { get; set; }
}