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;
///
/// 系统消息
/// 版 本:V3.2
/// 版 权:引迈信息技术有限公司(https://www.jnpfsoft.com)
/// 作 者:JNPF开发平台组
/// 日 期:2021-06-01.
///
[ApiDescriptionSettings(Tag = "Message", Name = "message", Order = 240)]
[Route("api/[controller]")]
public class MessageService : IMessageService, IDynamicApiController, ITransient
{
private readonly ISqlSugarRepository _repository;
private readonly MessageOptions _messageOptions = App.GetConfig("Message", true);
private readonly IMHandler _imHandler;
///
/// 用户服务.
///
private readonly IUsersService _usersService;
///
/// 用户服务.
///
private readonly IUserRelationService _userRelationService;
///
/// 用户管理.
///
private readonly IUserManager _userManager;
///
/// 初始化一个类型的新实例.
///
public MessageService(
ISqlSugarRepository repository,
IUsersService usersService,
IUserRelationService userRelationService,
IUserManager userManager,
IMHandler imHandler)
{
_repository = repository;
_usersService = usersService;
_userRelationService = userRelationService;
_userManager = userManager;
_imHandler = imHandler;
}
#region Get
///
/// 列表(通知公告).
///
/// 请求参数.
///
[HttpGet("Notice")]
public async Task GetNoticeList([FromQuery] PageInputBase input)
{
var list = await _repository.AsSugarClient().Queryable((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.SqlSugarPageResult(list);
}
///
/// 列表(通知公告/系统消息/私信消息).
///
/// 请求参数.
///
[HttpGet("")]
public async Task GetMessageList([FromQuery] MessageListQueryInput input)
{
var list = await _repository.AsSugarClient().Queryable((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.SqlSugarPageResult(list);
}
///
/// 信息.
///
/// 主键值.
///
[HttpGet("{id}")]
public async Task GetInfo_Api(string id)
{
return await _repository.AsSugarClient().Queryable((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();
}
///
/// 读取消息.
///
/// 主键值.
///
[HttpGet("ReadInfo/{id}")]
public async Task ReadInfo(string id)
{
var data = await _repository.AsSugarClient().Queryable((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;
}
///
/// 读取消息.
///
/// 主键值.
///
[HttpGet("getUnReadMsgNum")]
public async Task GetUnReadMsgNum()
{
var unReadMsg = await _repository.AsSugarClient().Queryable((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((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
///
/// 删除.
///
/// 主键值.
///
[HttpDelete("{id}")]
[UnitOfWork]
public async Task Delete(string id)
{
try
{
await _repository.AsSugarClient().Deleteable().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);
}
}
///
/// 新建.
///
/// 实体对象.
///
[HttpPost("")]
public async Task Create([FromBody] MessageCrInput input)
{
var entity = input.Adapt();
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);
}
///
/// 更新.
///
/// 主键值
/// 实体对象
///
[HttpPut("{id}")]
public async Task Update(string id, [FromBody] MessageUpInput input)
{
var entity = input.Adapt();
var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
if (!isOk)
throw Oops.Oh(ErrorCode.COM1001);
}
///
/// 发布公告.
///
/// 主键值.
///
[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);
}
}
///
/// 全部已读.
///
///
[HttpPost("Actions/ReadAll")]
public async Task AllRead([FromQuery] string isRead, [FromQuery] string keyword, [FromQuery] string type)
{
await MessageRead(string.Empty, isRead, keyword, type);
}
///
/// 删除记录.
///
/// 请求参数.
///
[HttpDelete("Record")]
public async Task DeleteRecord_Api([FromBody] dynamic postParam)
{
string[] ids = postParam.ids.ToString().Split(',');
var isOk = await _repository.AsSugarClient().Deleteable().Where(m => m.UserId == _userManager.UserId && ids.Contains(m.MessageId)).ExecuteCommandHasChangeAsync();
if (!isOk)
throw Oops.Oh(ErrorCode.COM1002);
}
#endregion
#region PublicMethod
///
/// 创建.
///
/// 实体对象.
/// 收件用户.
[NonAction]
private int Create(MessageEntity entity, List receiveEntityList)
{
try
{
//modify ly on 20230803 改为CopyNew模式,否则多线程下会报错
_repository.AsSugarClient().CopyNew().Insertable(receiveEntityList).ExecuteCommand();
return _repository.AsSugarClient().CopyNew().Insertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommand();
}
catch (Exception)
{
return 0;
}
}
///
/// 更新.
///
/// 实体对象.
/// 收件用户.
[NonAction]
private int Update(MessageEntity entity, List receiveEntityList)
{
try
{
_repository.AsSugarClient().Insertable(receiveEntityList).ExecuteCommand();
return _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommand();
}
catch (Exception)
{
return 0;
}
}
///
/// 消息已读(全部).
///
/// id.
[NonAction]
private async Task MessageRead(string id, string isRead, string keyword, string type)
{
var ids = await _repository.AsSugarClient().Queryable((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().Any(x => x.IsRead == 0 && x.UserId == _userManager.UserId) && id.IsNullOrEmpty())
{
throw Oops.Oh(ErrorCode.D7017);
}
await _repository.AsSugarClient().Updateable().SetColumns(it => it.ReadCount == it.ReadCount + 1).SetColumns(x => new MessageReceiveEntity()
{
IsRead = 1,
ReadTime = DateTime.Now
}).Where(x => ids.Contains(x.MessageId)).ExecuteCommandAsync();
}
///
/// 发送公告.
///
/// 消息信息.
[NonAction]
private async Task SentNotice(MessageEntity entity)
{
try
{
var toUserIds = new List();
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 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);
}
}
///
/// 发送站内消息.
///
/// 发送用户.
/// 标题.
/// 内容.
[NonAction]
public async Task SentMessage(List toUserIds, string title, string bodyText = null, Dictionary bodyDic = null, int type = 2, string flowType = "1")
{
try
{
//modifyby zhoukeda 20230704 定时任务发起的推送消息没有user
string userManagerUserId = _userManager.UserId ?? "";
string userManagerTenantId = _userManager.TenantId ?? "";
MessageEntity entity = new MessageEntity();
entity.Id = SnowflakeIdHelper.NextId();
entity.Title = title;
entity.BodyText = bodyText;
entity.Type = type;
entity.LastModifyTime = DateTime.Now;
entity.LastModifyUserId = userManagerUserId;
entity.FlowType = flowType.ParseToInt();
List 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}", userManagerTenantId, userId), new { method = "messagePush", messageType = 2, userId = userManagerUserId, toUserId = toUserIds, title = entity.Title, unreadNoticeCount = 1, id = entity.Id }.ToJsonString());
}
}
}
catch (Exception ex)
{
throw;
}
}
///
/// 发送个推.
///
/// 推送用户.
/// 标题.
/// 内容.
/// 消息id.
/// 1:公告消息、2:流程消息、3:聊天消息.
///
private async Task GeTuiMessage(List 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().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();
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
}