feat: 新增IM即时通讯(浮窗)、工作流、打印模块及工作台增强
- IM: 新增浮窗聊天(ImFloatWindow)、管理页(monitor/config/service/message)、SSE推送 - 工作流: 新增待办/我的流程页面及后端服务 - 打印: 新增打印模板、出库单打印(PrintPage)、模板种子脚本 - 工作台: 增强快捷入口与工作台数据 - 修复: TagsView页签关闭、CrudPage通用表格增强 - 移除导航菜单中的即时通讯入口,改为右下角浮窗
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
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;
|
||||
|
||||
/// <summary>轻量 IM:单聊 + 系统通知(SSE 长连接实时推送)</summary>
|
||||
[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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SSE 长连接:订阅新消息/通知的实时推送。
|
||||
/// 客户端用 fetch 流式读取(EventSource 无法携带 Authorization header),
|
||||
/// 收到 message 事件后刷新会话/消息列表即可,无需再轮询。
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>会话列表</summary>
|
||||
[HttpGet("sessions")]
|
||||
public async Task<ActionResult> Sessions()
|
||||
{
|
||||
var list = await _im.GetSessionsAsync();
|
||||
return Ok(ApiResult.Ok(list));
|
||||
}
|
||||
|
||||
/// <summary>与某人的聊天记录</summary>
|
||||
[HttpGet("messages")]
|
||||
public async Task<ActionResult> 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 }));
|
||||
}
|
||||
|
||||
/// <summary>发送单聊消息</summary>
|
||||
[HttpPost("send")]
|
||||
public async Task<ActionResult> Send([FromBody] ImSendInput input)
|
||||
{
|
||||
await _im.SendAsync(input.PeerId, input.Content);
|
||||
return Ok(ApiResult.Ok(true, "发送成功"));
|
||||
}
|
||||
|
||||
/// <summary>标记与某人的会话已读</summary>
|
||||
[HttpPost("read")]
|
||||
public async Task<ActionResult> Read([FromBody] ImReadInput input)
|
||||
{
|
||||
await _im.ReadAsync(input.PeerId);
|
||||
return Ok(ApiResult.Ok(true));
|
||||
}
|
||||
|
||||
/// <summary>未读消息总数(顶栏角标)</summary>
|
||||
[HttpGet("unread-count")]
|
||||
public async Task<ActionResult> UnreadCount()
|
||||
{
|
||||
var count = await _im.GetUnreadCountAsync();
|
||||
return Ok(ApiResult.Ok(count));
|
||||
}
|
||||
|
||||
/// <summary>系统/业务通知群发(工单/工艺单变更等)</summary>
|
||||
[HttpPost("notify")]
|
||||
public async Task<ActionResult> Notify([FromBody] ImNotifyInput input)
|
||||
{
|
||||
var count = await _im.NotifyAsync(input);
|
||||
return Ok(ApiResult.Ok(count, $"已发送 {count} 条通知"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user