添加项目文件。
This commit is contained in:
146
message/Tnb.Message/Service/ImReplyService.cs
Normal file
146
message/Tnb.Message/Service/ImReplyService.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using JNPF.Common.Core.Manager;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.Message.Entitys;
|
||||
using JNPF.Message.Entitys.Dto.ImReply;
|
||||
using JNPF.Message.Handlers;
|
||||
using JNPF.Message.Interfaces;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message;
|
||||
|
||||
/// <summary>
|
||||
/// 业务实现:消息会话.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "imreply", Order = 163)]
|
||||
[Route("api/message/[controller]")]
|
||||
public class ImReplyService : IImReplyService, IDynamicApiController, ITransient
|
||||
{
|
||||
/// <summary>
|
||||
/// 服务基础仓储.
|
||||
/// </summary>
|
||||
private readonly ISqlSugarRepository<ImReplyEntity> _repository;
|
||||
|
||||
/// <summary>
|
||||
/// 用户管理.
|
||||
/// </summary>
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
/// <summary>
|
||||
/// IM中心处理程序.
|
||||
/// </summary>
|
||||
private IMHandler _imHandler;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化一个<see cref="ImReplyService"/>类型的新实例.
|
||||
/// </summary>
|
||||
public ImReplyService(
|
||||
ISqlSugarRepository<ImReplyEntity> repository,
|
||||
IUserManager userManager,
|
||||
IMHandler imHandler)
|
||||
{
|
||||
_repository = repository;
|
||||
_userManager = userManager;
|
||||
_imHandler = imHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取消息会话列表.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public async Task<dynamic> GetList()
|
||||
{
|
||||
var newObjectUserList = new List<ImReplyListOutput>();
|
||||
|
||||
// 获取全部聊天对象列表
|
||||
var objectList = _repository.AsSugarClient().UnionAll(
|
||||
_repository.AsQueryable().Where(i => i.ReceiveUserId == _userManager.UserId && (SqlFunc.IsNullOrEmpty(i.ImreplySendDeleteMark)||i.ImreplySendDeleteMark != _userManager.UserId)).Select(it => new ImReplyObjectIdOutput { userId = it.UserId, latestDate = it.ReceiveTime }),
|
||||
_repository.AsQueryable().Where(i => i.UserId == _userManager.UserId && (SqlFunc.IsNullOrEmpty(i.ImreplySendDeleteMark) || i.ImreplySendDeleteMark != _userManager.UserId)).Select(it => new ImReplyObjectIdOutput { userId = it.ReceiveUserId, latestDate = it.ReceiveTime })).MergeTable().GroupBy(it => new { it.userId }).Select(it => new { it.userId, latestDate = SqlFunc.AggregateMax(it.latestDate) }).ToList();
|
||||
var objectUserList = objectList.Adapt<List<ImReplyListOutput>>();
|
||||
if (objectUserList.Count > 0)
|
||||
{
|
||||
var userList = await _repository.AsSugarClient().Queryable<UserEntity>().In(it => it.Id, objectUserList.Select(it => it.userId).ToArray()).ToListAsync();
|
||||
|
||||
// 将用户信息补齐
|
||||
userList.ForEach(item =>
|
||||
{
|
||||
objectUserList.ForEach(it =>
|
||||
{
|
||||
if (it.userId == item.Id)
|
||||
{
|
||||
it.account = item.Account;
|
||||
it.id = it.userId;
|
||||
it.realName = item.RealName;
|
||||
it.headIcon = "/api/File/Image/userAvatar/" + item.HeadIcon;
|
||||
|
||||
var imContent = _repository.AsSugarClient().Queryable<IMContentEntity>().Where(i => (i.SendUserId == _userManager.UserId && i.ReceiveUserId == it.userId) || (i.SendUserId == it.userId && i.ReceiveUserId == _userManager.UserId)).Where(i => i.SendTime.Equals(it.latestDate) && (SqlFunc.IsNullOrEmpty(i.SendDeleteMark)|| i.SendDeleteMark != _userManager.UserId)).ToList().FirstOrDefault();
|
||||
|
||||
// 获取最信息
|
||||
if (imContent != null)
|
||||
{
|
||||
it.latestMessage = imContent.Content;
|
||||
it.messageType = imContent.ContentType;
|
||||
}
|
||||
|
||||
it.unreadMessage = _repository.AsSugarClient().Queryable<IMContentEntity>().Where(i => i.SendUserId == it.userId && i.ReceiveUserId == _userManager.UserId).Where(i => i.State == 0 && (SqlFunc.IsNullOrEmpty(i.SendDeleteMark) || i.SendDeleteMark != _userManager.UserId)).Count();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return new { list = objectUserList.OrderByDescending(x => x.latestDate).ToList() };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除聊天会话.
|
||||
/// </summary>
|
||||
/// <param name="id">聊天人员UserId</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("relocation/{id}")]
|
||||
public async Task DelMsgSession(string id)
|
||||
{
|
||||
var list = _repository.AsQueryable().Where(i => (i.UserId == _userManager.UserId && i.ReceiveUserId == id) || (i.UserId == id && i.ReceiveUserId == _userManager.UserId)).ToList();
|
||||
if (list.Any(x => x.ImreplySendDeleteMark == id))
|
||||
{
|
||||
await _repository.AsSugarClient().Deleteable(list).ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _repository.AsSugarClient().Updateable(list).ReSetValue(it => { it.ImreplySendDeleteMark = _userManager.UserId; }).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除聊天记录.
|
||||
/// </summary>
|
||||
/// <param name="id">聊天人员UserId</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("deleteChatRecord/{id}")]
|
||||
public async Task DelMsgContent(string id)
|
||||
{
|
||||
var list = _repository.AsSugarClient().Queryable<IMContentEntity>().Where(i => (i.SendUserId == _userManager.UserId && i.ReceiveUserId == id) || (i.SendUserId == id && i.ReceiveUserId == _userManager.UserId)).ToList();
|
||||
if (list.Any(x => x.SendDeleteMark == id))
|
||||
{
|
||||
await _repository.AsSugarClient().Deleteable(list).ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _repository.AsSugarClient().Updateable(list).ReSetValue(it => { it.SendDeleteMark = _userManager.UserId; }).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制下线.
|
||||
/// </summary>
|
||||
/// <param name="connectionId"></param>
|
||||
[NonAction]
|
||||
public async void ForcedOffline(string connectionId)
|
||||
{
|
||||
await _imHandler.SendMessageAsync(connectionId, new { method = "logout", msg = "此账号已在其他地方登陆" }.ToJsonString());
|
||||
}
|
||||
}
|
||||
232
message/Tnb.Message/Service/MessageAccountService.cs
Normal file
232
message/Tnb.Message/Service/MessageAccountService.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System.Web;
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Filter;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.Extras.Thirdparty.DingDing;
|
||||
using JNPF.Extras.Thirdparty.Email;
|
||||
using JNPF.Extras.Thirdparty.WeChat;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Message.Entitys.Dto.MessageAccount;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 消息账号
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "AccountConfig", Order = 240)]
|
||||
[Route("api/message/AccountConfig")]
|
||||
public class MessageAccountService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageAccountEntity> _repository;
|
||||
|
||||
public MessageAccountService(ISqlSugarRepository<MessageAccountEntity> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 列表.
|
||||
/// </summary>
|
||||
/// <param name="input">请求参数.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public async Task<dynamic> GetList([FromQuery] MessageAccountQuery input)
|
||||
{
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageAccountEntity>()
|
||||
.Where(a => a.Type == input.type && a.DeleteMark == null)
|
||||
.WhereIF(input.enabledMark.IsNotEmptyOrNull(), a => a.EnabledMark == input.enabledMark)
|
||||
.WhereIF(input.channel.IsNotEmptyOrNull(), a => a.Channel == input.channel)
|
||||
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword) ||
|
||||
a.AddressorName.Contains(input.keyword) || a.SmtpUser.Contains(input.keyword) ||
|
||||
a.SmsSignature.Contains(input.keyword))
|
||||
.OrderBy(a => a.SortCode)
|
||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||||
.Select(a => new MessageAccountListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
enCode = a.EnCode,
|
||||
fullName = a.FullName,
|
||||
type = a.Type,
|
||||
creatorUser = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)),
|
||||
creatorTime = a.CreatorTime,
|
||||
lastModifyTime = a.LastModifyTime,
|
||||
sortCode = a.SortCode,
|
||||
enabledMark = a.EnabledMark,
|
||||
smsSignature = a.SmsSignature,
|
||||
channel = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "2" && u.EnCode == a.Channel).Select(u => u.FullName),
|
||||
addressorName = a.AddressorName,
|
||||
smtpUser = a.SmtpUser,
|
||||
webhookType = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "3" && u.EnCode == a.WebhookType).Select(u => u.FullName),
|
||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||
return PageResult<MessageAccountListOutput>.SqlSugarPageResult(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<dynamic> GetInfo(string id)
|
||||
{
|
||||
return (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<MessageAccountListOutput>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Post
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("")]
|
||||
public async Task Create([FromBody] MessageAccountListOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
var entity = input.Adapt<MessageAccountEntity>();
|
||||
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] MessageAccountListOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
if ((await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().AnyAsync(x => x.AccountConfigId == id && x.DeleteMark == null)) && input.enabledMark == 0)
|
||||
throw Oops.Oh(ErrorCode.D7013);
|
||||
var entity = input.Adapt<MessageAccountEntity>();
|
||||
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>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task Delete(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
if (entity == null)
|
||||
throw Oops.Oh(ErrorCode.COM1005);
|
||||
if (await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().AnyAsync(x => x.AccountConfigId == id && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.D7012);
|
||||
var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
|
||||
if (!isOk)
|
||||
throw Oops.Oh(ErrorCode.COM1002);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制.
|
||||
/// </summary>
|
||||
/// <param name="id">主键值.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("copy/{id}")]
|
||||
public async Task ActionsCopy(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower();
|
||||
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
||||
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
||||
entity.EnabledMark = 0;
|
||||
if (entity.Type == "7")
|
||||
{
|
||||
entity.AppKey = string.Format("{0}{1}", entity.AppKey, random);
|
||||
}
|
||||
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
||||
throw Oops.Oh(ErrorCode.COM1009);
|
||||
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
if (isOk < 1)
|
||||
throw Oops.Oh(ErrorCode.COM1008);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 钉钉链接测试.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
[HttpPost("testDingTalkConnect")]
|
||||
public void testDingTalkConnect([FromBody] MessageAccountListOutput input)
|
||||
{
|
||||
var dingUtil = new DingUtil(input.appId, input.appSecret);
|
||||
if (string.IsNullOrEmpty(dingUtil.token))
|
||||
throw Oops.Oh(ErrorCode.D9003);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱链接测试.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
[HttpPost("testSendMail")]
|
||||
public async Task EmailTest([FromBody] EmailSendTestQuery input)
|
||||
{
|
||||
MailParameterInfo mailParameterInfo = new MailParameterInfo()
|
||||
{
|
||||
SMTPHost = input.smtpServer,
|
||||
SMTPPort = input.smtpPort.ParseToInt(),
|
||||
Account = input.smtpUser,
|
||||
Password = input.smtpPassword,
|
||||
Ssl = input.sslLink.Equals("1")
|
||||
};
|
||||
var result = MailUtil.CheckConnected(mailParameterInfo);
|
||||
if (!result)
|
||||
throw Oops.Oh(ErrorCode.D7006);
|
||||
var emailList = new List<string>();
|
||||
foreach (var item in input.testSendEmail)
|
||||
{
|
||||
var receiverUser = await _repository.AsSugarClient().Queryable<UserEntity>().FirstAsync(x => x.Id == item && x.DeleteMark == null);
|
||||
if (receiverUser.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.COM1005);
|
||||
if (receiverUser.Email.IsNullOrEmpty()) throw Oops.Oh(ErrorCode.D7007, receiverUser.RealName);
|
||||
if (!receiverUser.Email.IsEmail()) throw Oops.Oh(ErrorCode.D7008, receiverUser.RealName);
|
||||
var mailModel = new MailInfo();
|
||||
mailModel.To = receiverUser.Email;
|
||||
mailModel.Subject = input.testEmailTitle;
|
||||
mailModel.BodyText = HttpUtility.HtmlDecode(input.testEmailContent);
|
||||
try
|
||||
{
|
||||
MailUtil.Send(mailParameterInfo, mailModel);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw Oops.Oh(ErrorCode.D7014, receiverUser.RealName, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 企业微信链接测试.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="input"></param>
|
||||
[HttpPost("testQyWebChatConnect")]
|
||||
public void testQyWebChatConnect([FromBody] MessageAccountListOutput input)
|
||||
{
|
||||
var weChatUtil = new WeChatUtil(input.enterpriseId, input.appSecret);
|
||||
if (string.IsNullOrEmpty(weChatUtil.accessToken))
|
||||
throw Oops.Oh(ErrorCode.D9003);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
46
message/Tnb.Message/Service/MessageDataTypeService.cs
Normal file
46
message/Tnb.Message/Service/MessageDataTypeService.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Filter;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Message.Entitys.Dto.MessageAccount;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 消息账号
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "MessageDataType", Order = 240)]
|
||||
[Route("api/message/[controller]")]
|
||||
public class MessageDataTypeService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageDataTypeEntity> _repository;
|
||||
|
||||
public MessageDataTypeService(ISqlSugarRepository<MessageDataTypeEntity> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 下拉列表.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("getTypeList/{type}")]
|
||||
public async Task<dynamic> GetTypeList(string type)
|
||||
{
|
||||
return (await _repository.GetListAsync(x => x.Type == type && x.DeleteMark == null)).Select(x => new { id = x.Id, fullName = x.FullName ,enCode=x.EnCode}).ToList();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
123
message/Tnb.Message/Service/MessageMonitorService.cs
Normal file
123
message/Tnb.Message/Service/MessageMonitorService.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Filter;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.LinqBuilder;
|
||||
using JNPF.Message.Entitys.Dto.MessageMonitor;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using JNPF.Systems.Interfaces.Permission;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 消息监控
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "MessageMonitor", Order = 240)]
|
||||
[Route("api/message/[controller]")]
|
||||
public class MessageMonitorService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageMonitorEntity> _repository;
|
||||
private readonly IUsersService _usersService;
|
||||
|
||||
public MessageMonitorService(
|
||||
ISqlSugarRepository<MessageMonitorEntity> repository,
|
||||
IUsersService usersService)
|
||||
{
|
||||
_repository = repository;
|
||||
_usersService = usersService;
|
||||
}
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 列表.
|
||||
/// </summary>
|
||||
/// <param name="input">请求参数.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public async Task<dynamic> GetList([FromQuery] MessageMonitorQuery input)
|
||||
{
|
||||
var whereLambda = LinqExpression.And<MessageMonitorEntity>();
|
||||
whereLambda = whereLambda.And(a => a.DeleteMark == null);
|
||||
var start = new DateTime();
|
||||
var end = new DateTime();
|
||||
if (input.endTime != null && input.startTime != null)
|
||||
{
|
||||
start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime()));
|
||||
end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime()));
|
||||
whereLambda = whereLambda.And(a => SqlFunc.Between(a.SendTime, start, end));
|
||||
}
|
||||
// 关键字(用户、IP地址、功能名称)
|
||||
if (!string.IsNullOrEmpty(input.keyword))
|
||||
whereLambda = whereLambda.And(a => a.Title.Contains(input.keyword));
|
||||
if (input.messageSource.IsNotEmptyOrNull())
|
||||
whereLambda = whereLambda.And(a => a.MessageSource.Contains(input.messageSource));
|
||||
if (input.messageType.IsNotEmptyOrNull())
|
||||
whereLambda = whereLambda.And(m => m.MessageType.Contains(input.messageType));
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageMonitorEntity>()
|
||||
.Where(whereLambda)
|
||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||||
.Select(a => new MessageMonitorListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
messageType = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "1" && u.EnCode == a.MessageType).Select(u => u.FullName),
|
||||
messageSource = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "4" && u.EnCode == a.MessageSource).Select(u => u.FullName),
|
||||
title = a.Title,
|
||||
sendTime = a.SendTime,
|
||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||
return PageResult<MessageMonitorListOutput>.SqlSugarPageResult(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("detail/{id}")]
|
||||
public async Task<dynamic> GetInfo(string id)
|
||||
{
|
||||
return await _repository.AsSugarClient().Queryable<MessageMonitorEntity>().Where(a => a.Id == id && a.DeleteMark == null).Select(a => new MessageMonitorListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
messageType = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "1" && u.EnCode == a.MessageType).Select(u => u.FullName),
|
||||
messageSource = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "4" && u.EnCode == a.MessageSource).Select(u => u.FullName),
|
||||
title = a.Title,
|
||||
sendTime = a.SendTime,
|
||||
receiveUser = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == SqlFunc.ToString(a.ReceiveUser)).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)),
|
||||
content = a.Content
|
||||
}).FirstAsync();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region POST
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除.
|
||||
/// </summary>
|
||||
/// <param name="input">请求参数.</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("batchRemove")]
|
||||
public async Task Delete([FromBody] MessageMonitorDelInput input)
|
||||
{
|
||||
await _repository.AsDeleteable().In(it => it.Id, input.ids).ExecuteCommandAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 一键删除.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("empty")]
|
||||
public async Task Delete()
|
||||
{
|
||||
await _repository.DeleteAsync(x => x.DeleteMark == null);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
482
message/Tnb.Message/Service/MessageService.cs
Normal file
482
message/Tnb.Message/Service/MessageService.cs
Normal file
@@ -0,0 +1,482 @@
|
||||
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.Handlers;
|
||||
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
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期: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
|
||||
}).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).ExecuteCommandAsync();
|
||||
|
||||
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).ExecuteCommandAsync();
|
||||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageEntity entity = new MessageEntity();
|
||||
entity.Id = SnowflakeIdHelper.NextId();
|
||||
entity.Title = title;
|
||||
entity.BodyText = bodyText;
|
||||
entity.Type = 2;
|
||||
entity.LastModifyTime = DateTime.Now;
|
||||
entity.LastModifyUserId = _userManager.UserId;
|
||||
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, item), 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
|
||||
}
|
||||
220
message/Tnb.Message/Service/MessageTemplateService.cs
Normal file
220
message/Tnb.Message/Service/MessageTemplateService.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Filter;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Message.Entitys.Dto.MessageTemplate;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Message.Entitys.Model.MessageTemplate;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 消息监控
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "MessageTemplate", Order = 240)]
|
||||
[Route("api/message/MessageTemplateConfig")]
|
||||
public class MessageTemplateService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageTemplateEntity> _repository;
|
||||
|
||||
public MessageTemplateService(
|
||||
ISqlSugarRepository<MessageTemplateEntity> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// 列表.
|
||||
/// </summary>
|
||||
/// <param name="input">请求参数.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public async Task<dynamic> GetList([FromQuery] MessageTemplateQuery input)
|
||||
{
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageTemplateEntity>()
|
||||
.Where(a => a.DeleteMark == null)
|
||||
.WhereIF(input.messageSource.IsNotEmptyOrNull(), a => a.MessageSource == input.messageSource)
|
||||
.WhereIF(input.messageType.IsNotEmptyOrNull(), a => a.MessageType == input.messageType)
|
||||
.WhereIF(input.templateType.IsNotEmptyOrNull(), a => a.TemplateType == input.templateType)
|
||||
.WhereIF(input.enabledMark.IsNotEmptyOrNull(), a => a.EnabledMark == input.enabledMark)
|
||||
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
|
||||
.OrderBy(a => a.SortCode)
|
||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||||
.Select(a => new MessageTemplateListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
fullName = a.FullName,
|
||||
enCode = a.EnCode,
|
||||
templateType = a.TemplateType,
|
||||
messageType = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "1" && u.EnCode == a.MessageType).Select(u => u.FullName),
|
||||
messageSource = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "4" && u.EnCode == a.MessageSource).Select(u => u.FullName),
|
||||
creatorUser = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)),
|
||||
creatorTime = a.CreatorTime,
|
||||
lastModifyTime = a.LastModifyTime,
|
||||
sortCode = a.SortCode,
|
||||
enabledMark = a.EnabledMark,
|
||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||
return PageResult<MessageTemplateListOutput>.SqlSugarPageResult(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<dynamic> GetInfo(string id)
|
||||
{
|
||||
var output = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<MessageTemplateListOutput>();
|
||||
output.smsFieldList = (await _repository.AsSugarClient().Queryable<MessageSmsFieldEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync()).ToObject<List<SmsFieldModel>>();
|
||||
output.templateParamList = (await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync()).ToObject<List<TemplateParamModel>>();
|
||||
return output;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region POST
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("")]
|
||||
public async Task Create([FromBody] MessageTemplateListOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
if (input.enCode.Contains("MBXTLC"))
|
||||
throw Oops.Oh(ErrorCode.D7011);
|
||||
var entity = input.Adapt<MessageTemplateEntity>();
|
||||
var result = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
|
||||
if (input.templateParamList.Any())
|
||||
{
|
||||
foreach (var item in input.templateParamList)
|
||||
{
|
||||
var paramEntity = item.Adapt<MessageTemplateParamEntity>();
|
||||
paramEntity.TemplateId = result.Id;
|
||||
await _repository.AsSugarClient().Insertable(paramEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
if (input.smsFieldList.Any())
|
||||
{
|
||||
foreach (var item in input.smsFieldList)
|
||||
{
|
||||
var smsFieldEntity = item.Adapt<MessageSmsFieldEntity>();
|
||||
smsFieldEntity.TemplateId = result.Id;
|
||||
await _repository.AsSugarClient().Insertable(smsFieldEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
if (result.IsNullOrEmpty())
|
||||
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] MessageTemplateListOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
if (input.enCode.Contains("MBXTLC"))
|
||||
throw Oops.Oh(ErrorCode.D7011);
|
||||
var entity = input.Adapt<MessageTemplateEntity>();
|
||||
if (input.templateParamList.Any())
|
||||
{
|
||||
await _repository.AsSugarClient().Deleteable<MessageTemplateParamEntity>(x => x.TemplateId == id).ExecuteCommandAsync();
|
||||
foreach (var item in input.templateParamList)
|
||||
{
|
||||
var paramEntity = item.Adapt<MessageTemplateParamEntity>();
|
||||
paramEntity.TemplateId = id;
|
||||
await _repository.AsSugarClient().Insertable(paramEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
if (input.smsFieldList.Any())
|
||||
{
|
||||
await _repository.AsSugarClient().Deleteable<MessageSmsFieldEntity>(x => x.TemplateId == id).ExecuteCommandAsync();
|
||||
foreach (var item in input.smsFieldList)
|
||||
{
|
||||
var smsFieldEntity = item.Adapt<MessageSmsFieldEntity>();
|
||||
smsFieldEntity.TemplateId = id;
|
||||
await _repository.AsSugarClient().Insertable(smsFieldEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
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>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task Delete(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
if (entity == null)
|
||||
throw Oops.Oh(ErrorCode.COM1005);
|
||||
await _repository.AsSugarClient().Deleteable<MessageTemplateParamEntity>(x => x.TemplateId == id).ExecuteCommandAsync();
|
||||
await _repository.AsSugarClient().Deleteable<MessageSmsFieldEntity>(x => x.TemplateId == id).ExecuteCommandAsync();
|
||||
var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
|
||||
if (!isOk)
|
||||
throw Oops.Oh(ErrorCode.COM1002);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制.
|
||||
/// </summary>
|
||||
/// <param name="id">主键值.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("copy/{id}")]
|
||||
public async Task ActionsCopy(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower();
|
||||
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
||||
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
||||
entity.Id = SnowflakeIdHelper.NextId();
|
||||
entity.EnabledMark = 0;
|
||||
entity.TemplateType = "0";
|
||||
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
||||
throw Oops.Oh(ErrorCode.COM1009);
|
||||
var templateParamList = await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync();
|
||||
foreach (var item in templateParamList)
|
||||
{
|
||||
var paramEntity = item.Adapt<MessageTemplateParamEntity>();
|
||||
paramEntity.TemplateId = entity.Id;
|
||||
paramEntity.Id= SnowflakeIdHelper.NextId();
|
||||
await _repository.AsSugarClient().Insertable(paramEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommandAsync();
|
||||
}
|
||||
var smsFieldList = await _repository.AsSugarClient().Queryable<MessageSmsFieldEntity>().Where(x => x.TemplateId == id && x.DeleteMark == null).ToListAsync();
|
||||
foreach (var item in smsFieldList)
|
||||
{
|
||||
var smsFieldEntity = item.Adapt<MessageSmsFieldEntity>();
|
||||
smsFieldEntity.TemplateId = entity.Id;
|
||||
smsFieldEntity.Id = SnowflakeIdHelper.NextId();
|
||||
await _repository.AsSugarClient().Insertable(smsFieldEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommandAsync();
|
||||
if (isOk < 1)
|
||||
throw Oops.Oh(ErrorCode.COM1008);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
702
message/Tnb.Message/Service/SendMessageService.cs
Normal file
702
message/Tnb.Message/Service/SendMessageService.cs
Normal file
@@ -0,0 +1,702 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using JNPF.Common.Core.Manager;
|
||||
using JNPF.Common.Dtos.Message;
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Filter;
|
||||
using JNPF.Common.Options;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.Extras.Thirdparty.DingDing;
|
||||
using JNPF.Extras.Thirdparty.Email;
|
||||
using JNPF.Extras.Thirdparty.Sms;
|
||||
using JNPF.Extras.Thirdparty.WeChat;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Message.Entitys.Dto.MessageTemplate;
|
||||
using JNPF.Message.Entitys.Dto.SendMessage;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Message.Entitys.Model.MessageTemplate;
|
||||
using JNPF.Message.Interfaces.Message;
|
||||
using JNPF.RemoteRequest.Extensions;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using JNPF.Systems.Interfaces.Permission;
|
||||
using JNPF.Systems.Interfaces.System;
|
||||
using JNPF.WorkFlow.Entitys.Entity;
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 发送配置
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "SendMessage", Order = 240)]
|
||||
[Route("api/message/SendMessageConfig")]
|
||||
public class SendMessageService : ISendMessageService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageSendEntity> _repository;
|
||||
private readonly IUsersService _usersService;
|
||||
private readonly IMessageService _messageService;
|
||||
private readonly ISynThirdInfoService _synThirdInfoService;
|
||||
private readonly IShortLinkService _shortLinkService;
|
||||
private readonly MessageOptions _messageOptions = App.GetConfig<MessageOptions>("Message", true);
|
||||
private readonly IUserManager _userManager;
|
||||
|
||||
public SendMessageService(
|
||||
ISqlSugarRepository<MessageSendEntity> repository,
|
||||
IUsersService usersService,
|
||||
IMessageService messageService,
|
||||
ISynThirdInfoService synThirdInfoService,
|
||||
IShortLinkService shortLinkService,
|
||||
IUserManager userManager)
|
||||
{
|
||||
_repository = repository;
|
||||
_usersService = usersService;
|
||||
_messageService = messageService;
|
||||
_synThirdInfoService = synThirdInfoService;
|
||||
_shortLinkService = shortLinkService;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
#region Get
|
||||
/// <summary>
|
||||
/// 列表.
|
||||
/// </summary>
|
||||
/// <param name="input">请求参数.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("")]
|
||||
public async Task<dynamic> GetList([FromQuery] MessageTemplateQuery input)
|
||||
{
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageSendEntity>()
|
||||
.Where(a => a.DeleteMark == null)
|
||||
.WhereIF(input.messageSource.IsNotEmptyOrNull(), a => a.MessageSource == input.messageSource)
|
||||
.WhereIF(input.templateType.IsNotEmptyOrNull(), a => a.TemplateType == input.templateType)
|
||||
.WhereIF(input.enabledMark.IsNotEmptyOrNull(), a => a.EnabledMark == input.enabledMark)
|
||||
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
|
||||
.OrderBy(a => a.SortCode)
|
||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||||
.Select(a => new SendMessageListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
fullName = a.FullName,
|
||||
enCode = a.EnCode,
|
||||
templateType = a.TemplateType,
|
||||
messageSource = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "4" && u.EnCode == a.MessageSource).Select(u => u.FullName),
|
||||
creatorUser = SqlFunc.Subqueryable<UserEntity>().Where(u => u.Id == a.CreatorUserId).Select(u => SqlFunc.MergeString(u.RealName, "/", u.Account)),
|
||||
creatorTime = a.CreatorTime,
|
||||
lastModifyTime = a.LastModifyTime,
|
||||
sortCode = a.SortCode,
|
||||
enabledMark = a.EnabledMark,
|
||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||
foreach (var item in list.list)
|
||||
{
|
||||
item.messageType = await _repository.AsSugarClient()
|
||||
.Queryable<MessageSendTemplateEntity, MessageDataTypeEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.MessageType == b.EnCode && b.Type == "1"))
|
||||
.Where((a, b) => a.SendConfigId == item.id && a.DeleteMark == null)
|
||||
.Select((a, b) => new MessageTypeModel
|
||||
{
|
||||
fullName = b.FullName,
|
||||
type = a.MessageType,
|
||||
}).ToListAsync();
|
||||
}
|
||||
return PageResult<SendMessageListOutput>.SqlSugarPageResult(list);
|
||||
}
|
||||
|
||||
[HttpGet("getSendConfigList")]
|
||||
public async Task<dynamic> GetSendList([FromQuery] MessageTemplateQuery input)
|
||||
{
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageSendEntity>()
|
||||
.Where(a => a.DeleteMark == null)
|
||||
.WhereIF(input.messageSource.IsNotEmptyOrNull(), a => a.MessageSource == input.messageSource)
|
||||
.WhereIF(input.templateType.IsNotEmptyOrNull(), a => a.TemplateType == input.templateType)
|
||||
.WhereIF(input.enabledMark.IsNotEmptyOrNull(), a => a.EnabledMark == input.enabledMark)
|
||||
.WhereIF(input.keyword.IsNotEmptyOrNull(), a => a.FullName.Contains(input.keyword) || a.EnCode.Contains(input.keyword))
|
||||
.OrderBy(a => a.SortCode)
|
||||
.OrderBy(a => a.CreatorTime, OrderByType.Desc)
|
||||
.OrderBy(a => a.LastModifyTime, OrderByType.Desc)
|
||||
.Select(a => new SendMessageListOutput
|
||||
{
|
||||
id = a.Id,
|
||||
fullName = a.FullName,
|
||||
enCode = a.EnCode,
|
||||
}).ToPagedListAsync(input.currentPage, input.pageSize);
|
||||
foreach (var item in list.list)
|
||||
{
|
||||
item.templateJson = await SendTest(item.id);
|
||||
}
|
||||
return PageResult<SendMessageListOutput>.SqlSugarPageResult(list);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{id}")]
|
||||
public async Task<dynamic> GetInfo(string id)
|
||||
{
|
||||
var output = (await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null)).Adapt<SendMessageInfoOutput>();
|
||||
output.sendConfigTemplateList = await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity, MessageTemplateEntity, MessageAccountEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id, JoinType.Left, a.AccountConfigId == c.Id))
|
||||
.Where(a => a.SendConfigId == id && a.DeleteMark == null)
|
||||
.Select((a, b, c) => new SendTemplateModel
|
||||
{
|
||||
id = a.Id,
|
||||
messageType = a.MessageType,
|
||||
sendConfigId = a.SendConfigId,
|
||||
templateId = a.TemplateId,
|
||||
accountConfigId = a.AccountConfigId,
|
||||
templateCode = b.EnCode,
|
||||
templateName = b.FullName,
|
||||
accountCode = c.EnCode,
|
||||
accountName = c.FullName,
|
||||
enabledMark = a.EnabledMark,
|
||||
sortCode = a.SortCode,
|
||||
description = a.Description
|
||||
}).ToListAsync();
|
||||
return output;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region POST
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("")]
|
||||
public async Task Create([FromBody] SendMessageInfoOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
var entity = input.Adapt<MessageSendEntity>();
|
||||
var result = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
|
||||
if (input.sendConfigTemplateList.Any())
|
||||
{
|
||||
foreach (var item in input.sendConfigTemplateList)
|
||||
{
|
||||
var sendTemplateEntity = item.Adapt<MessageSendTemplateEntity>();
|
||||
sendTemplateEntity.SendConfigId = result.Id;
|
||||
await _repository.AsSugarClient().Insertable(sendTemplateEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
if (result.IsNullOrEmpty())
|
||||
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] SendMessageInfoOutput input)
|
||||
{
|
||||
if (await _repository.IsAnyAsync(x => x.Id != id && (x.EnCode == input.enCode || x.FullName == input.fullName) && x.DeleteMark == null))
|
||||
throw Oops.Oh(ErrorCode.COM1004);
|
||||
var entity = input.Adapt<MessageSendEntity>();
|
||||
await _repository.AsSugarClient().Deleteable<MessageSendTemplateEntity>(x => x.SendConfigId == id).ExecuteCommandAsync();
|
||||
if (input.sendConfigTemplateList.Any())
|
||||
{
|
||||
foreach (var item in input.sendConfigTemplateList)
|
||||
{
|
||||
var sendTemplateEntity = item.Adapt<MessageSendTemplateEntity>();
|
||||
sendTemplateEntity.SendConfigId = id;
|
||||
await _repository.AsSugarClient().Insertable(sendTemplateEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
}
|
||||
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>
|
||||
[HttpDelete("{id}")]
|
||||
public async Task Delete(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
if (entity == null)
|
||||
throw Oops.Oh(ErrorCode.COM1005);
|
||||
if (await _repository.AsSugarClient().Queryable<FlowEngineEntity>().AnyAsync(x => x.FlowTemplateJson.Contains(id)))
|
||||
throw Oops.Oh(ErrorCode.D1007);
|
||||
await _repository.AsSugarClient().Deleteable<MessageSendTemplateEntity>(x => x.SendConfigId == id).ExecuteCommandAsync();
|
||||
var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync();
|
||||
if (!isOk)
|
||||
throw Oops.Oh(ErrorCode.COM1002);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 复制.
|
||||
/// </summary>
|
||||
/// <param name="id">主键值.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("copy/{id}")]
|
||||
public async Task ActionsCopy(string id)
|
||||
{
|
||||
var entity = await _repository.GetFirstAsync(x => x.Id == id && x.DeleteMark == null);
|
||||
var random = RandomExtensions.NextLetterAndNumberString(new Random(), 5).ToLower();
|
||||
entity.FullName = string.Format("{0}副本{1}", entity.FullName, random);
|
||||
entity.EnCode = string.Format("{0}{1}", entity.EnCode, random);
|
||||
entity.Id = SnowflakeIdHelper.NextId();
|
||||
if (entity.FullName.Length >= 50 || entity.EnCode.Length >= 50)
|
||||
throw Oops.Oh(ErrorCode.COM1009);
|
||||
var sendTemplateList = await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity>().Where(x => x.SendConfigId == id && x.DeleteMark == null).ToListAsync();
|
||||
foreach (var item in sendTemplateList)
|
||||
{
|
||||
var sendTemplateEntity = item.Adapt<MessageSendTemplateEntity>();
|
||||
sendTemplateEntity.SendConfigId = entity.Id;
|
||||
await _repository.AsSugarClient().Insertable(sendTemplateEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteCommandAsync();
|
||||
if (isOk < 1)
|
||||
throw Oops.Oh(ErrorCode.COM1008);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试发送.
|
||||
/// </summary>
|
||||
/// <param name="id">主键值.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("getTestConfig/{id}")]
|
||||
public async Task<dynamic> SendTest(string id)
|
||||
{
|
||||
var list = await _repository.AsSugarClient().Queryable<MessageSendTemplateEntity, MessageTemplateEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id))
|
||||
.Where((a, b) => a.SendConfigId == id && a.DeleteMark == null && b.DeleteMark == null)
|
||||
.Select((a, b) => new MessageSendModel
|
||||
{
|
||||
accountConfigId = a.AccountConfigId,
|
||||
id = a.Id,
|
||||
messageType = SqlFunc.Subqueryable<MessageDataTypeEntity>().Where(u => u.Type == "1" && u.EnCode == a.MessageType).Select(u => u.FullName),
|
||||
msgTemplateName = b.FullName,
|
||||
sendConfigId = a.SendConfigId,
|
||||
templateId = a.TemplateId,
|
||||
}).ToListAsync();
|
||||
foreach (var item in list)
|
||||
{
|
||||
// 是否存在参数.
|
||||
var flag = await _repository.AsSugarClient().Queryable<MessageSmsFieldEntity>().AnyAsync(x => x.TemplateId == item.templateId && x.DeleteMark == null);
|
||||
if (flag)
|
||||
{
|
||||
item.paramJson = await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity, MessageTemplateEntity, MessageSmsFieldEntity>((a, b, c) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id, JoinType.Left, a.TemplateId == c.TemplateId))
|
||||
.Where((a, b, c) => a.TemplateId == item.templateId && a.DeleteMark == null && b.DeleteMark == null && a.Field == c.Field && a.Field != "@flowLink")
|
||||
.Select((a, b) => new MessageSendParam
|
||||
{
|
||||
field = a.Field,
|
||||
fieldName = a.FieldName,
|
||||
id = a.Id,
|
||||
templateCode = b.TemplateCode,
|
||||
templateId = a.TemplateId,
|
||||
templateName = b.FullName,
|
||||
templateType = b.TemplateType
|
||||
}).ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.paramJson = await _repository.AsSugarClient().Queryable<MessageTemplateParamEntity, MessageTemplateEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.TemplateId == b.Id))
|
||||
.Where((a, b) => a.TemplateId == item.templateId && a.DeleteMark == null && b.DeleteMark == null && a.Field != "@flowLink")
|
||||
.Where((a, b) => b.Title.Contains(a.Field) || b.Content.Contains(a.Field))
|
||||
.Select((a, b) => new MessageSendParam
|
||||
{
|
||||
field = a.Field,
|
||||
fieldName = a.FieldName,
|
||||
id = a.Id,
|
||||
templateCode = b.TemplateCode,
|
||||
templateId = a.TemplateId,
|
||||
templateName = b.FullName,
|
||||
templateType = b.TemplateType
|
||||
}).ToListAsync();
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试发送.
|
||||
/// </summary>
|
||||
/// <param name="id">主键值.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("testSendConfig")]
|
||||
public async Task<dynamic> SendTest([FromBody] List<MessageSendModel> input)
|
||||
{
|
||||
var resultList = new List<object>();
|
||||
foreach (var item in input)
|
||||
{
|
||||
var result = await SendMessage(item, new Dictionary<string, object>());
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
resultList.Add(new { isSuccess = "1", messageType = string.Format("消息类型:{0}", item.messageType) });
|
||||
}
|
||||
else
|
||||
{
|
||||
resultList.Add(new { isSuccess = "0", messageType = string.Format("消息类型:{0}", item.messageType), result = string.Format("发送{0}失败,失败原因:{1}", item.messageType, result) });
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PublicMethod
|
||||
[NonAction]
|
||||
public async Task<string> SendMessage(MessageSendModel messageSendModel, Dictionary<string, object> bodyDic)
|
||||
{
|
||||
var errorList = new List<string>();
|
||||
var messageTemplateEntity = await _repository.AsSugarClient().Queryable<MessageTemplateEntity>().FirstAsync(x => x.Id == messageSendModel.templateId && x.DeleteMark == null);
|
||||
var messageAccountEntity = await _repository.AsSugarClient().Queryable<MessageAccountEntity>().FirstAsync(x => x.Id == messageSendModel.accountConfigId && x.DeleteMark == null);
|
||||
var paramsDic = messageSendModel.paramJson.ToDictionary(x => x.field, y => y.value);//参数
|
||||
var title = messageTemplateEntity.Title;
|
||||
var content = messageTemplateEntity.Content;
|
||||
if (messageTemplateEntity.MessageType=="6")
|
||||
{
|
||||
try
|
||||
{
|
||||
messageTemplateEntity.Title = MessageTemplateManage(messageTemplateEntity.Title, paramsDic);
|
||||
messageTemplateEntity.Content = MessageTemplateManage(messageTemplateEntity.Content, paramsDic);
|
||||
await WebHookSend(messageTemplateEntity, messageAccountEntity);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
errorList.Add(string.Format("【{0}】", ex.Message));
|
||||
}
|
||||
var messageMonitorEntity = new MessageMonitorEntity();
|
||||
messageMonitorEntity.MessageType = messageTemplateEntity.MessageType;
|
||||
messageMonitorEntity.MessageSource = messageTemplateEntity.MessageSource;
|
||||
messageMonitorEntity.SendTime = DateTime.Now;
|
||||
messageMonitorEntity.MessageTemplateId = messageTemplateEntity.Id;
|
||||
messageMonitorEntity.Title = messageTemplateEntity.Title;
|
||||
await _repository.AsSugarClient().Insertable(messageMonitorEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
foreach (var item in messageSendModel.toUser)
|
||||
{
|
||||
var userId = item.Replace("-delegate", string.Empty);
|
||||
var userName = await _usersService.GetUserName(userId);
|
||||
try
|
||||
{
|
||||
if (bodyDic.IsNotEmptyOrNull() && bodyDic.ContainsKey(item))
|
||||
{
|
||||
var shortLinkEntity = await _shortLinkService.Create(userId, bodyDic[item].ToJsonString());
|
||||
var shortLink = string.Format("{0}/dev/api/message/ShortLink/{1}", _messageOptions.DoMainPc, shortLinkEntity.ShortLink);
|
||||
paramsDic["@flowLink"] = shortLink;
|
||||
}
|
||||
messageTemplateEntity.Title = MessageTemplateManage(title, paramsDic);
|
||||
messageTemplateEntity.Content = MessageTemplateManage(content, paramsDic);
|
||||
switch (messageTemplateEntity.MessageType)
|
||||
{
|
||||
case "1"://站内信
|
||||
await _messageService.SentMessage(new List<string>() { item }, messageTemplateEntity.Title, messageTemplateEntity.Content, bodyDic);
|
||||
break;
|
||||
case "2"://邮件
|
||||
EmailSend(new List<string>() { userId }, messageTemplateEntity, messageAccountEntity);
|
||||
break;
|
||||
case "3"://短信
|
||||
SmsSend(new List<string>() { userId }, messageTemplateEntity, messageAccountEntity, paramsDic);
|
||||
break;
|
||||
case "4"://钉钉
|
||||
var dingIds = await _synThirdInfoService.GetThirdIdList(new List<string>() { userId }, 2, 3);
|
||||
if (dingIds.Count > 0)
|
||||
{
|
||||
var dingMsg = new { msgtype = "text", text = new { content = messageTemplateEntity.Content } }.ToJsonString();
|
||||
DingWorkMessageParameter dingWorkMsgModel = new DingWorkMessageParameter()
|
||||
{
|
||||
toUsers = string.Join(",", dingIds),
|
||||
agentId = messageAccountEntity.AgentId,
|
||||
msg = dingMsg
|
||||
};
|
||||
new DingUtil(messageAccountEntity.AppId, messageAccountEntity.AppSecret).SendWorkMsg(dingWorkMsgModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Oops.Oh(ErrorCode.D7015);
|
||||
}
|
||||
break;
|
||||
case "5"://企业微信
|
||||
var qyIds = await _synThirdInfoService.GetThirdIdList(new List<string>() { userId }, 1, 3);
|
||||
var weChat = new WeChatUtil(messageAccountEntity.EnterpriseId, messageAccountEntity.AppSecret);
|
||||
if (qyIds.Count > 0)
|
||||
{
|
||||
await weChat.SendText(messageAccountEntity.AppId, messageTemplateEntity.Content, string.Join(",", qyIds));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Oops.Oh(ErrorCode.D7015);
|
||||
}
|
||||
break;
|
||||
case "7"://微信公众号
|
||||
var body = bodyDic.ContainsKey(item) ? bodyDic[item].ToJsonString() : string.Empty;
|
||||
WeChatMpSend(userId, messageTemplateEntity, messageAccountEntity, paramsDic, body);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorList.Add(string.Format("用户{0}【{1}】", userName, ex.Message));
|
||||
}
|
||||
|
||||
#region 消息监控
|
||||
var messageMonitorEntity = new MessageMonitorEntity();
|
||||
messageMonitorEntity.MessageType = messageTemplateEntity.MessageType;
|
||||
messageMonitorEntity.MessageSource = messageTemplateEntity.MessageSource;
|
||||
messageMonitorEntity.SendTime = DateTime.Now;
|
||||
messageMonitorEntity.MessageTemplateId = messageTemplateEntity.Id;
|
||||
messageMonitorEntity.Title = messageTemplateEntity.Title;
|
||||
messageMonitorEntity.Content = messageTemplateEntity.Content;
|
||||
messageMonitorEntity.ReceiveUser = userId;
|
||||
await _repository.AsSugarClient().Insertable(messageMonitorEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
#endregion
|
||||
}
|
||||
return errorList.Any() ? string.Join(",", errorList) : string.Empty;
|
||||
}
|
||||
|
||||
public async Task SendMessageDefult(string enCode,List<string> toUser, string taskName, Dictionary<string, object> bodyDic)
|
||||
{
|
||||
var msgTemplateEntity= await _repository.AsSugarClient().Queryable<MessageTemplateEntity>().FirstAsync(x => x.EnCode == enCode && x.TemplateType=="1" && x.DeleteMark == null);
|
||||
msgTemplateEntity.Title= msgTemplateEntity.Title.Replace("@流程发起人@流程名称", taskName);
|
||||
msgTemplateEntity.Content = msgTemplateEntity.Content.Replace("@流程发起人@流程名称", taskName);
|
||||
await _messageService.SentMessage(toUser, msgTemplateEntity.Title, msgTemplateEntity.Content, bodyDic);
|
||||
#region 消息监控
|
||||
foreach (var item in toUser)
|
||||
{
|
||||
var userId = item.Replace("-delegate", string.Empty);
|
||||
var messageMonitorEntity = new MessageMonitorEntity();
|
||||
messageMonitorEntity.MessageType = msgTemplateEntity.MessageType;
|
||||
messageMonitorEntity.MessageSource = msgTemplateEntity.MessageSource;
|
||||
messageMonitorEntity.SendTime = DateTime.Now;
|
||||
messageMonitorEntity.MessageTemplateId = msgTemplateEntity.Id;
|
||||
messageMonitorEntity.Title = msgTemplateEntity.Title;
|
||||
messageMonitorEntity.Content = msgTemplateEntity.Content;
|
||||
messageMonitorEntity.ReceiveUser = item;
|
||||
await _repository.AsSugarClient().Insertable(messageMonitorEntity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PrivateMethod
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱.
|
||||
/// </summary>
|
||||
/// <param name="titile"></param>
|
||||
/// <param name="userList"></param>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="sysconfig"></param>
|
||||
/// <returns></returns>
|
||||
private void EmailSend(List<string> userList, MessageTemplateEntity messageTemplateEntity, MessageAccountEntity messageAccountEntity)
|
||||
{
|
||||
var emailList = new List<string>();
|
||||
foreach (var item in userList)
|
||||
{
|
||||
var user = _usersService.GetInfoByUserId(item);
|
||||
if (user.IsNotEmptyOrNull() && user.Email.IsNotEmptyOrNull())
|
||||
{
|
||||
emailList.Add(user.Email);
|
||||
}
|
||||
}
|
||||
var mailModel = new MailInfo();
|
||||
mailModel.To = string.Join(",", emailList);
|
||||
mailModel.Subject = messageTemplateEntity.Title;
|
||||
mailModel.BodyText = HttpUtility.HtmlDecode(messageTemplateEntity.Content);
|
||||
MailUtil.Send(
|
||||
new MailParameterInfo
|
||||
{
|
||||
AccountName = messageAccountEntity.AddressorName,
|
||||
Account = messageAccountEntity.SmtpUser,
|
||||
Password = messageAccountEntity.SmtpPassword,
|
||||
SMTPHost = messageAccountEntity.SmtpServer,
|
||||
SMTPPort = messageAccountEntity.SmtpPort.ParseToInt(),
|
||||
Ssl=messageAccountEntity.SslLink.Equals("1")
|
||||
}, mailModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 短信.
|
||||
/// </summary>
|
||||
/// <param name="messageTemplateEntity"></param>
|
||||
/// <param name="userList"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <param name="sysconfig"></param>
|
||||
private void SmsSend(List<string> userList, MessageTemplateEntity messageTemplateEntity, MessageAccountEntity messageAccountEntity, Dictionary<string, string> smsParams)
|
||||
{
|
||||
var phoneList = new List<string>();//电话号码
|
||||
foreach (var item in userList)
|
||||
{
|
||||
var user = _usersService.GetInfoByUserId(item);
|
||||
if (user.IsNotEmptyOrNull() && user.MobilePhone.IsNotEmptyOrNull())
|
||||
{
|
||||
phoneList.Add("+86" + user.MobilePhone);
|
||||
}
|
||||
}
|
||||
var smsModel = new SmsParameterInfo()
|
||||
{
|
||||
keyId = messageAccountEntity.AppId,
|
||||
keySecret = messageAccountEntity.AppSecret,
|
||||
region = messageAccountEntity.ZoneParam,
|
||||
domain = messageAccountEntity.Channel.Equals("1") ? messageAccountEntity.EndPoint : messageAccountEntity.ZoneName,
|
||||
templateId = messageTemplateEntity.TemplateCode,
|
||||
signName = messageAccountEntity.SmsSignature,
|
||||
appId = messageAccountEntity.SdkAppId
|
||||
};
|
||||
var smsFieldList = _repository.AsSugarClient().Queryable<MessageSmsFieldEntity>().Where(x => x.TemplateId == messageTemplateEntity.Id).ToDictionary(x => x.SmsField, y => y.Field);
|
||||
foreach (var item in smsFieldList.Keys)
|
||||
{
|
||||
if (smsParams.Keys.Contains(smsFieldList[item].ToString()))
|
||||
{
|
||||
smsFieldList[item] = smsParams[smsFieldList[item].ToString()];
|
||||
}
|
||||
}
|
||||
if (messageAccountEntity.Channel.Equals("1"))
|
||||
{
|
||||
smsModel.mobileAli = string.Join(",", phoneList);
|
||||
smsModel.templateParamAli = smsFieldList.ToJsonString();
|
||||
SmsUtil.SendSmsByAli(smsModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
smsModel.mobileTx = phoneList.ToArray();
|
||||
List<string> mList = new List<string>();
|
||||
var fields = SmsUtil.GetTemplateByTencent(smsModel);
|
||||
foreach (string item in fields)
|
||||
{
|
||||
if (smsFieldList.ContainsKey(item))
|
||||
mList.Add(smsFieldList[item].ToString());
|
||||
}
|
||||
|
||||
smsModel.templateParamTx = mList.ToArray();
|
||||
SmsUtil.SendSmsByTencent(smsModel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// webhook.
|
||||
/// </summary>
|
||||
/// <param name="messageTemplateEntity"></param>
|
||||
/// <param name="messageAccountEntity"></param>
|
||||
/// <param name="messageSendModel"></param>
|
||||
/// <returns></returns>
|
||||
private async Task WebHookSend(MessageTemplateEntity messageTemplateEntity, MessageAccountEntity messageAccountEntity)
|
||||
{
|
||||
// 钉钉
|
||||
if (messageAccountEntity.WebhookType == "1")
|
||||
{
|
||||
// 认证
|
||||
if (messageAccountEntity.ApproveType == "2") SignWebhook(messageAccountEntity);
|
||||
new DingUtil().SendGroupMsg(messageAccountEntity.WebhookAddress, messageTemplateEntity.Content);
|
||||
}
|
||||
// 企业微信
|
||||
if (messageAccountEntity.WebhookType == "2")
|
||||
{
|
||||
var bodyDic = new Dictionary<string, object>();
|
||||
bodyDic.Add("msgtype", "text");
|
||||
bodyDic.Add("text", new { content = messageTemplateEntity.Content });
|
||||
await messageAccountEntity.WebhookAddress.SetBody(bodyDic).PostAsStringAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// webhook签名.
|
||||
/// </summary>
|
||||
/// <param name="messageAccountEntity"></param>
|
||||
private void SignWebhook(MessageAccountEntity messageAccountEntity)
|
||||
{
|
||||
// webhook加签密钥
|
||||
var secret = messageAccountEntity.Bearer;
|
||||
|
||||
// 获取时间戳
|
||||
var timestamp = DateTime.Now.ParseToUnixTime();
|
||||
|
||||
var signature = string.Empty;
|
||||
using (var hmac = new HMACSHA256(secret.ToBase64String().ToBytes()))
|
||||
{
|
||||
byte[] hashmessage = hmac.ComputeHash(timestamp.ToString().ToBytes(Encoding.UTF8));
|
||||
signature = hashmessage.ToHexString();
|
||||
}
|
||||
|
||||
messageAccountEntity.WebhookAddress = string.Format("{0}×tamp={1}&signature={2}", messageAccountEntity.WebhookAddress, timestamp, signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 公众号.
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="messageTemplateEntity"></param>
|
||||
/// <param name="messageAccountEntity"></param>
|
||||
/// <param name="paramDic"></param>
|
||||
/// <param name="bodyDic"></param>
|
||||
private void WeChatMpSend(string userId, MessageTemplateEntity messageTemplateEntity, MessageAccountEntity messageAccountEntity, Dictionary<string, string> paramDic, string bodyDic)
|
||||
{
|
||||
var weChatMP = new WeChatMPUtil(messageAccountEntity.AppId, messageAccountEntity.AppSecret);
|
||||
var wechatUser = _repository.AsSugarClient().Queryable<MessageWechatUserEntity>().Single(x => userId == x.UserId);
|
||||
if (wechatUser == null) throw Oops.Oh(ErrorCode.D7016);
|
||||
var openId = wechatUser.IsNotEmptyOrNull() ? wechatUser.OpenId : string.Empty;
|
||||
var mpFieldList = _repository.AsSugarClient().Queryable<MessageSmsFieldEntity>().Where(x => x.TemplateId == messageTemplateEntity.Id).ToList();
|
||||
var mpTempDic = new Dictionary<string, object>();
|
||||
foreach (var item in mpFieldList)
|
||||
{
|
||||
if (paramDic.Keys.Contains(item.Field))
|
||||
{
|
||||
mpTempDic[item.SmsField] = new { value = paramDic[item.Field] };
|
||||
}
|
||||
}
|
||||
var url = paramDic.ContainsKey("@flowLink") ? paramDic["@flowLink"] : string.Empty;
|
||||
// 跳转小程序
|
||||
if (messageTemplateEntity.WxSkip == "1")
|
||||
{
|
||||
var config = bodyDic.ToBase64String();
|
||||
var token = _shortLinkService.CreateToken(userId);
|
||||
var miniProgram = new TemplateModel_MiniProgram
|
||||
{
|
||||
appid = messageTemplateEntity.XcxAppId,
|
||||
pagepath = "/pages/workFlow/flowBefore/index?config=" + config + "&token=" + token
|
||||
};
|
||||
weChatMP.SendTemplateMessage(openId, messageTemplateEntity.TemplateCode, url, mpTempDic, miniProgram);
|
||||
}
|
||||
else
|
||||
{
|
||||
weChatMP.SendTemplateMessage(openId, messageTemplateEntity.TemplateCode, url, mpTempDic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 参数处理.
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="paramDic"></param>
|
||||
/// <returns></returns>
|
||||
private string MessageTemplateManage(string text, Dictionary<string, string> paramDic, bool isGzh = false)
|
||||
{
|
||||
if (text.IsNotEmptyOrNull())
|
||||
{
|
||||
// 默认站内信
|
||||
if (paramDic.ContainsKey("@taskFullName"))
|
||||
{
|
||||
text = text.Replace("@流程发起人@流程名称", paramDic["@taskFullName"]);
|
||||
}
|
||||
foreach (var item in paramDic.Keys)
|
||||
{
|
||||
if (isGzh)
|
||||
{
|
||||
text = text.Replace(item, paramDic[item]);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = text.Replace("{" + item + "}", paramDic[item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
158
message/Tnb.Message/Service/ShortLinkService.cs
Normal file
158
message/Tnb.Message/Service/ShortLinkService.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using JNPF.Common.Const;
|
||||
using JNPF.Common.Dtos.OAuth;
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Net;
|
||||
using JNPF.Common.Options;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DataEncryption;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Logging.Attributes;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Message.Interfaces.Message;
|
||||
using JNPF.RemoteRequest.Extensions;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using JNPF.Systems.Interfaces.System;
|
||||
using JNPF.UnifyResult;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 公众号.
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "ShortLink", Order = 240)]
|
||||
[Route("api/message/[controller]")]
|
||||
public class ShortLinkService : IShortLinkService, IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageShortLinkEntity> _repository;
|
||||
private readonly ISysConfigService _sysConfigService;
|
||||
private readonly ConnectionStringsOptions _connectionStrings;
|
||||
private readonly TenantOptions _tenant;
|
||||
private readonly MessageOptions _messageOptions = App.GetConfig<MessageOptions>("Message", true);
|
||||
private SqlSugarScope _sqlSugarClient;
|
||||
|
||||
public ShortLinkService(
|
||||
ISqlSugarRepository<MessageShortLinkEntity> repository,
|
||||
ISysConfigService sysConfigService,
|
||||
IOptions<ConnectionStringsOptions> connectionOptions,
|
||||
IOptions<TenantOptions> tenantOptions,
|
||||
ISqlSugarClient sqlSugarClient
|
||||
)
|
||||
{
|
||||
_repository = repository;
|
||||
_sysConfigService = sysConfigService;
|
||||
_connectionStrings = connectionOptions.Value;
|
||||
_tenant = tenantOptions.Value;
|
||||
_sqlSugarClient = (SqlSugarScope)sqlSugarClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("{shortLink}")]
|
||||
[HttpGet("{shortLink}/{tenantId}")]
|
||||
[AllowAnonymous]
|
||||
[IgnoreLog]
|
||||
public async Task GetInfo(string shortLink, string tenantId)
|
||||
{
|
||||
ConnectionConfigOptions options = JNPFTenantExtensions.GetLinkToOrdinary(_connectionStrings.ConfigId, _connectionStrings.DBName);
|
||||
UserAgent userAgent = new UserAgent(App.HttpContext);
|
||||
if (tenantId.IsNotEmptyOrNull())
|
||||
{
|
||||
var interFace = string.Format("{0}{1}", _tenant.MultiTenancyDBInterFace, tenantId);
|
||||
var response = await interFace.GetAsStringAsync();
|
||||
var result = response.ToObject<RESTfulResult<TenantInterFaceOutput>>();
|
||||
if (result.code != 200)
|
||||
{
|
||||
throw Oops.Oh(result.msg);
|
||||
}
|
||||
else if (result.data.dotnet == null && result.data.linkList == null)
|
||||
{
|
||||
throw Oops.Oh(ErrorCode.D1025);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result.data.linkList == null || result.data.linkList?.Count == 0)
|
||||
{
|
||||
options = JNPFTenantExtensions.GetLinkToOrdinary(tenantId, result.data.dotnet);
|
||||
}
|
||||
else if (result.data.dotnet == null)
|
||||
{
|
||||
options = JNPFTenantExtensions.GetLinkToCustom(tenantId, result.data.linkList);
|
||||
}
|
||||
}
|
||||
|
||||
_sqlSugarClient.AddConnection(JNPFTenantExtensions.GetConfig(options));
|
||||
_sqlSugarClient.ChangeDatabase(tenantId);
|
||||
}
|
||||
|
||||
var entity = await _sqlSugarClient.Queryable<MessageShortLinkEntity>().SingleAsync(x => x.ShortLink == shortLink && x.DeleteMark == null);
|
||||
if (entity == null) throw Oops.Oh(ErrorCode.D7009);
|
||||
// 验证失效以及修改点击次数
|
||||
if (entity.IsUsed == 1)
|
||||
{
|
||||
if (entity.UnableTime < DateTime.Now || entity.ClickNum == entity.UnableNum) throw Oops.Oh(ErrorCode.D7010);
|
||||
++entity.ClickNum;
|
||||
await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
|
||||
}
|
||||
string accessToken = CreateToken(entity.UserId);
|
||||
// 验证请求端
|
||||
var urlLink = userAgent.IsMobileDevice ? entity.RealAppLink : entity.RealPcLink;
|
||||
urlLink = string.Format("{0}&token={1}", urlLink, accessToken);
|
||||
App.HttpContext.Response.Redirect(urlLink);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[NonAction]
|
||||
public async Task<MessageShortLinkEntity> Create(string userId, string bodyText)
|
||||
{
|
||||
var sysconfig = await _sysConfigService.GetInfo();
|
||||
var entity = new MessageShortLinkEntity();
|
||||
entity.ShortLink = RandomExtensions.NextLetterAndNumberString(new Random(), 6);
|
||||
entity.UserId = userId;
|
||||
if (sysconfig.isClick == 1)
|
||||
{
|
||||
entity.IsUsed = 1;
|
||||
entity.ClickNum = 0;
|
||||
entity.UnableNum = sysconfig.unClickNum;
|
||||
entity.UnableTime = DateTime.Now.AddHours(sysconfig.linkTime);
|
||||
}
|
||||
entity.BodyText = bodyText;
|
||||
entity.RealAppLink = string.Format("{0}/pages/workFlow/flowBefore/index?config={1}", _messageOptions.DoMainApp, bodyText.ToBase64String());
|
||||
entity.RealPcLink = string.Format("{0}/workFlowDetail?config={1}", _messageOptions.DoMainPc, bodyText.ToBase64String());
|
||||
return await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Create()).ExecuteReturnEntityAsync();
|
||||
}
|
||||
|
||||
public string CreateToken(string userId)
|
||||
{
|
||||
ConnectionConfigOptions options = JNPFTenantExtensions.GetLinkToOrdinary(_connectionStrings.ConfigId, _connectionStrings.DBName);
|
||||
var userEntity = _sqlSugarClient.Queryable<UserEntity>().Single(u => u.Id == userId && u.DeleteMark == null);
|
||||
var token = JWTEncryption.Encrypt(
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ ClaimConst.CLAINMUSERID, userEntity.Id },
|
||||
{ ClaimConst.CLAINMACCOUNT, userEntity.Account },
|
||||
{ ClaimConst.CLAINMREALNAME, userEntity.RealName },
|
||||
{ ClaimConst.CLAINMADMINISTRATOR, userEntity.IsAdministrator },
|
||||
{ ClaimConst.TENANTID, options.ConfigId },
|
||||
{ ClaimConst.CONNECTIONCONFIG, options},
|
||||
{ ClaimConst.SINGLELOGIN, 1 }
|
||||
}, 900);
|
||||
return string.Format("Bearer%20{0}", token);
|
||||
}
|
||||
}
|
||||
128
message/Tnb.Message/Service/WechatOpenService.cs
Normal file
128
message/Tnb.Message/Service/WechatOpenService.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using JNPF.Common.Enums;
|
||||
using JNPF.Common.Extension;
|
||||
using JNPF.Common.Security;
|
||||
using JNPF.DependencyInjection;
|
||||
using JNPF.DynamicApiController;
|
||||
using JNPF.Extras.Thirdparty.WeChat;
|
||||
using JNPF.Extras.Thirdparty.WeChat.Internal;
|
||||
using JNPF.FriendlyException;
|
||||
using JNPF.Logging.Attributes;
|
||||
using JNPF.Message.Entitys.Entity;
|
||||
using JNPF.Systems.Entitys.Permission;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Senparc.Weixin.MP;
|
||||
using SqlSugar;
|
||||
|
||||
namespace JNPF.Message.Service;
|
||||
|
||||
/// <summary>
|
||||
/// 公众号.
|
||||
/// 版 本:V3.2
|
||||
/// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com)
|
||||
/// 日 期:2021-06-01.
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings(Tag = "Message", Name = "WechatOpen", Order = 240)]
|
||||
[Route("api/message/[controller]")]
|
||||
public class WechatOpenService : IDynamicApiController, ITransient
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageWechatUserEntity> _repository;
|
||||
|
||||
public WechatOpenService(ISqlSugarRepository<MessageWechatUserEntity> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("token")]
|
||||
[AllowAnonymous]
|
||||
[IgnoreLog]
|
||||
[NonUnify]
|
||||
public dynamic CheckToken([FromQuery] string signature, [FromQuery] string timestamp, [FromQuery] string nonce, [FromQuery] string echostr)
|
||||
{
|
||||
var token = "WEIXINJNPF";
|
||||
var hashCode = CheckSignature.GetSignature(timestamp, nonce, token);
|
||||
if (hashCode == signature)
|
||||
{
|
||||
Console.WriteLine("验证成功");
|
||||
return echostr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("验证失败");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新建.
|
||||
/// </summary>
|
||||
/// <param name="input">实体对象.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost("token")]
|
||||
[AllowAnonymous]
|
||||
[IgnoreLog]
|
||||
[NonUnify]
|
||||
public async Task<dynamic> Create([FromQuery] string signature, [FromQuery] string timestamp, [FromQuery] string nonce, [FromQuery] string openid)
|
||||
{
|
||||
var input = await GetWechatMPEvent();
|
||||
var weChatMp = new WeChatMPUtil();
|
||||
if (weChatMp.CheckToken(signature, timestamp, nonce))
|
||||
{
|
||||
var messageAccountEntity = await _repository.AsSugarClient().Queryable<MessageAccountEntity>().FirstAsync(x => x.AppKey == input.ToUserName && x.DeleteMark == null);
|
||||
var wechatUser = new WeChatMPUtil(messageAccountEntity.AppId, messageAccountEntity.AppSecret).GetWeChatUserInfo(openid);
|
||||
if (wechatUser.IsNotEmptyOrNull() && wechatUser.unionid.IsNotEmptyOrNull())
|
||||
{
|
||||
var socialsUser = await _repository.AsSugarClient().Queryable<SocialsUsersEntity>().FirstAsync(x => x.SocialId == wechatUser.unionid && x.SocialType == "WECHAT_OPEN" && x.DeleteMark == null);
|
||||
var entity = await _repository.GetFirstAsync(x => x.GzhId == input.ToUserName && x.UserId == socialsUser.UserId && x.OpenId == openid);
|
||||
if (entity.IsNullOrEmpty())
|
||||
{
|
||||
entity = new MessageWechatUserEntity
|
||||
{
|
||||
GzhId = input.ToUserName,
|
||||
UserId = socialsUser.UserId,
|
||||
OpenId = openid,
|
||||
CloseMark = 1
|
||||
};
|
||||
await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.CloseMark = input.Event.Equals("subscribe") ? 1 : 0;
|
||||
await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取xml参数.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task<WechatMPEvent> GetWechatMPEvent()
|
||||
{
|
||||
var request = App.HttpContext.Request;
|
||||
var buffer = new byte[Convert.ToInt32(request.ContentLength)];
|
||||
await request.Body.ReadAsync(buffer, 0, buffer.Length);
|
||||
var body = Encoding.UTF8.GetString(buffer);
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.LoadXml(body);
|
||||
var input = new WechatMPEvent();
|
||||
input.ToUserName = doc.DocumentElement.SelectSingleNode("ToUserName").InnerText.Trim();
|
||||
input.FromUserName = doc.DocumentElement.SelectSingleNode("FromUserName").InnerText.Trim();
|
||||
input.Event= doc.DocumentElement.SelectSingleNode("Event").InnerText.Trim();
|
||||
return input;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user