using NCC.Common.Core.Manager; using NCC.Common.Enum; using NCC.Common.Extension; using NCC.Common.Filter; using NCC.Dependency; using NCC.DynamicApiController; using NCC.FriendlyException; using NCC.JsonSerialization; using NCC.LinqBuilder; using NCC.Message.Entitys; using NCC.Message.Entitys.Dto.Message; using NCC.Message.Extensions; using NCC.Message.Interfaces.Message; using NCC.System.Entitys.Permission; using NCC.System.Interfaces.Permission; using Mapster; using Microsoft.AspNetCore.Mvc; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Yitter.IdGenerator; using NCC.Message.Entitys.Dto.IM; namespace NCC.Message.Service { ///     /// 系统消息     /// 版 本:V1.20.15     /// 版 权:Wesley(https://www.NCCsoft.com)     /// 作 者:NCC开发平台组     /// 日 期:2022-03-16     /// [ApiDescriptionSettings(Tag = "Message", Name = "message", Order = 240)] [Route("api/[controller]")] public class MessageService : IMessageService, IDynamicApiController, ITransient { private readonly ISqlSugarRepository _messageRepository; private readonly ISqlSugarRepository _messageReceiveRepository; private readonly SqlSugarScope db; private readonly IUserManager _userManager; private readonly IUsersService _usersService; private readonly ISqlSugarRepository _IMContentRepository; private readonly ISqlSugarRepository _roomMessageRepository; /// /// /// /// /// /// /// public MessageService(ISqlSugarRepository messageRepository, ISqlSugarRepository messageReceiveRepository, IUsersService usersService, IUserManager userManager, ISqlSugarRepository iMContentRepository, ISqlSugarRepository roomMessageRepository) { _messageRepository = messageRepository; _messageReceiveRepository = messageReceiveRepository; db = messageRepository.Context; _usersService = usersService; _userManager = userManager; _IMContentRepository = iMContentRepository; _roomMessageRepository = roomMessageRepository; } #region Get /// /// 列表(通知公告) /// /// 请求参数 /// [HttpGet("Notice")] public async Task GetNoticeList([FromQuery] PageInputBase input) { var list = await _messageRepository.Context.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.CreatorUserId)).Select((a, b) => new MessageNoticeOutput { id = a.Id, lastModifyTime = a.LastModifyTime, enabledMark = a.EnabledMark, creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), title = a.Title, deleteMark = SqlFunc.ToString(a.DeleteMark), type = a.Type }).MergeTable().Where(m => m.type == 1 && m.deleteMark == null) .WhereIF(!string.IsNullOrEmpty(input.keyword), m => m.title.Contains(input.keyword)) .OrderBy(t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 列表(通知公告/系统消息/私信消息) /// /// 请求参数 /// [HttpGet("")] public async Task GetMessageList([FromQuery] MessageListInput input) { var list = await _messageRepository.Context.Queryable( (a, b, c) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId, JoinType.Left, a.CreatorUserId == c.Id)).Select((a, b, c) => new MessageListOutput { id = a.Id, lastModifyTime = a.LastModifyTime, enabledMark = a.EnabledMark, creatorUser = SqlFunc.MergeString(c.RealName, "/", c.Account), title = a.Title, deleteMark = a.DeleteMark, type = a.Type, isRead = b.IsRead, userId = b.UserId }).MergeTable() .Where(m => m.userId == _userManager.UserId && m.deleteMark == null) .WhereIF(input.type.IsNotEmptyOrNull(), x => x.type == input.type) .WhereIF(!string.IsNullOrEmpty(input.keyword), m => m.title.Contains(input.keyword)) .OrderBy(t => t.lastModifyTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); return PageResult.SqlSugarPageResult(list); } /// /// 信息 /// /// 主键值 /// [HttpGet("{id}")] public async Task GetInfo_Api(string id) { var data = await _messageRepository.Context.Queryable( (a, b) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id)) .Select((a, b) => new MessageInfoOutput { id = a.Id, lastModifyTime = a.LastModifyTime, creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), title = a.Title, deleteMark = a.DeleteMark, bodyText = a.BodyText }).MergeTable(). Where(m => m.id == id && m.deleteMark == null).FirstAsync(); return data; } /// /// 读取消息 /// /// 主键值 /// [HttpGet("ReadInfo/{id}")] public async Task ReadInfo(string id) { var data = await _messageRepository.Context.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id)) .Select((a, b) => new MessageReadInfoOutput { id = a.Id, lastModifyTime = a.LastModifyTime, creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), title = a.Title, deleteMark = a.DeleteMark, bodyText = a.BodyText }).MergeTable().Where(m => m.id == id && m.deleteMark == null) .OrderBy(t => t.lastModifyTime).FirstAsync(); if (data != null) await MessageRead(id); return data; } #endregion #region 群组/房间 #endregion #region Post /// /// 删除 /// /// 主键值 /// [HttpDelete("{id}")] public async Task Delete(string id) { var entity = await GetInfo(id); var isOk = await Delete(entity); if (isOk < 1) throw NCCException.Oh(ErrorCode.COM1002); } /// /// 新建 /// /// 实体对象 /// [HttpPost("")] public async Task Create([FromBody] MessageCrInput input) { var entity = input.Adapt(); entity.Type = 1; entity.EnabledMark = 0; var isOk = await Create(entity); if (isOk < 1) throw NCCException.Oh(ErrorCode.COM1000); } /// /// 更新 /// /// 主键值 /// 实体对象 /// [HttpPut("{id}")] public async Task Update(string id, [FromBody] MessageUpInput input) { var entity = input.Adapt(); var isOk = await Update(entity); if (isOk < 1) throw NCCException.Oh(ErrorCode.COM1001); } /// /// 发布公告 /// /// 主键值 /// [HttpPut("{id}/Actions/Release")] public async Task Release(string id) { var entity = await GetInfo(id); if (entity != null) { var userList = await _usersService.GetList(); entity.ToUserIds = string.Join(",", userList.Select(m => m.Id).ToList()); //发送 await SentNotice(entity.ToUserIds.Split(',').ToList(), entity); } } /// /// 全部已读 /// /// [HttpPost("Actions/ReadAll")] public async Task AllRead() { await MessageRead(""); } /// /// 删除记录 /// /// 请求参数 /// [HttpDelete("Record")] public async Task DeleteRecord_Api([FromBody] dynamic postParam) { string[] ids = postParam.ids.ToString().Split(','); var isOk = await DeleteRecord(_userManager.UserId, ids.ToList()); if (isOk < 1) throw NCCException.Oh(ErrorCode.COM1002); } #endregion #region PublicMethod ///         /// 列表         ///         /// 类型         ///         [NonAction] public async Task> GetList(int type) { return await _messageRepository.Entities.Where(m => m.Type == type && m.DeleteMark == null).ToListAsync(); } ///         /// 信息         ///         /// 主键值         ///         [NonAction] public async Task GetInfo(string id) { return await _messageRepository.FirstOrDefaultAsync(x => x.Id == id && x.DeleteMark == null); } /// /// 默认公告(app) /// /// [NonAction] public string GetInfoDefaultNotice() { var entity = _messageRepository.Entities.Where(x => x.Type == 1 && x.DeleteMark == null).OrderBy(x => x.CreatorTime, OrderByType.Desc).First(); return entity == null ? "" : entity.Title; } /// /// 默认消息(app) /// /// /// [NonAction] public string GetInfoDefaultMessage(string userId) { var entity = db.Queryable((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId)) .Where((a, b) => a.Type == 2 && a.DeleteMark == null && b.UserId == userId).OrderBy(a => a.CreatorTime, OrderByType.Desc).Select(a => a).First(); return entity == null ? "" : entity.Title; }         ///         /// 删除         ///         /// 实体对象         [NonAction] public async Task Delete(MessageEntity entity) { try { db.BeginTran(); await _messageReceiveRepository.DeleteAsync(x => x.MessageId == entity.Id); var total = await _messageRepository.Context.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.Delete()).ExecuteCommandAsync(); db.CommitTran(); return total; } catch (Exception) { db.RollbackTran(); return 0; } } /// /// 创建 /// /// 实体对象 [NonAction] public async Task Create(MessageEntity entity) { return await _messageRepository.Context.Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } /// /// 创建 /// /// 实体对象 /// 收件用户 [NonAction] public async Task Create(MessageEntity entity, List receiveEntityList) { try { db.BeginTran(); await _messageReceiveRepository.InsertAsync(receiveEntityList); var total = await _messageRepository.Context.Insertable(entity).CallEntityMethod(m => m.Create()).ExecuteCommandAsync(); db.CommitTran(); return total; } catch (Exception ex) { db.RollbackTran(); return 0; } } /// /// 更新 /// /// 实体对象 [NonAction] public async Task Update(MessageEntity entity) { return await _messageRepository.Context.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync(); } /// /// 更新 /// /// 实体对象 /// 收件用户 [NonAction] public async Task Update(MessageEntity entity, List receiveEntityList) { try { db.BeginTran(); await _messageReceiveRepository.InsertAsync(receiveEntityList); var total = await _messageRepository.Context.Updateable(entity).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync(); db.CommitTran(); return total; } catch (Exception ex) { db.RollbackTran(); return 0; } } /// /// 消息已读(单条) /// /// 当前用户 /// 消息主键 [NonAction] public async Task MessageRead(string userId, string messageId) { await db.Updateable().SetColumns(it => it.ReadCount == it.ReadCount + 1).SetColumns(x => new MessageReceiveEntity() { IsRead = 1, ReadTime = DateTime.Now }).Where(x => x.UserId == userId && x.MessageId == messageId).ExecuteCommandAsync(); } /// /// 消息已读(全部) /// /// id [NonAction] public async Task MessageRead(string id) { try { db.BeginTran(); var whereParams = LinqExpression.And(); whereParams = whereParams.And(x => x.UserId == _userManager.UserId && x.IsRead == 0); if (id.IsNotEmptyOrNull()) whereParams = whereParams.And(x => x.MessageId == id); await db.Updateable().SetColumns(it => it.ReadCount == it.ReadCount + 1).SetColumns(x => new MessageReceiveEntity() { IsRead = 1, ReadTime = DateTime.Now }).Where(whereParams).ExecuteCommandAsync(); db.CommitTran(); } catch (Exception e) { db.RollbackTran(); } } /// /// 删除记录 /// /// 当前用户 /// 消息Id [NonAction] public async Task DeleteRecord(string userId, List messageIds) { return await _messageReceiveRepository.DeleteAsync(m => m.UserId == userId && messageIds.Contains(m.MessageId)); } /// /// 获取未读数量(含 通知公告、系统消息) /// /// 用户主键 /// [NonAction] public async Task GetUnreadCount(string userId) { return await _messageReceiveRepository.CountAsync(m => m.UserId == userId && m.IsRead == 0); } /// /// 获取公告未读数量 /// /// 用户主键 /// [NonAction] public int GetUnreadNoticeCount(string userId) { return db.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Select((m, mr) => new { mr.Id, mr.UserId, mr.IsRead, m.Type, m.DeleteMark }).MergeTable().Where(x => x.Type == 1 && x.DeleteMark == null && x.UserId == userId && x.IsRead == 0).Count(); } /// /// 获取消息未读数量 /// /// 用户主键 /// [NonAction] public int GetUnreadMessageCount(string userId) { return db.Queryable((m, mr) => new JoinQueryInfos(JoinType.Left, m.Id == mr.MessageId)).Select((m, mr) => new { mr.Id, mr.UserId, mr.IsRead, m.Type, m.DeleteMark }).MergeTable().Where(x => x.Type == 2 && x.DeleteMark == null && x.UserId == userId && x.IsRead == 0).Count(); } /// /// 发送公告 /// /// 发送用户 /// 消息信息 [NonAction] public async Task SentNotice(List toUserIds, MessageEntity entity) { try { entity.EnabledMark = 1; List receiveEntityList = new List(); foreach (var item in toUserIds) { MessageReceiveEntity messageReceiveEntity = new MessageReceiveEntity(); messageReceiveEntity.Id = YitIdHelper.NextId().ToString(); messageReceiveEntity.MessageId = entity.Id; messageReceiveEntity.UserId = item; messageReceiveEntity.IsRead = 0; receiveEntityList.Add(messageReceiveEntity); } await Update(entity, receiveEntityList); //消息推送 - PC端 foreach (var item in WebSocketClientCollection._clients.FindAll(it => it.TenantId == _userManager.TenantId)) { if (toUserIds.Contains(item.UserId)) { await item.SendMessageAsync(new { method = "messagePush", userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1 }.Serialize()); } } } catch (Exception ex) { throw NCCException.Oh(ErrorCode.D7003); } } /// /// 发送站内消息 /// /// 发送用户 /// 标题 /// 内容 [NonAction] public async Task SentMessage(List toUserIds, string title, string bodyText = null) { try { MessageEntity entity = new MessageEntity(); entity.Id = YitIdHelper.NextId().ToString(); entity.Title = title; entity.BodyText = bodyText; entity.Type = 2; entity.LastModifyTime = DateTime.Now; entity.LastModifyUserId = _userManager.UserId; List receiveEntityList = new List(); foreach (var item in toUserIds) { MessageReceiveEntity messageReceiveEntity = new MessageReceiveEntity(); messageReceiveEntity.Id = YitIdHelper.NextId().ToString(); messageReceiveEntity.MessageId = entity.Id; messageReceiveEntity.UserId = item; messageReceiveEntity.IsRead = 0; receiveEntityList.Add(messageReceiveEntity); } await Create(entity, receiveEntityList); //消息推送 - PC端 foreach (var item in WebSocketClientCollection._clients) { if (toUserIds.Contains(item.UserId)) { await item.SendMessageAsync(new { method = "messagePush", userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1 }.Serialize()); } } //消息推送 - APP // GetuiAppPushHelper.Instance.SendNotice(userInfo.TenantId, toUserIds, "系统消息", entity.F_Title, "2"); } catch (Exception ex) { throw; } } #endregion /// /// 获取群组/房间消息列表 /// /// 分页参数 /// 房间号/群组 /// [HttpPost("GetRoomMessageList/{roomNo}")] public dynamic GetRoomMessageList( string roomNo, PageInputBase input) { var orderByType = input.sort == "asc" ? OrderByType.Asc : OrderByType.Desc; var list = _IMContentRepository.Entities.Select(it => new RoomIMContentListOutput { id = it.Id, sendUserId = it.SendUserId, sendTime = it.SendTime, content = it.Content, contentType = it.ContentType, state = it.State, roomNo = it.RoomNo }).MergeTable() .OrderBy(it => it.sendTime, orderByType) .WhereIF(!string.IsNullOrEmpty(input.keyword), it => it.content.Contains(input.keyword)) .Where(i => (i.roomNo == roomNo))//i.sendUserId == sendUserId && .ToPagedList(input.currentPage, input.pageSize); if (input.sort == "desc") { list.list = list.list.ToList().OrderBy(it => it.sendTime); } return PageResult.SqlSugarPageResult(list); } /// /// 发送消息 /// /// /// /// /// /// [HttpPost("SendRoomMessage")] public int SendRoomMessage( string roomNo, string message, string messageType, string sendUserId="") { RoomIMContentEntity entity = new RoomIMContentEntity(); entity.Id = YitIdHelper.NextId().ToString(); entity.SendUserId = _userManager.UserId; entity.SendTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); entity.RoomNo = roomNo; entity.State = 0; entity.Content = message; entity.ContentType = messageType; return _IMContentRepository.Insert(entity); } /// /// 添加房间 /// /// [HttpPost("AddRoom")] public async Task AddRoom(GroupMessageCrInput input) { if (input == null) throw NCCException.Oh("添加失败!"); //if (input.roomNo.IsNullOrEmpty()) throw NCCException.Oh("房间号必填!"); //if (_roomMessageRepository.Any(o => o.RoomNo == input.roomNo)) throw NCCException.Oh("房间已存在!"); RoomMessageEntity entity = input.Adapt(); entity.Id = YitIdHelper.NextId().ToString(); entity.IsRead = 0; entity.RoomNo = YitIdHelper.NextId().ToString(); await _roomMessageRepository.Ado.Context.Insertable(entity).CallEntityMethod(m => m.Create()).ExecuteCommandAsync(); return entity; } } }