添加项目文件。

This commit is contained in:
2023-03-13 15:00:34 +08:00
parent 42bf06ca3e
commit 1d73df3235
1205 changed files with 185078 additions and 0 deletions

View 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());
}
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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}&timestamp={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
}

View 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);
}
}

View 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;
}
}