track/src/TrackCenter.Application/Services/TrackPush/TrackPushService.cs
2025-07-14 10:30:46 +08:00

407 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Linq.Expressions;
using Microsoft.Extensions.Localization;
using SJZY.Expand.ABP.Core.Localization;
using SJZY.Expand.ABP.Core.Logger;
using SJZY.Expand.ABP.Core.PublicMethords;
using TrackCenter.Application.Dtos.TrackPush;
using TrackCenter.Application.Services;
using TrackCenter.Application.Helpers;
using TrackCenter.Application.Localization;
using TrackCenter.Application.Services.Warning.Handlers;
using TrackCenter.Domain.Aggregates.OrderAggregate;
using TrackCenter.Domain.Aggregates.TrackPushAggregate;
using TrackCenter.Domain.Dtos.TrackPush;
using TrackCenter.Domain.Enums;
using Volo.Abp.DependencyInjection;
namespace TrackCenter.Application.Services.TrackPush;
/// <summary>
/// 轨迹推送
/// </summary>
[ApiExplorerSettings(GroupName = "轨迹推送")]
[Route("/Track/PushConfig")]
public class TrackPushService : ApplicationServiceBase, ISingletonDependency
{
private readonly IStringLocalizer<TrackLocalizationResource> _stringLocalizer;
private readonly ITrackPushCacheService _trackPushCacheService;
private readonly ITrackPushConfigRepository _trackPushConfigRepository;
private readonly IOrderRepository _orderRepository;
private readonly IServiceProvider _serviceProvider;
public TrackPushService(
IStringLocalizer<TrackLocalizationResource> stringLocalizer,
ITrackPushConfigRepository trackPushConfigRepository,
ITrackPushCacheService trackPushCacheService,
IOrderRepository orderRepository, IServiceProvider serviceProvider)
{
_stringLocalizer = stringLocalizer;
_trackPushConfigRepository = trackPushConfigRepository;
_trackPushCacheService = trackPushCacheService;
_orderRepository = orderRepository;
_serviceProvider = serviceProvider;
}
/// <summary>
/// 轨迹推送配置列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetPage")]
public async Task<PagedResult<GetTrackPushConfigPageOutputVO>> GetPageAsync([FromBody] KeywordsInputVO input)
{
return await _trackPushConfigRepository.GetPageAsync(input);
}
/// <summary>
/// 获取推送配置类型标签卡列表
/// </summary>
/// <returns></returns>
[HttpPost("GetConfigTags")]
public async Task<List<TrackPushConfigTagDto>> GetConfigTags([FromBody] GetConfigTagsInputVO inputVo)
{
var orderTypes = await _trackPushConfigRepository.GetConfigTags(inputVo);
if (orderTypes.Count == 0) return new List<TrackPushConfigTagDto>();
var trackOrderTypes = await _orderRepository.GetTrackOrderTypeDictAsync();
return orderTypes.Select(x => new TrackPushConfigTagDto
{
Type = x,
Name = trackOrderTypes[x.ToString()]
})
.OrderBy(x => x.Type)
.ToList();
}
/// <summary>
/// 轨迹推送配置内容列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("GetContentPage")]
public async Task<PagedResult<GetTrackPushContentPageOutputVO>> GetContentPageAsync(
[FromBody] GetTrackPushContentPageInputVO input)
{
return await _trackPushConfigRepository.GetContentPageAsync(input);
}
/// <summary>
/// 轨迹推送配置详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("GetDetail")]
public async Task<GetTrackPushConfigDetailOutputVO> GetDetailAsync(int id)
{
return await _trackPushConfigRepository.GetDetailAsync(id);
}
/// <summary>
/// 轨迹推送配置内容详情
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("GetContentDetail")]
public async Task<GetTrackPushContentDetailOutputVO> GetContentDetailAsync(int id)
{
return await _trackPushConfigRepository.GetContentDetailAsync(id);
}
/// <summary>
/// 轨迹推送配置编辑
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("Edit")]
public async Task<string> EditAsync([FromBody] EditTrackPushConfigInput input)
{
if (input.Options != OptionTypeNoNull.删除)
{
Expression<Func<TrackPushConfigEntity, bool>> isAnyExp = x =>
x.SubSystemId == input.SubSystemId && x.CustomId == input.CustomId;
if (input.Options == OptionTypeNoNull.修改) isAnyExp = isAnyExp.And(x => x.Id != input.Id);
if (await _trackPushConfigRepository.IsAnyAsync(isAnyExp))
throw new BusinessException(message: _stringLocalizer["IsTrackPushConfigAny"]);
}
var msg = string.Empty;
if (input.Options is OptionTypeNoNull.新增 or OptionTypeNoNull.修改)
{
var (success, message) = CheckDateTimeFormat(input.DateTimeFormat, input.DateTimeFormatType, input.TimezoneFormat);
if (!success) throw new BusinessException(message: message);
msg = message;
}
using var ts = TransactionScopeHelper.Create();
switch (input.Options)
{
case OptionTypeNoNull.新增:
var trackPushEntity = ObjectMapper.Map<EditTrackPushConfigInput, TrackPushConfigEntity>(input);
await _trackPushConfigRepository.InsertReturnIdentityAsync(trackPushEntity);
await _trackPushCacheService.SetPushContentConfigsAsync(trackPushEntity.SubSystemId,
trackPushEntity.CustomId);
break;
case OptionTypeNoNull.修改:
var oldTrackPushEntity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ??
throw new BusinessException(message: _stringLocalizer["NotFindData"]);
ObjectMapper.Map(input, oldTrackPushEntity);
await _trackPushConfigRepository.UpdateAsync(oldTrackPushEntity);
await _trackPushCacheService.SetPushContentConfigsAsync(oldTrackPushEntity.SubSystemId,
oldTrackPushEntity.CustomId);
break;
case OptionTypeNoNull.删除:
var entity = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == input.Id) ??
throw new BusinessException(message: _stringLocalizer["NotFindData"]);
await _trackPushConfigRepository.SoftDeleteAsync(x => x.Id == input.Id);
await _trackPushConfigRepository.SoftDeleteContentAsync(x => x.TrackPushConfigId == input.Id);
await _trackPushCacheService.SetPushContentConfigsAsync(entity.SubSystemId, entity.CustomId);
break;
default:
throw new BusinessException(message: _stringLocalizer[SjzyBasicLocalization.Validation_IsInEnum,
nameof(EditTrackPushConfigInput.Options)]);
}
ts.Complete();
return msg;
}
/// <summary>
/// 获取服务商code根据客户id
/// </summary>
/// <param name="customerId"></param>
/// <returns></returns>
[HttpGet("GetServiceCodeByCustomerId")]
public async Task<string?> GetServiceCodeByCustomerId(int customerId)
{
return await _trackPushConfigRepository.GetServiceCodeByCustomerIdAsync(customerId);
}
/// <summary>
/// 轨迹推送配置内容编辑
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("EditContent")]
public async Task<bool> EditContentAsync([FromBody] EditTrackPushContentInput input)
{
if (input.Options != OptionTypeNoNull.删除)
{
Expression<Func<TrackPushContentConfigEntity, bool>> isContentAnyExp = x =>
x.TrackPushConfigId == input.TrackPushConfigId
&& x.OrderNoType == input.OrderNoType;
if (input.Options == OptionTypeNoNull.修改) isContentAnyExp = isContentAnyExp.And(x => x.Id != input.Id);
if (await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x =>
x.TrackContentId == input.TrackContentId)))
throw new BusinessException(message: _stringLocalizer["IsTrackPushContentAny"]);
if (!input.TrackContentCodeValue.IsNullOrWhiteSpace() &&
await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x =>
x.TrackContentCodeValue == input.TrackContentCodeValue)))
throw new BusinessException(message: _stringLocalizer["IsTrackPushContentCodeValueAny"]);
if (!input.TrackStatusValue.IsNullOrWhiteSpace() &&
await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x =>
x.TrackStatusValue == input.TrackStatusValue)))
throw new BusinessException(message: _stringLocalizer["IsTrackPushContentStatusValueAny"]);
if (!input.TrackContentValue.IsNullOrWhiteSpace() &&
await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x =>
x.TrackContentValue == input.TrackContentValue)))
throw new BusinessException(message: _stringLocalizer["IsTrackPushContentValueAny"]);
if (!input.TrackEnContentValue.IsNullOrWhiteSpace() &&
await _trackPushConfigRepository.IsContentAnyAsync(isContentAnyExp.And(x =>
x.TrackEnContentValue == input.TrackEnContentValue)))
throw new BusinessException(message: _stringLocalizer["IsTrackPushEnContentValueAny"]);
}
var trackPushConfigId = input.TrackPushConfigId;
using var ts = TransactionScopeHelper.Create();
TrackPushContentConfigEntity? oldContentConfig = null;
TrackPushContentConfigEntity? postContentConfig = null;
switch (input.Options)
{
case OptionTypeNoNull.新增:
{
var maxSort = await _trackPushConfigRepository.ContentMaxAsync(x => x.Sort, x =>
x.OrderNoType == input.OrderNoType
&& x.TrackPushConfigId == input.TrackPushConfigId
);
var entity = ObjectMapper.Map<EditTrackPushContentInput, TrackPushContentConfigEntity>(input);
entity.Sort = maxSort + 1;
await _trackPushConfigRepository.InsertContentAsync(entity);
break;
}
case OptionTypeNoNull.修改:
{
var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ??
throw new BusinessException(message: _stringLocalizer["NotFindData"]);
oldContentConfig = entity.DeepCopy();
ObjectMapper.Map(input, entity);
await _trackPushConfigRepository.UpdateContentAsync(entity);
postContentConfig = entity;
break;
}
case OptionTypeNoNull.删除:
{
var entity = await _trackPushConfigRepository.GetContentByIdAsync(input.Id!.Value) ??
throw new BusinessException(message: _stringLocalizer["NotFindData"]);
oldContentConfig = entity;
trackPushConfigId = entity.TrackPushConfigId;
await _trackPushConfigRepository.SoftDeleteContentAsync(x => x.Id == input.Id);
await _trackPushConfigRepository.UpdateContentAsync(x => x.Sort == x.Sort - 1, x =>
x.OrderNoType == entity.OrderNoType
&& x.TrackPushConfigId == entity.TrackPushConfigId
&& x.Sort > entity.Sort
);
break;
}
default:
throw new BusinessException(message: _stringLocalizer[SjzyBasicLocalization.Validation_IsInEnum,
nameof(EditTrackPushContentInput.Options)]);
}
var pushConfig = await _trackPushConfigRepository.GetFirstAsync(x => x.Id == trackPushConfigId);
if (pushConfig != null)
{
await _trackPushCacheService.SetPushContentConfigsAsync(pushConfig.SubSystemId, pushConfig.CustomId);
}
ts.Complete();
// 引发预警计算
WarningCalc_PushContentConfigChanged(pushConfig, oldContentConfig, postContentConfig);
return true;
}
/// <summary>
/// 轨迹推送配置内容排序
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("SortContent")]
public async Task<bool> SortContentAsync([FromBody] SortTrackPushContentInput input)
{
var ids = input.SortInfo.Select(x => int.Parse(x.Key)).ToList();
var trackPushContentEntities = await _trackPushConfigRepository.GetContentListAsync(x => ids.Contains(x.Id));
trackPushContentEntities.ForEach(item => { item.Sort = input.SortInfo.Single(x => x.Key == item.Id.ToString()).Value; });
if (trackPushContentEntities.Count > 0)
{
using var ts = TransactionScopeHelper.Create();
await _trackPushConfigRepository.UpdateContentRangeAsync(trackPushContentEntities);
var pushConfig = await _trackPushConfigRepository.GetFirstAsync(
x => x.Id == trackPushContentEntities[0].TrackPushConfigId,
y => new
{
y.SubSystemId,
y.CustomId
});
if (pushConfig != null)
{
await _trackPushCacheService.SetPushContentConfigsAsync(pushConfig.SubSystemId, pushConfig.CustomId);
}
ts.Complete();
}
return true;
}
private void WarningCalc_PushContentConfigChanged(TrackPushConfigEntity? pushConfig, TrackPushContentConfigEntity? oldContentConfig, TrackPushContentConfigEntity? postContentConfig)
{
// 推送配置主体不存在?
if (pushConfig == null) return;
// 说明是新增
if (oldContentConfig == null) return;
// 删除 postContentConfig == null 否则为更新(tips:判断更新差异化比较?)
var contentConfigEntity = postContentConfig ?? oldContentConfig;
_ = Task.Run(async () =>
{
var scope = _serviceProvider.CreateScope();
try
{
var handler = scope.ServiceProvider.GetRequiredService<IReturnWarningHandler>();
await handler.PushConfigChangedHandleAsync(pushConfig, contentConfigEntity);
}
catch (Exception ex)
{
LogHelper.Error(ex);
}
finally
{
scope.Dispose();
}
});
}
private static (bool Success, string Message) CheckDateTimeFormat(string? dateTimeFormat, int? dateTimeFormatType, string? timezoneFormat)
{
const int defaultTimeZone = 8;
var dateTime = DateTime.Now;
string dateStr;
try
{
if (dateTimeFormatType == (int) DateTimeFormatEnum.Timestamp)
{
dateStr = DateTimeHelper.ConvertToUnixTimestamp(dateTime).ToString();
return (true, $"格式化样例:{dateStr}");
}
if (dateTimeFormatType == (int) DateTimeFormatEnum.DateTimeAndTimezone)
{
// 没时间有时区,出错
if (string.IsNullOrWhiteSpace(dateTimeFormat) && !string.IsNullOrWhiteSpace(timezoneFormat))
return (false, "如果填写了时区格式,那么时间格式是必须的");
// 只有时间
if (!string.IsNullOrWhiteSpace(dateTimeFormat) && string.IsNullOrWhiteSpace(timezoneFormat))
{
var datetimeStr = DateTimeHelper.FormatDateTime(dateTime, dateTimeFormat);
return (true, $"格式化样例:{datetimeStr}");
}
// 时间和时区同时存在
if (!string.IsNullOrWhiteSpace(dateTimeFormat) && !string.IsNullOrWhiteSpace(timezoneFormat))
{
var zoneStr = DateTimeHelper.TimezoneFormat(defaultTimeZone, timezoneFormat);
var datetimeStr = DateTimeHelper.FormatDateTime(dateTime, dateTimeFormat);
dateStr = $"{datetimeStr} {zoneStr}";
return (true, $"格式化样例:{dateStr}");
}
}
}
catch (Exception e)
{
return (false, $"时间格式错误请检查:{e.Message}");
}
// 默认情况
dateTimeFormat ??= "yyyy-MM-ddTHH:mm:ss.fffK";
dateStr = dateTime.ToString(dateTimeFormat);
return (true, $"格式化样例:{dateStr}");
}
}