Merge branch 'S06' into test
This commit is contained in:
commit
d7925b09ea
@ -1,5 +1,8 @@
|
|||||||
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
namespace SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 支持模板,传入时区补正,按轨迹发生时间升序降序
|
||||||
|
/// </summary>
|
||||||
public class GetTrackInput : OrderNosInfo
|
public class GetTrackInput : OrderNosInfo
|
||||||
{
|
{
|
||||||
private float? _timeZone;
|
private float? _timeZone;
|
||||||
@ -8,16 +11,28 @@ public class GetTrackInput : OrderNosInfo
|
|||||||
/// 时区 +8 +8.25 -8.5 -9
|
/// 时区 +8 +8.25 -8.5 -9
|
||||||
/// 不传默认+8
|
/// 不传默认+8
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float? TimeZone
|
public float? TimeZone { get => _timeZone ?? 8; set => _timeZone = value; }
|
||||||
{
|
|
||||||
get => _timeZone ?? 8;
|
|
||||||
set => _timeZone = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 排序方式,默认按轨迹发生时间降序
|
/// 排序方式,默认按轨迹发生时间降序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SortMethod? SortMethod { get; set; }
|
public SortMethod? SortMethod { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 轨迹模板代码
|
||||||
|
/// </summary>
|
||||||
|
public string? TrackTemplateCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不支持模板,无时区补正,按轨迹发生时间升序降序
|
||||||
|
/// </summary>
|
||||||
|
public class GetTrackInputV2 : OrderNosInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 排序方式,默认按轨迹发生时间降序
|
||||||
|
/// </summary>
|
||||||
|
public SortMethod? SortMethod { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SortMethod
|
public enum SortMethod
|
||||||
@ -25,10 +40,20 @@ public enum SortMethod
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按轨迹发生时间排序
|
/// 按轨迹发生时间排序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ByTrackTime,
|
ByTrackTime = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按轨迹发生时间降序
|
/// 按轨迹发生时间降序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ByTrackTimeDesc,
|
ByTrackTimeDesc = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模板排序+轨迹发生时间
|
||||||
|
/// </summary>
|
||||||
|
ByTemplateAndTrackTime = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模板排序+轨迹发生时间
|
||||||
|
/// </summary>
|
||||||
|
ByTemplateAndTrackTimeDesc = 3
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
<Version>7.0.10</Version>
|
<Version>7.0.11</Version>
|
||||||
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
<GenerateDocumentationFile>True</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -4,10 +4,10 @@ using Volo.Abp.DependencyInjection;
|
|||||||
|
|
||||||
namespace SJZY.Track.Application.Contract.Services;
|
namespace SJZY.Track.Application.Contract.Services;
|
||||||
|
|
||||||
public interface IBroadcastingService :ITransientDependency
|
public interface IBroadcastingService : ITransientDependency
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 轨迹变更广播
|
/// 轨迹变更广播(新增/修改)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eto"></param>
|
/// <param name="eto"></param>
|
||||||
/// <param name="subSystemCode"></param>
|
/// <param name="subSystemCode"></param>
|
||||||
@ -15,7 +15,15 @@ public interface IBroadcastingService :ITransientDependency
|
|||||||
void TrackChangePublicTopicAsync(TrackUpsertEvent eto, string subSystemCode, string trackStatusCode);
|
void TrackChangePublicTopicAsync(TrackUpsertEvent eto, string subSystemCode, string trackStatusCode);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 轨迹推送完成广播
|
/// 轨迹变更广播(删除)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eto"></param>
|
||||||
|
/// <param name="subSystemCode"></param>
|
||||||
|
/// <param name="trackStatusCode"></param>
|
||||||
|
void TrackChangePublicTopicAsync(TrackDeleteEvent eto, OrderIdentifier[] orderIdentifiers, string trackCode, string trackStatusCode, string subSystemCode);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 轨迹推送完成广播(推送完成回调)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="log"></param>
|
/// <param name="log"></param>
|
||||||
void TrackPushCompletedPublicTopicAsync(TrackPushRecordDto log);
|
void TrackPushCompletedPublicTopicAsync(TrackPushRecordDto log);
|
||||||
|
|||||||
@ -35,8 +35,17 @@ public interface ITrackService : IRemoteService
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据订单号获取轨迹
|
/// 根据订单号获取轨迹
|
||||||
|
/// 支持模板,传入时区补正,按轨迹发生时间升序降序
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<UnifyResultDto<List<GetTrackOutput>>> QueryAsync(GetTrackInput input);
|
Task<UnifyResultDto<List<GetTrackOutput>>> QueryAsync(GetTrackInput input);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据订单号获取轨迹
|
||||||
|
/// 不支持模板,无时区补正,可按轨迹发生时间升序降序
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<UnifyResultDto<List<GetTrackOutput>>> QueryV2Async(GetTrackInputV2 input);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,11 @@
|
|||||||
using System.Text;
|
|
||||||
using BSI.Stack.Rabbit;
|
|
||||||
using DotNetCore.CAP;
|
using DotNetCore.CAP;
|
||||||
using SJZY.Expand.ABP.Core.Logger;
|
using SJZY.Expand.ABP.Core.Logger;
|
||||||
using SJZY.Expand.ABP.Core.PublicMethords;
|
using SJZY.Expand.ABP.Core.PublicMethords;
|
||||||
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
||||||
using SJZY.Track.Application.Contract.Events;
|
using SJZY.Track.Application.Contract.Events;
|
||||||
|
using SJZY.Track.Application.Contract.Services;
|
||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
|
|
||||||
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
|
|
||||||
using SJZY.Track.Domain.Enums;
|
using SJZY.Track.Domain.Enums;
|
||||||
using SJZY.Track.Domain.Queries;
|
using SJZY.Track.Domain.Queries;
|
||||||
using Volo.Abp.DependencyInjection;
|
using Volo.Abp.DependencyInjection;
|
||||||
@ -21,27 +18,21 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
|
private readonly IOrderOperationRecordEsRepository _orderOperationRecordEsRepository;
|
||||||
private readonly IOrderRepository _orderRepository;
|
private readonly IOrderRepository _orderRepository;
|
||||||
private readonly IProvideQueries _provideQueries;
|
private readonly IProvideQueries _provideQueries;
|
||||||
private readonly RabbitClientBus _rabbitClientBus;
|
|
||||||
private readonly ITrackContentRepository _trackContentRepository;
|
|
||||||
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
|
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
|
||||||
private readonly ITrackStatusRepository _trackStatusRepository;
|
private readonly IBroadcastingService _broadcastingService;
|
||||||
|
|
||||||
public TrackDeleteEventHandler(IProvideQueries provideQueries,
|
public TrackDeleteEventHandler(IProvideQueries provideQueries,
|
||||||
IOrderRepository orderRepository, ICapPublisher capPublisher,
|
IOrderRepository orderRepository, ICapPublisher capPublisher,
|
||||||
ITrackDetailsEsRepository trackDetailsEsRepository,
|
ITrackDetailsEsRepository trackDetailsEsRepository,
|
||||||
RabbitClientBus rabbitClientBus,
|
IOrderOperationRecordEsRepository orderOperationRecordEsRepository,
|
||||||
ITrackStatusRepository trackStatusRepository,
|
IBroadcastingService broadcastingService)
|
||||||
ITrackContentRepository trackContentRepository,
|
|
||||||
IOrderOperationRecordEsRepository orderOperationRecordEsRepository)
|
|
||||||
{
|
{
|
||||||
_provideQueries = provideQueries;
|
_provideQueries = provideQueries;
|
||||||
_orderRepository = orderRepository;
|
_orderRepository = orderRepository;
|
||||||
_capPublisher = capPublisher;
|
_capPublisher = capPublisher;
|
||||||
_trackDetailsEsRepository = trackDetailsEsRepository;
|
_trackDetailsEsRepository = trackDetailsEsRepository;
|
||||||
_rabbitClientBus = rabbitClientBus;
|
|
||||||
_trackStatusRepository = trackStatusRepository;
|
|
||||||
_trackContentRepository = trackContentRepository;
|
|
||||||
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
|
_orderOperationRecordEsRepository = orderOperationRecordEsRepository;
|
||||||
|
_broadcastingService = broadcastingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)]
|
[CapSubscribe(GlobalConst.TrackDeleteSubscribe, Group = GlobalConst.TrackDeleteSubscribe)]
|
||||||
@ -51,8 +42,9 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
|
|
||||||
var trackList = await DeleteTrackAsync(@event);
|
var trackList = await DeleteTrackAsync(@event);
|
||||||
|
|
||||||
//发布事件
|
//当轨迹删除,根据轨迹标记/状态上IsToMq选择进行广播
|
||||||
await PublicTrackTopicAsync(@event, trackList);
|
if (trackList.Count != 0)
|
||||||
|
await PublicTrackTopicAsync(@event, trackList);
|
||||||
|
|
||||||
// 根据订单关联关系异步向下刷(异步)
|
// 根据订单关联关系异步向下刷(异步)
|
||||||
await DownByOrderLink(@event);
|
await DownByOrderLink(@event);
|
||||||
@ -128,48 +120,41 @@ public class TrackDeleteEventHandler : ITransientDependency, ICapSubscribe
|
|||||||
|
|
||||||
private async Task PublicTrackTopicAsync(TrackDeleteEvent eto, List<TrackDetailsIndex> trackList)
|
private async Task PublicTrackTopicAsync(TrackDeleteEvent eto, List<TrackDetailsIndex> trackList)
|
||||||
{
|
{
|
||||||
// // todo: review 这里查库太多了
|
var systemIds = trackList.Select(x => x.SubSystemId).Distinct().ToArray();
|
||||||
if (trackList == null)
|
var trackCodes = trackList.Select(x => x.TrackCode).Distinct().ToArray();
|
||||||
return;
|
|
||||||
|
|
||||||
var statusList = await _trackStatusRepository.GetListAsync(m => m.SubSystemId == eto.SubSystemId);
|
//从轨迹内容中查询出标记是否需要mq广播
|
||||||
if (statusList == null)
|
var contentList = await _provideQueries.GetTrackContentsAsync(systemIds, trackCodes);
|
||||||
return;
|
var toMqDict = contentList
|
||||||
|
.ToDictionary(x => x.SubSystemId + x.TrackContentCode, y => y.IsToMq);
|
||||||
|
|
||||||
var contentList = await _trackContentRepository.GetTrackContentBySyetemIdAsync(eto.SubSystemId);
|
//选出需要广播的轨迹,并按code和订单号分组
|
||||||
if (contentList == null)
|
var trackGroup = trackList
|
||||||
return;
|
.Where(x => toMqDict[x.SubSystemId + x.TrackCode])
|
||||||
|
.GroupBy(m => new
|
||||||
|
{
|
||||||
|
m.TrackCode,
|
||||||
|
m.OrderNo
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
if (trackGroup.Count == 0) return;
|
||||||
|
|
||||||
foreach (var dataItem in trackList.GroupBy(m => new
|
foreach (var dataItem in trackGroup)
|
||||||
{
|
|
||||||
m.TrackCode,
|
|
||||||
m.OrderNo
|
|
||||||
}))
|
|
||||||
{
|
{
|
||||||
var item = dataItem.First();
|
var item = dataItem.First();
|
||||||
var status = statusList.FirstOrDefault(m => m.Code == item.TrackStatusCode);
|
var content = contentList.First(m => m.TrackContentCode == item.TrackCode);
|
||||||
if (status == null || !status.IsToMq)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var content = contentList.FirstOrDefault(m => m.TrackContentCode == item.TrackCode);
|
_broadcastingService.TrackChangePublicTopicAsync(eto,
|
||||||
|
dataItem.Select(m => new OrderIdentifier
|
||||||
var data = new TrackChangeEto()
|
|
||||||
{
|
|
||||||
OrderIdentifiers = dataItem.Select(m => new OrderIdentifier
|
|
||||||
{
|
{
|
||||||
OrderId = m.OrderId,
|
OrderId = m.OrderId,
|
||||||
OrderNo = m.OrderNo,
|
OrderNo = m.OrderNo,
|
||||||
OrderType = m.OrderType
|
OrderType = m.OrderType
|
||||||
}).ToArray(),
|
}).ToArray(),
|
||||||
TrackStatusCode = item.TrackStatusCode,
|
item.TrackCode,
|
||||||
TrackCode = item.TrackCode,
|
item.TrackStatusCode,
|
||||||
OperationMan = eto.OperationMan,
|
content.SubSystemCode
|
||||||
SubSystemId = eto.SubSystemId,
|
);
|
||||||
Option = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
_rabbitClientBus.Publish(GlobalConst.TrackChangeExchange, $"TrackChange.{content.SubSystemCode}",
|
|
||||||
Encoding.UTF8.GetBytes(data.ToJson()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -65,6 +65,22 @@ public class BroadcastingService : IBroadcastingService
|
|||||||
Encoding.UTF8.GetBytes(data.ToJson()));
|
Encoding.UTF8.GetBytes(data.ToJson()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TrackChangePublicTopicAsync(TrackDeleteEvent eto, OrderIdentifier[] orderIdentifiers, string trackCode, string trackStatusCode, string subSystemCode)
|
||||||
|
{
|
||||||
|
var data = new TrackChangeEto
|
||||||
|
{
|
||||||
|
OrderIdentifiers = orderIdentifiers,
|
||||||
|
TrackStatusCode = trackStatusCode,
|
||||||
|
TrackCode = trackCode,
|
||||||
|
OperationMan = eto.OperationMan,
|
||||||
|
SubSystemId = eto.SubSystemId,
|
||||||
|
Option = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
_rabbitClientBus.Publish(GlobalConst.TrackChangeExchange, $"TrackChange.{subSystemCode}",
|
||||||
|
Encoding.UTF8.GetBytes(data.ToJson()));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 轨迹推送完成广播
|
/// 轨迹推送完成广播
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
using SJZY.Track.Application.Contract.Dtos.ProvideServices;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
||||||
|
using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate;
|
||||||
|
using SJZY.Track.Domain.Dtos.TrackTemplate;
|
||||||
|
|
||||||
namespace SJZY.Track.Application.Services.ProvideServices;
|
namespace SJZY.Track.Application.Services.ProvideServices;
|
||||||
|
|
||||||
@ -9,6 +11,7 @@ namespace SJZY.Track.Application.Services.ProvideServices;
|
|||||||
public partial class TrackService
|
public partial class TrackService
|
||||||
{
|
{
|
||||||
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
|
private readonly ITrackDetailsEsRepository _trackDetailsEsRepository;
|
||||||
|
private readonly ITrackTemplateRepository _trackTemplateRepository;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询轨迹
|
/// 查询轨迹
|
||||||
@ -63,13 +66,13 @@ public partial class TrackService
|
|||||||
? null
|
? null
|
||||||
: input.TimeZone ?? 8,
|
: input.TimeZone ?? 8,
|
||||||
IsDisplay = trackContentDic.TryGetValue(x.TrackCode, out var isExternal) && isExternal,
|
IsDisplay = trackContentDic.TryGetValue(x.TrackCode, out var isExternal) && isExternal,
|
||||||
IsVisibility = x.IsVisibility,
|
IsVisibility = x.IsVisibility,
|
||||||
Source = x.Source,
|
Source = x.Source,
|
||||||
Remarks = x.Remarks,
|
Remarks = x.Remarks,
|
||||||
Files = x.Files?.Select(y => new FileItemDto
|
Files = x.Files?.Select(y => new FileItemDto
|
||||||
{
|
{
|
||||||
FileName = y.FileName,
|
FileName = y.FileName,
|
||||||
OssKey = y.OssKey
|
OssKey = y.OssKey
|
||||||
}).ToList(),
|
}).ToList(),
|
||||||
TrackPlaceCity = x.TrackPlaceCity,
|
TrackPlaceCity = x.TrackPlaceCity,
|
||||||
TrackPlaceCityId = x.TrackPlaceCityId,
|
TrackPlaceCityId = x.TrackPlaceCityId,
|
||||||
@ -87,25 +90,240 @@ public partial class TrackService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
TracksOrdered(res, input);
|
var sortedList = await TracksOrdered(res, input);
|
||||||
|
|
||||||
return new UnifyResultDto<List<GetTrackOutput>>(true, res, "操作成功");
|
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TracksOrdered(List<GetTrackOutput> list, GetTrackInput input)
|
|
||||||
|
[HttpPost("Track/QueryV2")]
|
||||||
|
public async Task<UnifyResultDto<List<GetTrackOutput>>> QueryV2Async(GetTrackInputV2 input)
|
||||||
|
{
|
||||||
|
var res = new List<GetTrackOutput>();
|
||||||
|
input.OrderNos = input.OrderNos.Where(x => !x.IsNullOrWhiteSpace()).Distinct().ToList(); // 单号去重、去空
|
||||||
|
|
||||||
|
var details = await _trackDetailsEsRepository.GetListAsync(input.SubSystemId, input.OrderType, input.OrderNos);
|
||||||
|
|
||||||
|
// 是否对外
|
||||||
|
var trackCodes = details.Select(x => x.TrackCode)
|
||||||
|
.Where(x => x != GlobalConst.EmptyString)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var trackContentDic = new Dictionary<string, bool>();
|
||||||
|
if (!trackCodes.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
var trackContents = await _trackContentRepository.GetListAsync(x =>
|
||||||
|
x.SubSystemId == input.SubSystemId && trackCodes.Contains(x.Code),
|
||||||
|
x => new
|
||||||
|
{
|
||||||
|
x.Code,
|
||||||
|
x.IsExternal
|
||||||
|
});
|
||||||
|
trackContents.ForEach(x => trackContentDic.Add(x.Code, x.IsExternal));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var group in details.GroupBy(x => x.OrderId))
|
||||||
|
{
|
||||||
|
var item = new GetTrackOutput();
|
||||||
|
var trackDetails = group.ToList();
|
||||||
|
item.OrderNo = trackDetails.First().OrderNo;
|
||||||
|
|
||||||
|
item.TrackDetails = trackDetails.Select(x => new TrackDetail
|
||||||
|
{
|
||||||
|
Code = x.TrackCode,
|
||||||
|
Status = x.TrackStatus,
|
||||||
|
Content = x.TrackContent,
|
||||||
|
OriginContent = x.OriginTrackContent,
|
||||||
|
Location = x.TrackPlace,
|
||||||
|
Time = x.TrackTime,
|
||||||
|
TimeZone = x.TrackTimeZone,
|
||||||
|
IsDisplay = trackContentDic.TryGetValue(x.TrackCode, out var isExternal) && isExternal,
|
||||||
|
IsVisibility = x.IsVisibility,
|
||||||
|
Source = x.Source,
|
||||||
|
Remarks = x.Remarks,
|
||||||
|
Files = x.Files?.Select(y => new FileItemDto
|
||||||
|
{
|
||||||
|
FileName = y.FileName,
|
||||||
|
OssKey = y.OssKey
|
||||||
|
}).ToList(),
|
||||||
|
TrackPlaceCity = x.TrackPlaceCity,
|
||||||
|
TrackPlaceCityId = x.TrackPlaceCityId,
|
||||||
|
TrackPlaceProvince = x.TrackPlaceProvince,
|
||||||
|
TrackPlaceProvinceId = x.TrackPlaceProvinceId,
|
||||||
|
TrackPlaceNation = x.TrackPlaceNation,
|
||||||
|
TrackPlaceNationId = x.TrackPlaceNationId,
|
||||||
|
TrackPlacePostcode = x.TrackPlacePostcode,
|
||||||
|
DestinationTimeZone = x.DestinationTimeZone,
|
||||||
|
EstimatedDeliveryDate = x.EstimatedDeliveryDate,
|
||||||
|
Extra = x.Extra
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
res.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
var sortedList = await TracksOrdered(res, input);
|
||||||
|
|
||||||
|
return new UnifyResultDto<List<GetTrackOutput>>(true, sortedList, "操作成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<List<GetTrackOutput>> TracksOrdered(List<GetTrackOutput> list, GetTrackInput input)
|
||||||
{
|
{
|
||||||
switch (input.SortMethod)
|
switch (input.SortMethod)
|
||||||
{
|
{
|
||||||
case SortMethod.ByTrackTime:
|
case SortMethod.ByTrackTime:
|
||||||
|
case SortMethod.ByTemplateAndTrackTime:
|
||||||
// tips:quick-sort 直接修改原list
|
// tips:quick-sort 直接修改原list
|
||||||
list.ForEach(item => item.TrackDetails.Sort((a, b) => a.Time.CompareTo(b.Time)));
|
list.ForEach(item => item.TrackDetails.Sort((a, b) => a.Time.CompareTo(b.Time)));
|
||||||
break;
|
break;
|
||||||
case null:
|
case null:
|
||||||
case SortMethod.ByTrackTimeDesc:
|
case SortMethod.ByTrackTimeDesc:
|
||||||
|
case SortMethod.ByTemplateAndTrackTimeDesc:
|
||||||
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(input.SortMethod), input.SortMethod, "不支持的排序方式");
|
throw new ArgumentOutOfRangeException(nameof(input.SortMethod), input.SortMethod, "不支持的排序方式");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (input.SortMethod != SortMethod.ByTemplateAndTrackTime
|
||||||
|
&& input.SortMethod != SortMethod.ByTemplateAndTrackTimeDesc)
|
||||||
|
{
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//查出订单模板
|
||||||
|
var templates = await _trackTemplateRepository.GetTrackTemplateListAsync(new GetTrackTemplateListInputVo
|
||||||
|
{
|
||||||
|
SubSystemId = input.SubSystemId,
|
||||||
|
TemplateCode = input.TrackTemplateCode
|
||||||
|
});
|
||||||
|
|
||||||
|
if (templates.Count == 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException("轨迹模板不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var getTrackOutput in list)
|
||||||
|
{
|
||||||
|
getTrackOutput.TrackDetails = SortByTemplate(getTrackOutput.TrackDetails, templates, input.SortMethod.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<List<GetTrackOutput>> TracksOrdered(List<GetTrackOutput> list, GetTrackInputV2 input)
|
||||||
|
{
|
||||||
|
switch (input.SortMethod)
|
||||||
|
{
|
||||||
|
case SortMethod.ByTrackTime:
|
||||||
|
case SortMethod.ByTemplateAndTrackTime:
|
||||||
|
// tips:quick-sort 直接修改原list
|
||||||
|
list.ForEach(item => item.TrackDetails.Sort((a, b) => a.Time.CompareTo(b.Time)));
|
||||||
|
break;
|
||||||
|
case null:
|
||||||
|
case SortMethod.ByTrackTimeDesc:
|
||||||
|
case SortMethod.ByTemplateAndTrackTimeDesc:
|
||||||
|
list.ForEach(item => item.TrackDetails.Sort((a, b) => b.Time.CompareTo(a.Time)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(input.SortMethod), input.SortMethod, "不支持的排序方式");
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//按模板排序
|
||||||
|
private static List<TrackDetail> SortByTemplate(List<TrackDetail> tracks, List<TrackTemplateOutputVo> templates, SortMethod sortMethod)
|
||||||
|
{
|
||||||
|
if (templates.Count == 0 ||
|
||||||
|
tracks.Count == 0)
|
||||||
|
{
|
||||||
|
return new List<TrackDetail>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var isAsc = sortMethod == SortMethod.ByTemplateAndTrackTime;
|
||||||
|
|
||||||
|
var allTemplateCodes = new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var template in templates)
|
||||||
|
{
|
||||||
|
tracks = Sort(tracks, template, isAsc, allTemplateCodes);
|
||||||
|
}
|
||||||
|
// tracks = templates.Aggregate(tracks,
|
||||||
|
// (current, template) => Sort(current, template, isAsc, allTemplateCodes));
|
||||||
|
|
||||||
|
return tracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<TrackDetail> Sort(List<TrackDetail> seq, TrackTemplateOutputVo template, bool isAsc = true, HashSet<string>? allTemplateCodes = null)
|
||||||
|
{
|
||||||
|
if (template.TemplateContents.Count == 0)
|
||||||
|
{
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个字典,用于存储排序序列中元素的索引
|
||||||
|
var sortDict = new Dictionary<TrackDetail, int>();
|
||||||
|
template.TemplateContents.Sort((x, y) => x.Sort.CompareTo(y.Sort));
|
||||||
|
var sortSeq = template.TemplateContents
|
||||||
|
.Select(x => seq.FirstOrDefault(y => y.Code == x.Code))
|
||||||
|
.Where(x => x != null)
|
||||||
|
.ToList();
|
||||||
|
for (var i = 0; i < sortSeq.Count; i++)
|
||||||
|
{
|
||||||
|
sortDict[sortSeq[i]!] = isAsc ? i : sortSeq.Count - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将模板code添加到上下文集合中
|
||||||
|
if (allTemplateCodes != null)
|
||||||
|
{
|
||||||
|
allTemplateCodes.UnionWith(template.TemplateContents.Select(x => x.Code));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据排序序列和字典中的索引对序列进行排序
|
||||||
|
// 使用稳定排序算法,如OrderBy,它保持相等元素的相对顺序
|
||||||
|
var sorted = seq.OrderBy(item => sortDict.GetValueOrDefault(item, int.MaxValue)).ToList();
|
||||||
|
|
||||||
|
// 存在
|
||||||
|
if (allTemplateCodes != null)
|
||||||
|
{
|
||||||
|
//查询到没有命中到模板的轨迹
|
||||||
|
var noTipTemplateTracks = sorted.Where(x => !allTemplateCodes.Contains(x.Code)).ToList();
|
||||||
|
|
||||||
|
//查询未命中轨迹的索引字典
|
||||||
|
var trackIdxDict = new Dictionary<TrackDetail, int>();
|
||||||
|
var trackSortDict = new SortedDictionary<int, TrackDetail>();
|
||||||
|
foreach (var track in noTipTemplateTracks)
|
||||||
|
{
|
||||||
|
trackIdxDict[track] = sorted.IndexOf(track);
|
||||||
|
trackSortDict[trackIdxDict[track]] = track;
|
||||||
|
}
|
||||||
|
|
||||||
|
//没有命中的轨迹排序
|
||||||
|
var noTipTemplateTrackSorted = (isAsc
|
||||||
|
? noTipTemplateTracks.OrderBy(x => x.Time)
|
||||||
|
: noTipTemplateTracks.OrderByDescending(x => x.Time))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
for (var i = 0; i < trackSortDict.Count; i++)
|
||||||
|
{
|
||||||
|
//在序列中的实际位置
|
||||||
|
var (idx, st) = trackSortDict.ElementAt(0);
|
||||||
|
//在这个位置它应该是哪个轨迹
|
||||||
|
var track = noTipTemplateTrackSorted[0];
|
||||||
|
//交换位置
|
||||||
|
if (track != st)
|
||||||
|
{
|
||||||
|
var idx2 = trackIdxDict[track];
|
||||||
|
sorted[idx2] = st;
|
||||||
|
sorted[idx] = track;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ using SJZY.Track.Application.Contract.Services.ProvideServices;
|
|||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackDetailsAggregate;
|
||||||
|
using SJZY.Track.Domain.Aggregates.TrackTemplateAggregate;
|
||||||
using SJZY.Track.Domain.Enums;
|
using SJZY.Track.Domain.Enums;
|
||||||
using SJZY.UserCenter.HttpApi.Services;
|
using SJZY.UserCenter.HttpApi.Services;
|
||||||
using SJZY.UserCenter.HttpApi.Services.User;
|
using SJZY.UserCenter.HttpApi.Services.User;
|
||||||
@ -26,12 +27,13 @@ public partial class TrackService : ApplicationService, ITrackService
|
|||||||
|
|
||||||
public TrackService(IOrderRepository orderRepository, ICapPublisher capPublisher,
|
public TrackService(IOrderRepository orderRepository, ICapPublisher capPublisher,
|
||||||
ITrackDetailsEsRepository trackDetailsEsRepository, ITrackContentRepository trackContentRepository,
|
ITrackDetailsEsRepository trackDetailsEsRepository, ITrackContentRepository trackContentRepository,
|
||||||
IHttpClientProxy<IUserBaseInfoService> requestCurrentUserService)
|
IHttpClientProxy<IUserBaseInfoService> requestCurrentUserService, ITrackTemplateRepository trackTemplateRepository)
|
||||||
{
|
{
|
||||||
_orderRepository = orderRepository;
|
_orderRepository = orderRepository;
|
||||||
_capPublisher = capPublisher;
|
_capPublisher = capPublisher;
|
||||||
_trackContentRepository = trackContentRepository;
|
_trackContentRepository = trackContentRepository;
|
||||||
_requestCurrentUserService = requestCurrentUserService;
|
_requestCurrentUserService = requestCurrentUserService;
|
||||||
|
_trackTemplateRepository = trackTemplateRepository;
|
||||||
_trackDetailsEsRepository = trackDetailsEsRepository;
|
_trackDetailsEsRepository = trackDetailsEsRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,8 @@ public interface ITrackDetailsEsRepository : IElasticsearchClientService<TrackDe
|
|||||||
Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes);
|
Task<List<int>> DeleteTrackAsync(int[] orderIds, List<string> trackCodes);
|
||||||
|
|
||||||
Task DeleteTrackByIdAsync(string id, string indexName);
|
Task DeleteTrackByIdAsync(string id, string indexName);
|
||||||
|
|
||||||
Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids);
|
Task<List<TrackDetailsIndex>> GetDataByIds(string[] ids);
|
||||||
|
|
||||||
Task<TrackDetailsIndex> GetDetailAsync(string orderNo, string trackCode, int orderType, int subSystemId, DateTime trackTime);
|
Task<TrackDetailsIndex> GetDetailAsync(string orderNo, string trackCode, int orderType, int subSystemId, DateTime trackTime);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
using SJZY.Track.Domain.Aggregates.OrderAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackContentAggregate;
|
||||||
|
using SJZY.Track.Domain.Aggregates.TrackFlagAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackPullAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackPullAggregate;
|
||||||
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
|
using SJZY.Track.Domain.Aggregates.TrackStatusAggregate;
|
||||||
using SJZY.Track.Domain.Dtos.Order;
|
using SJZY.Track.Domain.Dtos.Order;
|
||||||
@ -99,20 +100,22 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
|
|||||||
return await Context.Queryable<TrackContentEntity>()
|
return await Context.Queryable<TrackContentEntity>()
|
||||||
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
|
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
|
||||||
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
|
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
|
||||||
|
.LeftJoin<TrackFlagEntity>((x, y, z, k) => x.SubSystemId == k.SubSystemId && k.Code == x.Code)
|
||||||
.Where(x => x.SubSystemId == subSystemId && x.Code == trackCode)
|
.Where(x => x.SubSystemId == subSystemId && x.Code == trackCode)
|
||||||
.Select((x, y, z) => new TrackContentVO
|
.Select((x, y, z, k) => new TrackContentVO
|
||||||
{
|
{
|
||||||
SubSystemCode = z.Key,
|
SubSystemCode = z.Key,
|
||||||
TrackStatusId = x.TrackStatusId,
|
TrackStatusId = x.TrackStatusId,
|
||||||
TrackStatus = y.Status,
|
TrackStatus = y.Status,
|
||||||
TrackStatusCode = y.Code,
|
TrackStatusCode = y.Code,
|
||||||
|
TrackContentCode = x.Code,
|
||||||
TrackContent = x.Content,
|
TrackContent = x.Content,
|
||||||
TrackEnContent = x.EnContent,
|
TrackEnContent = x.EnContent,
|
||||||
IsCompleted = y.IsCompleted,
|
IsCompleted = y.IsCompleted,
|
||||||
IsRepeatable = x.IsRepeatable,
|
IsRepeatable = x.IsRepeatable,
|
||||||
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
|
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
|
||||||
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
|
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
|
||||||
IsToMq = y.IsToMq,
|
IsToMq = y.IsToMq || k.IsToMq,
|
||||||
})
|
})
|
||||||
.FirstAsync();
|
.FirstAsync();
|
||||||
}
|
}
|
||||||
@ -122,21 +125,23 @@ public class ProvideQueries : ISugarRepository, IProvideQueries, ITransientDepen
|
|||||||
return await Context.Queryable<TrackContentEntity>()
|
return await Context.Queryable<TrackContentEntity>()
|
||||||
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
|
.LeftJoin<TrackStatusEntity>((x, y) => x.TrackStatusId == y.Id)
|
||||||
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
|
.LeftJoin<VSystemEntity>((x, y, z) => x.SubSystemId == z.Id)
|
||||||
|
.LeftJoin<TrackFlagEntity>((x, y, z, k) => x.SubSystemId == k.SubSystemId && k.Code == x.Code)
|
||||||
.Where(x => subSystemIds.Contains(x.SubSystemId) && trackCodes.Contains(x.Code))
|
.Where(x => subSystemIds.Contains(x.SubSystemId) && trackCodes.Contains(x.Code))
|
||||||
.Select((x, y, z) => new TrackContentVO
|
.Select((x, y, z, k) => new TrackContentVO
|
||||||
{
|
{
|
||||||
SubSystemId = x.SubSystemId,
|
SubSystemId = x.SubSystemId,
|
||||||
SubSystemCode = z.Key,
|
SubSystemCode = z.Key,
|
||||||
TrackStatusId = x.TrackStatusId,
|
TrackStatusId = x.TrackStatusId,
|
||||||
TrackStatus = y.Status,
|
TrackStatus = y.Status,
|
||||||
TrackStatusCode = y.Code,
|
TrackStatusCode = y.Code,
|
||||||
|
TrackContentCode = x.Code,
|
||||||
TrackContent = x.Content,
|
TrackContent = x.Content,
|
||||||
TrackEnContent = x.EnContent,
|
TrackEnContent = x.EnContent,
|
||||||
IsCompleted = y.IsCompleted,
|
IsCompleted = y.IsCompleted,
|
||||||
IsRepeatable = x.IsRepeatable,
|
IsRepeatable = x.IsRepeatable,
|
||||||
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
|
IsAllowManuallyUpdate = x.IsAllowManuallyUpdate,
|
||||||
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
|
IsAllowManuallyCreate = x.IsAllowManuallyCreate,
|
||||||
IsToMq = y.IsToMq,
|
IsToMq = y.IsToMq || k.IsToMq,
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -430,7 +430,10 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
|
|||||||
q.Term(t => t.OrderId, orderId)
|
q.Term(t => t.OrderId, orderId)
|
||||||
)
|
)
|
||||||
.Size(SafelyLimit)
|
.Size(SafelyLimit)
|
||||||
.Sort(s => s.Field(f => f.ZeroTrackTime, SortOrder.Descending)));
|
.Sort(s => s
|
||||||
|
.Field(f => f.ZeroTrackTime, SortOrder.Descending)
|
||||||
|
.Field(f => f.CreateTime, SortOrder.Descending)
|
||||||
|
));
|
||||||
|
|
||||||
if (!r.IsValid)
|
if (!r.IsValid)
|
||||||
{
|
{
|
||||||
@ -463,7 +466,10 @@ public class TrackDetailsEsRepository : ElasticSearchContextAbstract<TrackDetail
|
|||||||
.Index(GlobalConst.TrackDetailsIndex)
|
.Index(GlobalConst.TrackDetailsIndex)
|
||||||
.Query(q => query)
|
.Query(q => query)
|
||||||
.Size(SafelyLimit)
|
.Size(SafelyLimit)
|
||||||
.Sort(s => s.Field(f => f.ZeroTrackTime, SortOrder.Descending)));
|
.Sort(s => s
|
||||||
|
.Field(f => f.ZeroTrackTime, SortOrder.Descending)
|
||||||
|
.Field(f => f.CreateTime, SortOrder.Descending))
|
||||||
|
);
|
||||||
|
|
||||||
if (!r.IsValid)
|
if (!r.IsValid)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user