From ae4e733a71c45bac8c81ff6ef47f0383200f6a72 Mon Sep 17 00:00:00 2001 From: zzh <1368735060@qq.com> Date: Wed, 7 Oct 2026 17:34:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20KPI=20=E5=88=86=E5=8C=BA=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=94=AF=E6=8C=81=E5=A2=9E=E9=87=8F/=E5=85=A8?= =?UTF-8?q?=E9=87=8F=EF=BC=8C=E5=88=A0=E9=99=A4=E5=88=86=E5=8C=BA=E7=BA=A7?= =?UTF-8?q?=E8=81=94=E6=98=8E=E7=BB=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../Dtos/Channels/KpiAreaInfoImportInput.cs | 11 +++++++ .../Services/Channels/KpiAreaService.cs | 29 +++++++++++++++++-- .../Repositories/IKpiAreaRepository.cs | 2 ++ .../Channels/KpiAreaRepository.cs | 6 ++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/Oms.Application/Dtos/Channels/KpiAreaInfoImportInput.cs b/src/Oms.Application/Dtos/Channels/KpiAreaInfoImportInput.cs index a2e5388..a65be92 100644 --- a/src/Oms.Application/Dtos/Channels/KpiAreaInfoImportInput.cs +++ b/src/Oms.Application/Dtos/Channels/KpiAreaInfoImportInput.cs @@ -12,8 +12,19 @@ public class KpiAreaInfoImportInput /// public int AreaId { get; set; } + /// + /// 导入模式:incremental=增量(跳过重复);full=全量(先清空本分区明细再导入)。 + /// + public string ImportMode { get; set; } = ImportModes.Incremental; + /// /// Excel 文件。 /// public IFormFile File { get; set; } = null!; + + public static class ImportModes + { + public const string Incremental = "incremental"; + public const string Full = "full"; + } } diff --git a/src/Oms.Application/Services/Channels/KpiAreaService.cs b/src/Oms.Application/Services/Channels/KpiAreaService.cs index ff902a5..95f6061 100644 --- a/src/Oms.Application/Services/Channels/KpiAreaService.cs +++ b/src/Oms.Application/Services/Channels/KpiAreaService.cs @@ -91,6 +91,7 @@ public class KpiAreaService : ApplicationService public async Task DeleteAsync(IdInput input) { var entity = await GetAreaOrThrowAsync(input.Id); + await KpiAreaRepository.DeleteInfosByAreaIdAsync(entity.Id); await KpiAreaRepository.DeleteAsync(entity); } @@ -203,6 +204,7 @@ public class KpiAreaService : ApplicationService } await GetAreaOrThrowAsync(input.AreaId); + var importMode = NormalizeImportMode(input.ImportMode); await using var stream = input.File.OpenReadStream(); var parsedRows = await KpiAreaInfoImportHelper.ParseImportRowsAsync(stream); @@ -218,9 +220,16 @@ public class KpiAreaService : ApplicationService .ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); var existingKeys = new HashSet(StringComparer.Ordinal); - foreach (var item in await KpiAreaRepository.GetAllInfosByAreaIdAsync(input.AreaId)) + if (importMode == KpiAreaInfoImportInput.ImportModes.Full) { - TryAddDuplicateKey(existingKeys, item); + await KpiAreaRepository.DeleteInfosByAreaIdAsync(input.AreaId); + } + else + { + foreach (var item in await KpiAreaRepository.GetAllInfosByAreaIdAsync(input.AreaId)) + { + TryAddDuplicateKey(existingKeys, item); + } } var output = new KpiAreaInfoImportOutput(); @@ -236,7 +245,9 @@ public class KpiAreaService : ApplicationService output.Failures.Add(new KpiAreaInfoImportFailRow { RowNumber = rowNumber, - Reason = "与已有规则重复,已跳过" + Reason = importMode == KpiAreaInfoImportInput.ImportModes.Full + ? "文件内规则重复,已跳过" + : "与已有规则重复,已跳过" }); continue; } @@ -258,6 +269,18 @@ public class KpiAreaService : ApplicationService return output; } + private static string NormalizeImportMode(string? mode) + { + if (string.Equals(mode, KpiAreaInfoImportInput.ImportModes.Full, StringComparison.OrdinalIgnoreCase) + || string.Equals(mode, "全量", StringComparison.OrdinalIgnoreCase) + || string.Equals(mode, "replace", StringComparison.OrdinalIgnoreCase)) + { + return KpiAreaInfoImportInput.ImportModes.Full; + } + + return KpiAreaInfoImportInput.ImportModes.Incremental; + } + private static Expression> BuildAreaPredicate(KpiAreaListInput input) { var appKey = input.AppKey?.Trim(); diff --git a/src/Oms.Domain/ChannelsAggregate/Repositories/IKpiAreaRepository.cs b/src/Oms.Domain/ChannelsAggregate/Repositories/IKpiAreaRepository.cs index 57db116..6dce96b 100644 --- a/src/Oms.Domain/ChannelsAggregate/Repositories/IKpiAreaRepository.cs +++ b/src/Oms.Domain/ChannelsAggregate/Repositories/IKpiAreaRepository.cs @@ -21,5 +21,7 @@ public interface IKpiAreaRepository : IRepository, IKpiAreaPublishRepos Task DeleteInfoAsync(int id, CancellationToken cancellationToken = default); + Task DeleteInfosByAreaIdAsync(int areaId, CancellationToken cancellationToken = default); + Task> GetAllInfosByAreaIdAsync(int areaId, CancellationToken cancellationToken = default); } diff --git a/src/Oms.SqlSugarCore/Channels/KpiAreaRepository.cs b/src/Oms.SqlSugarCore/Channels/KpiAreaRepository.cs index 1099272..b06e0e4 100644 --- a/src/Oms.SqlSugarCore/Channels/KpiAreaRepository.cs +++ b/src/Oms.SqlSugarCore/Channels/KpiAreaRepository.cs @@ -57,6 +57,12 @@ public class KpiAreaRepository : OmsSqlSugarRepository, IKpiAreaReposit await db.Deleteable().Where(x => x.Id == id).ExecuteCommandAsync(cancellationToken); } + public async Task DeleteInfosByAreaIdAsync(int areaId, CancellationToken cancellationToken = default) + { + var db = await GetDbContextAsync(cancellationToken); + await db.Deleteable().Where(x => x.AreaId == areaId).ExecuteCommandAsync(cancellationToken); + } + public async Task> GetAllInfosByAreaIdAsync(int areaId, CancellationToken cancellationToken = default) { var db = await GetDbContextAsync(cancellationToken);