485 lines
19 KiB
C#
485 lines
19 KiB
C#
using JNPF.Common.Core.Handlers;
|
||
using JNPF.Common.Core.Manager;
|
||
using JNPF.Common.Enums;
|
||
using JNPF.Common.Extension;
|
||
using JNPF.Common.Filter;
|
||
using JNPF.Common.Options;
|
||
using JNPF.Common.Security;
|
||
using JNPF.DatabaseAccessor;
|
||
using JNPF.DependencyInjection;
|
||
using JNPF.DynamicApiController;
|
||
using JNPF.FriendlyException;
|
||
using JNPF.LinqBuilder;
|
||
using JNPF.Message.Entitys;
|
||
using JNPF.Message.Entitys.Dto.Message;
|
||
using JNPF.Message.Entitys.Entity;
|
||
using JNPF.Message.Interfaces.Message;
|
||
using JNPF.RemoteRequest.Extensions;
|
||
using JNPF.Systems.Entitys.Permission;
|
||
using JNPF.Systems.Interfaces.Permission;
|
||
using Mapster;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using SqlSugar;
|
||
|
||
namespace JNPF.Message;
|
||
|
||
/// <summary>
|
||
/// 系统消息
|
||
/// 版 本:V3.2
|
||
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
|
||
/// 作 者:JNPF开发平台组
|
||
/// 日 期:2021-06-01.
|
||
/// </summary>
|
||
[ApiDescriptionSettings(Tag = "Message", Name = "message", Order = 240)]
|
||
[Route("api/[controller]")]
|
||
public class MessageService : IMessageService, IDynamicApiController, ITransient
|
||
{
|
||
private readonly ISqlSugarRepository<MessageEntity> _repository;
|
||
private readonly MessageOptions _messageOptions = App.GetConfig<MessageOptions>("Message", true);
|
||
private readonly IMHandler _imHandler;
|
||
|
||
/// <summary>
|
||
/// 用户服务.
|
||
/// </summary>
|
||
private readonly IUsersService _usersService;
|
||
|
||
/// <summary>
|
||
/// 用户服务.
|
||
/// </summary>
|
||
private readonly IUserRelationService _userRelationService;
|
||
|
||
/// <summary>
|
||
/// 用户管理.
|
||
/// </summary>
|
||
private readonly IUserManager _userManager;
|
||
|
||
/// <summary>
|
||
/// 初始化一个<see cref="MessageService"/>类型的新实例.
|
||
/// </summary>
|
||
public MessageService(
|
||
ISqlSugarRepository<MessageEntity> repository,
|
||
IUsersService usersService,
|
||
IUserRelationService userRelationService,
|
||
IUserManager userManager,
|
||
IMHandler imHandler)
|
||
{
|
||
_repository = repository;
|
||
_usersService = usersService;
|
||
_userRelationService = userRelationService;
|
||
_userManager = userManager;
|
||
_imHandler = imHandler;
|
||
}
|
||
|
||
#region Get
|
||
|
||
/// <summary>
|
||
/// 列表(通知公告).
|
||
/// </summary>
|
||
/// <param name="input">请求参数.</param>
|
||
/// <returns></returns>
|
||
[HttpGet("Notice")]
|
||
public async Task<dynamic> GetNoticeList([FromQuery] PageInputBase input)
|
||
{
|
||
var list = await _repository.AsSugarClient().Queryable<MessageEntity, UserEntity>((a, b) => new JoinQueryInfos(JoinType.Left, b.Id == a.LastModifyUserId))
|
||
.Where(a => a.Type == 1 && a.DeleteMark == null)
|
||
.WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.Title.Contains(input.keyword))
|
||
.OrderBy(a => a.EnabledMark).OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||
.Select((a, b) => new MessageNoticeOutput
|
||
{
|
||
id = a.Id,
|
||
releaseTime = a.LastModifyTime,
|
||
enabledMark = a.EnabledMark,
|
||
releaseUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
|
||
title = a.Title,
|
||
type = a.Type,
|
||
creatorTime = a.CreatorTime,
|
||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||
return PageResult<MessageNoticeOutput>.SqlSugarPageResult(list);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 列表(通知公告/系统消息/私信消息).
|
||
/// </summary>
|
||
/// <param name="input">请求参数.</param>
|
||
/// <returns></returns>
|
||
[HttpGet("")]
|
||
public async Task<dynamic> GetMessageList([FromQuery] MessageListQueryInput input)
|
||
{
|
||
var list = await _repository.AsSugarClient().Queryable<MessageEntity, MessageReceiveEntity, UserEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId, JoinType.Left, a.CreatorUserId == c.Id))
|
||
.Where((a, b) => b.UserId == _userManager.UserId && a.DeleteMark == null)
|
||
.WhereIF(input.type.IsNotEmptyOrNull(), a => a.Type == input.type)
|
||
.WhereIF(input.isRead.IsNotEmptyOrNull(), (a, b) => b.IsRead == SqlFunc.ToInt32(input.isRead))
|
||
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.Title.Contains(input.keyword))
|
||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||
.Select((a, b, c) => new MessageListOutput
|
||
{
|
||
id = a.Id,
|
||
releaseTime = a.LastModifyTime,
|
||
releaseUser = SqlFunc.MergeString(c.RealName, "/", c.Account),
|
||
title = a.Title,
|
||
type = a.Type,
|
||
isRead = b.IsRead,
|
||
flowType=a.FlowType
|
||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||
return PageResult<MessageListOutput>.SqlSugarPageResult(list);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 信息.
|
||
/// </summary>
|
||
/// <param name="id">主键值.</param>
|
||
/// <returns></returns>
|
||
[HttpGet("{id}")]
|
||
public async Task<dynamic> GetInfo_Api(string id)
|
||
{
|
||
return await _repository.AsSugarClient().Queryable<MessageEntity, UserEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id))
|
||
.Where(a => a.Id == id && a.DeleteMark == null)
|
||
.Select((a, b) => new MessageInfoOutput
|
||
{
|
||
id = a.Id,
|
||
releaseTime = a.LastModifyTime,
|
||
releaseUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
|
||
title = a.Title,
|
||
bodyText = a.BodyText,
|
||
files = a.Files,
|
||
toUserIds = a.ToUserIds,
|
||
}).FirstAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取消息.
|
||
/// </summary>
|
||
/// <param name="id">主键值.</param>
|
||
/// <returns></returns>
|
||
[HttpGet("ReadInfo/{id}")]
|
||
public async Task<dynamic> ReadInfo(string id)
|
||
{
|
||
var data = await _repository.AsSugarClient().Queryable<MessageEntity, UserEntity, MessageReceiveEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id, JoinType.Left, a.Id == c.MessageId))
|
||
.Where((a, b, c) => a.Id == id && a.DeleteMark == null && c.UserId == _userManager.UserId)
|
||
.OrderBy(a => a.LastModifyTime)
|
||
.Select((a, b, c) => new MessageReadInfoOutput
|
||
{
|
||
id = a.Id,
|
||
releaseTime = a.LastModifyTime,
|
||
releaseUser = SqlFunc.MergeString(b.RealName, "/", b.Account),
|
||
title = a.Title,
|
||
bodyText = c.BodyText,
|
||
files = a.Files
|
||
}).FirstAsync();
|
||
if (data != null)
|
||
await MessageRead(id, null, null, null);
|
||
return data;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 读取消息.
|
||
/// </summary>
|
||
/// <param name="id">主键值.</param>
|
||
/// <returns></returns>
|
||
[HttpGet("getUnReadMsgNum")]
|
||
public async Task<dynamic> GetUnReadMsgNum()
|
||
{
|
||
var unReadMsg = await _repository.AsSugarClient().Queryable<MessageEntity, MessageReceiveEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId)).Where((a, b) => a.Type == 2 && b.UserId == _userManager.UserId && b.IsRead == 0).CountAsync();
|
||
var unReadNotice = await _repository.AsSugarClient().Queryable<MessageEntity, MessageReceiveEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId)).Where((a, b) => a.Type == 1 && b.UserId == _userManager.UserId && b.IsRead == 0).CountAsync();
|
||
return new { unReadMsg = unReadMsg, unReadNotice = unReadNotice, unReadNum = unReadMsg + unReadNotice };
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Post
|
||
|
||
/// <summary>
|
||
/// 删除.
|
||
/// </summary>
|
||
/// <param name="id">主键值.</param>
|
||
/// <returns></returns>
|
||
[HttpDelete("{id}")]
|
||
[UnitOfWork]
|
||
public async Task Delete(string id)
|
||
{
|
||
try
|
||
{
|
||
await _repository.AsSugarClient().Deleteable<MessageReceiveEntity>().Where(x => x.MessageId == id).ExecuteCommandAsync();
|
||
await _repository.AsUpdateable().SetColumns(it => new MessageEntity()
|
||
{
|
||
DeleteMark = 1,
|
||
DeleteUserId = _userManager.UserId,
|
||
DeleteTime = SqlFunc.GetDate()
|
||
}).Where(it => it.Id.Equals(id)).ExecuteCommandAsync();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
throw Oops.Oh(ErrorCode.COM1002);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 新建.
|
||
/// </summary>
|
||
/// <param name="input">实体对象.</param>
|
||
/// <returns></returns>
|
||
[HttpPost("")]
|
||
public async Task Create([FromBody] MessageCrInput input)
|
||
{
|
||
var entity = input.Adapt<MessageEntity>();
|
||
entity.Type = 1;
|
||
entity.EnabledMark = 0;
|
||
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||
if (isOk < 1)
|
||
throw Oops.Oh(ErrorCode.COM1000);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新.
|
||
/// </summary>
|
||
/// <param name="id">主键值</param>
|
||
/// <param name="input">实体对象</param>
|
||
/// <returns></returns>
|
||
[HttpPut("{id}")]
|
||
public async Task Update(string id, [FromBody] MessageUpInput input)
|
||
{
|
||
var entity = input.Adapt<MessageEntity>();
|
||
var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
|
||
if (!isOk)
|
||
throw Oops.Oh(ErrorCode.COM1001);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布公告.
|
||
/// </summary>
|
||
/// <param name="id">主键值.</param>
|
||
/// <returns></returns>
|
||
[HttpPut("{id}/Actions/Release")]
|
||
public async Task Release(string id)
|
||
{
|
||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||
if (entity != null)
|
||
{
|
||
// 发送
|
||
await SentNotice(entity);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 全部已读.
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
[HttpPost("Actions/ReadAll")]
|
||
public async Task AllRead([FromQuery] string isRead, [FromQuery] string keyword, [FromQuery] string type)
|
||
{
|
||
await MessageRead(string.Empty, isRead, keyword, type);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除记录.
|
||
/// </summary>
|
||
/// <param name="postParam">请求参数.</param>
|
||
/// <returns></returns>
|
||
[HttpDelete("Record")]
|
||
public async Task DeleteRecord_Api([FromBody] dynamic postParam)
|
||
{
|
||
string[] ids = postParam.ids.ToString().Split(',');
|
||
var isOk = await _repository.AsSugarClient().Deleteable<MessageReceiveEntity>().Where(m => m.UserId == _userManager.UserId && ids.Contains(m.MessageId)).ExecuteCommandHasChangeAsync();
|
||
if (!isOk)
|
||
throw Oops.Oh(ErrorCode.COM1002);
|
||
}
|
||
#endregion
|
||
|
||
#region PublicMethod
|
||
|
||
/// <summary>
|
||
/// 创建.
|
||
/// </summary>
|
||
/// <param name="entity">实体对象.</param>
|
||
/// <param name="receiveEntityList">收件用户.</param>
|
||
[NonAction]
|
||
private int Create(MessageEntity entity, List<MessageReceiveEntity> receiveEntityList)
|
||
{
|
||
try
|
||
{
|
||
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
|
||
|
||
return _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommand();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新.
|
||
/// </summary>
|
||
/// <param name="entity">实体对象.</param>
|
||
/// <param name="receiveEntityList">收件用户.</param>
|
||
[NonAction]
|
||
private int Update(MessageEntity entity, List<MessageReceiveEntity> receiveEntityList)
|
||
{
|
||
try
|
||
{
|
||
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
|
||
return _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommand();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 消息已读(全部).
|
||
/// </summary>
|
||
/// <param name="id">id.</param>
|
||
[NonAction]
|
||
private async Task MessageRead(string id, string isRead, string keyword, string type)
|
||
{
|
||
var ids = await _repository.AsSugarClient().Queryable<MessageEntity, MessageReceiveEntity, UserEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.Id == b.MessageId, JoinType.Left, a.CreatorUserId == c.Id))
|
||
.Where((a, b) => b.UserId == _userManager.UserId && a.DeleteMark == null)
|
||
.WhereIF(id.IsNotEmptyOrNull(), a => a.Id == id)
|
||
.WhereIF(type.IsNotEmptyOrNull(), a => a.Type == SqlFunc.ToInt32(type))
|
||
.WhereIF(!string.IsNullOrEmpty(isRead), a => a.IsRead == SqlFunc.ToInt32(isRead))
|
||
.WhereIF(!string.IsNullOrEmpty(keyword), a => a.Title.Contains(keyword))
|
||
.Select((a, b, c) => a.Id).ToListAsync();
|
||
if (!_repository.AsSugarClient().Queryable<MessageReceiveEntity>().Any(x => x.IsRead == 0 && x.UserId == _userManager.UserId) && id.IsNullOrEmpty())
|
||
{
|
||
throw Oops.Oh(ErrorCode.D7017);
|
||
}
|
||
await _repository.AsSugarClient().Updateable<MessageReceiveEntity>().SetColumns(it => it.ReadCount == it.ReadCount + 1).SetColumns(x => new MessageReceiveEntity()
|
||
{
|
||
IsRead = 1,
|
||
ReadTime = DateTime.Now
|
||
}).Where(x => ids.Contains(x.MessageId)).ExecuteCommandAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送公告.
|
||
/// </summary>
|
||
/// <param name="entity">消息信息.</param>
|
||
[NonAction]
|
||
private async Task SentNotice(MessageEntity entity)
|
||
{
|
||
try
|
||
{
|
||
var toUserIds = new List<string>();
|
||
entity.EnabledMark = 1;
|
||
if (entity.ToUserIds.IsNullOrEmpty())
|
||
toUserIds = (await _usersService.GetList()).Select(x => x.Id).ToList();
|
||
else
|
||
toUserIds = await _userRelationService.GetUserId(entity.ToUserIds.Split(",").ToList());
|
||
List<MessageReceiveEntity> receiveEntityList = toUserIds
|
||
.Select(x => new MessageReceiveEntity()
|
||
{
|
||
Id = SnowflakeIdHelper.NextId(),
|
||
MessageId = entity.Id,
|
||
UserId = x,
|
||
IsRead = 0,
|
||
BodyText = entity.BodyText,
|
||
}).ToList();
|
||
|
||
Update(entity, receiveEntityList);
|
||
if (entity.ToUserIds.IsNullOrEmpty())
|
||
{
|
||
await _imHandler.SendMessageToTenantAsync(_userManager.TenantId, new { method = "messagePush", messageType = 1, userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
|
||
}
|
||
else
|
||
{
|
||
foreach (var item in toUserIds)
|
||
{
|
||
var userId = item.Replace("-delegate", string.Empty);
|
||
// 消息推送 - 指定用户
|
||
await _imHandler.SendMessageToUserAsync(string.Format("{0}-{1}", _userManager.TenantId, userId), new { method = "messagePush", messageType = 2, userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
|
||
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw Oops.Oh(ErrorCode.D7003);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送站内消息.
|
||
/// </summary>
|
||
/// <param name="toUserIds">发送用户.</param>
|
||
/// <param name="title">标题.</param>
|
||
/// <param name="bodyText">内容.</param>
|
||
[NonAction]
|
||
public async Task SentMessage(List<string> toUserIds, string title, string bodyText = null, Dictionary<string, object> bodyDic = null, int type = 2, string flowType = "1")
|
||
{
|
||
try
|
||
{
|
||
MessageEntity entity = new MessageEntity();
|
||
entity.Id = SnowflakeIdHelper.NextId();
|
||
entity.Title = title;
|
||
entity.BodyText = bodyText;
|
||
entity.Type = type;
|
||
entity.LastModifyTime = DateTime.Now;
|
||
entity.LastModifyUserId = _userManager.UserId;
|
||
entity.FlowType = flowType.ParseToInt();
|
||
List<MessageReceiveEntity> receiveEntityList = toUserIds
|
||
.Select(x => new MessageReceiveEntity()
|
||
{
|
||
Id = SnowflakeIdHelper.NextId(),
|
||
MessageId = entity.Id,
|
||
UserId = x.Replace("-delegate", string.Empty),
|
||
IsRead = 0,
|
||
BodyText = bodyDic.IsNotEmptyOrNull() && bodyDic.ContainsKey(x) ? bodyDic[x].ToJsonString() : null,
|
||
}).ToList();
|
||
|
||
if (Create(entity, receiveEntityList) >= 1)
|
||
{
|
||
foreach (var item in toUserIds)
|
||
{
|
||
var userId = item.Replace("-delegate", string.Empty);
|
||
// 消息推送 - 指定用户
|
||
await _imHandler.SendMessageToUserAsync(string.Format("{0}-{1}", _userManager.TenantId, userId), new { method = "messagePush", messageType = 2, userId = _userManager.UserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送个推.
|
||
/// </summary>
|
||
/// <param name="toUserIds">推送用户.</param>
|
||
/// <param name="title">标题.</param>
|
||
/// <param name="content">内容.</param>
|
||
/// <param name="msgId">消息id.</param>
|
||
/// <param name="type">1:公告消息、2:流程消息、3:聊天消息.</param>
|
||
/// <returns></returns>
|
||
private async Task GeTuiMessage(List<string> toUserIds, string title, string content, string msgId, string type)
|
||
{
|
||
var getuiUrl = "{0}?clientId={1}&title={2}&content={3}1&text={4}&create=true";
|
||
if (toUserIds.Any())
|
||
{
|
||
var clientIdList = await _repository.AsSugarClient().Queryable<UserDeviceEntity>().Where(x => toUserIds.Contains(x.UserId) && x.DeleteMark == null).Select(x => x.ClientId).ToListAsync();
|
||
if (clientIdList.Any())
|
||
{
|
||
var clientId = string.Join(",", clientIdList);
|
||
var textDic = new Dictionary<string, string>();
|
||
textDic.Add("type", type);
|
||
if (type == "3")
|
||
{
|
||
var userName = await _usersService.GetUserName(_userManager.UserId);
|
||
textDic.Add("name", userName);
|
||
textDic.Add("formUserId", _userManager.UserId);
|
||
textDic.Add("headIcon", "/api/File/Image/userAvatar/" + _userManager.User.HeadIcon);
|
||
}
|
||
else
|
||
{
|
||
textDic.Add("id", msgId);
|
||
textDic.Add("title", title);
|
||
}
|
||
getuiUrl = string.Format(getuiUrl, _messageOptions.AppPushUrl, clientId, title, content, textDic.ToJsonString());
|
||
await getuiUrl.GetAsStringAsync();
|
||
}
|
||
}
|
||
}
|
||
#endregion
|
||
} |