using System.Threading.Tasks; using F9MES.Application.Im; using F9MES.Common.Auth; using F9MES.Common.Result; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace F9MES.Api.Controllers; /// 轻量 IM:单聊 + 系统通知(SSE 长连接实时推送) [ApiController] [Route("api/im")] [Authorize] public class ImController : ControllerBase { private readonly ImService _im; private readonly ImEventHub _hub; private readonly CurrentUserService _currentUser; public ImController(ImService im, ImEventHub hub, CurrentUserService currentUser) { _im = im; _hub = hub; _currentUser = currentUser; } /// /// SSE 长连接:订阅新消息/通知的实时推送。 /// 客户端用 fetch 流式读取(EventSource 无法携带 Authorization header), /// 收到 message 事件后刷新会话/消息列表即可,无需再轮询。 /// [HttpGet("events")] public async Task Events(CancellationToken ct) { var me = _currentUser.UserId; if (me <= 0) { Response.StatusCode = StatusCodes.Status401Unauthorized; return; } _im.TouchActive(); Response.ContentType = "text/event-stream"; Response.Headers.CacheControl = "no-cache"; Response.Headers.Append("Connection", "keep-alive"); await _hub.SubscribeAsync(me, Response, ct); } /// 会话列表 [HttpGet("sessions")] public async Task Sessions() { var list = await _im.GetSessionsAsync(); return Ok(ApiResult.Ok(list)); } /// 与某人的聊天记录 [HttpGet("messages")] public async Task Messages([FromQuery] long peerId, [FromQuery] int page = 1, [FromQuery] int size = 20) { var (items, total) = await _im.GetMessagesAsync(peerId, page, size); return Ok(ApiResult.Ok(new { items, total, page, size })); } /// 发送单聊消息 [HttpPost("send")] public async Task Send([FromBody] ImSendInput input) { await _im.SendAsync(input.PeerId, input.Content); return Ok(ApiResult.Ok(true, "发送成功")); } /// 标记与某人的会话已读 [HttpPost("read")] public async Task Read([FromBody] ImReadInput input) { await _im.ReadAsync(input.PeerId); return Ok(ApiResult.Ok(true)); } /// 未读消息总数(顶栏角标) [HttpGet("unread-count")] public async Task UnreadCount() { var count = await _im.GetUnreadCountAsync(); return Ok(ApiResult.Ok(count)); } /// 系统/业务通知群发(工单/工艺单变更等) [HttpPost("notify")] public async Task Notify([FromBody] ImNotifyInput input) { var count = await _im.NotifyAsync(input); return Ok(ApiResult.Ok(count, $"已发送 {count} 条通知")); } }