feat: KPI分区明细列表支持表头字段后端筛选
All checks were successful
Build and Deploy / deploy (push) Successful in 1m22s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m22s
EOF Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b87414aafd
commit
8a4848644f
@ -19,4 +19,39 @@ public class KpiAreaInfoListInput
|
|||||||
/// 每页条数。
|
/// 每页条数。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int PageSize { get; set; }
|
public int PageSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 国家/地区(匹配国家名称或国家代码,模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匹配维度(如 zip/state/city/country,模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? MatchDim { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 匹配方式(如 prefix/exact/range/all,模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? MatchMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 州/省(模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? Province { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 城市(模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 起始邮编(模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? LeftPostcode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 截止邮编(模糊)。
|
||||||
|
/// </summary>
|
||||||
|
public string? RightPostcode { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,8 +106,9 @@ public class KpiAreaService : ApplicationService
|
|||||||
await GetAreaOrThrowAsync(input.AreaId);
|
await GetAreaOrThrowAsync(input.AreaId);
|
||||||
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
var pageIndex = OmsDocHelper.NormalizePage(input.Page);
|
||||||
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
||||||
var entities = await KpiAreaRepository.GetInfosAsync(input.AreaId, pageIndex, pageSize);
|
var filter = BuildInfoQueryFilter(input);
|
||||||
var total = await KpiAreaRepository.CountInfosAsync(input.AreaId);
|
var entities = await KpiAreaRepository.GetInfosAsync(input.AreaId, pageIndex, pageSize, filter);
|
||||||
|
var total = await KpiAreaRepository.CountInfosAsync(input.AreaId, filter);
|
||||||
return new OmsPageResult<KpiAreaInfoOutput>
|
return new OmsPageResult<KpiAreaInfoOutput>
|
||||||
{
|
{
|
||||||
Items = entities.Select(MapInfoOutput).ToList(),
|
Items = entities.Select(MapInfoOutput).ToList(),
|
||||||
@ -115,6 +116,18 @@ public class KpiAreaService : ApplicationService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static KpiAreaInfoQueryFilter BuildInfoQueryFilter(KpiAreaInfoListInput input) =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Country = input.Country,
|
||||||
|
MatchDim = input.MatchDim,
|
||||||
|
MatchMode = input.MatchMode,
|
||||||
|
Province = input.Province,
|
||||||
|
City = input.City,
|
||||||
|
LeftPostcode = input.LeftPostcode,
|
||||||
|
RightPostcode = input.RightPostcode
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 新增KPI分区明细。
|
/// 新增KPI分区明细。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -3,15 +3,37 @@ using Oms.Domain.ChannelsAggregate.Entities;
|
|||||||
|
|
||||||
namespace Oms.Domain.ChannelsAggregate.Repositories;
|
namespace Oms.Domain.ChannelsAggregate.Repositories;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// KPI 分区明细列表筛选条件(字段均为可选,模糊匹配)。
|
||||||
|
/// </summary>
|
||||||
|
public class KpiAreaInfoQueryFilter
|
||||||
|
{
|
||||||
|
public string? Country { get; set; }
|
||||||
|
public string? MatchDim { get; set; }
|
||||||
|
public string? MatchMode { get; set; }
|
||||||
|
public string? Province { get; set; }
|
||||||
|
public string? City { get; set; }
|
||||||
|
public string? LeftPostcode { get; set; }
|
||||||
|
public string? RightPostcode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public interface IKpiAreaRepository : IRepository<KpiArea>, IKpiAreaPublishRepository
|
public interface IKpiAreaRepository : IRepository<KpiArea>, IKpiAreaPublishRepository
|
||||||
{
|
{
|
||||||
Task<KpiArea?> GetByAppKeyTypeAndNameAsync(string appKey, string areaType, string name, CancellationToken cancellationToken = default);
|
Task<KpiArea?> GetByAppKeyTypeAndNameAsync(string appKey, string areaType, string name, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<bool> ExistsNameAsync(string appKey, string areaType, string name, CancellationToken cancellationToken = default);
|
Task<bool> ExistsNameAsync(string appKey, string areaType, string name, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<List<KpiAreaInfo>> GetInfosAsync(int areaId, int pageIndex, int pageSize, CancellationToken cancellationToken = default);
|
Task<List<KpiAreaInfo>> GetInfosAsync(
|
||||||
|
int areaId,
|
||||||
|
int pageIndex,
|
||||||
|
int pageSize,
|
||||||
|
KpiAreaInfoQueryFilter? filter = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<int> CountInfosAsync(int areaId, CancellationToken cancellationToken = default);
|
Task<int> CountInfosAsync(
|
||||||
|
int areaId,
|
||||||
|
KpiAreaInfoQueryFilter? filter = null,
|
||||||
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
Task<KpiAreaInfo> InsertInfoAsync(KpiAreaInfo info, CancellationToken cancellationToken = default);
|
Task<KpiAreaInfo> InsertInfoAsync(KpiAreaInfo info, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
|||||||
@ -18,20 +18,91 @@ public class KpiAreaRepository : OmsSqlSugarRepository<KpiArea>, IKpiAreaReposit
|
|||||||
return AnyAsync(x => x.AppKey == appKey && x.AreaType == areaType && x.Name == name, cancellationToken);
|
return AnyAsync(x => x.AppKey == appKey && x.AreaType == areaType && x.Name == name, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<KpiAreaInfo>> GetInfosAsync(int areaId, int pageIndex, int pageSize, CancellationToken cancellationToken = default)
|
public async Task<List<KpiAreaInfo>> GetInfosAsync(
|
||||||
|
int areaId,
|
||||||
|
int pageIndex,
|
||||||
|
int pageSize,
|
||||||
|
KpiAreaInfoQueryFilter? filter = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var db = await GetDbContextAsync(cancellationToken);
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
// 依赖 idx_kpi_info_area_id (AreaId, Id),避免大分区 filesort
|
// 依赖 idx_kpi_info_area_id (AreaId, Id),避免大分区 filesort
|
||||||
return await db.Queryable<KpiAreaInfo>()
|
return await BuildInfoQueryable(db, areaId, filter)
|
||||||
.Where(x => x.AreaId == areaId)
|
|
||||||
.OrderBy(x => x.Id, OrderByType.Desc)
|
.OrderBy(x => x.Id, OrderByType.Desc)
|
||||||
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
|
.ToPageListAsync(pageIndex, pageSize, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> CountInfosAsync(int areaId, CancellationToken cancellationToken = default)
|
public async Task<int> CountInfosAsync(
|
||||||
|
int areaId,
|
||||||
|
KpiAreaInfoQueryFilter? filter = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var db = await GetDbContextAsync(cancellationToken);
|
var db = await GetDbContextAsync(cancellationToken);
|
||||||
return await db.Queryable<KpiAreaInfo>().Where(x => x.AreaId == areaId).CountAsync(cancellationToken);
|
return await BuildInfoQueryable(db, areaId, filter).CountAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ISugarQueryable<KpiAreaInfo> BuildInfoQueryable(
|
||||||
|
ISqlSugarClient db,
|
||||||
|
int areaId,
|
||||||
|
KpiAreaInfoQueryFilter? filter)
|
||||||
|
{
|
||||||
|
var query = db.Queryable<KpiAreaInfo>().Where(x => x.AreaId == areaId);
|
||||||
|
if (filter == null)
|
||||||
|
{
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
var country = TrimOrNull(filter.Country);
|
||||||
|
if (country != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x =>
|
||||||
|
(x.CountryName != null && x.CountryName.Contains(country))
|
||||||
|
|| (x.CountryCode != null && x.CountryCode.Contains(country)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var matchDim = TrimOrNull(filter.MatchDim);
|
||||||
|
if (matchDim != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.MatchDim != null && x.MatchDim.Contains(matchDim));
|
||||||
|
}
|
||||||
|
|
||||||
|
var matchMode = TrimOrNull(filter.MatchMode);
|
||||||
|
if (matchMode != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.MatchMode != null && x.MatchMode.Contains(matchMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
var province = TrimOrNull(filter.Province);
|
||||||
|
if (province != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.Province != null && x.Province.Contains(province));
|
||||||
|
}
|
||||||
|
|
||||||
|
var city = TrimOrNull(filter.City);
|
||||||
|
if (city != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.City != null && x.City.Contains(city));
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftPostcode = TrimOrNull(filter.LeftPostcode);
|
||||||
|
if (leftPostcode != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.LeftPostcode != null && x.LeftPostcode.Contains(leftPostcode));
|
||||||
|
}
|
||||||
|
|
||||||
|
var rightPostcode = TrimOrNull(filter.RightPostcode);
|
||||||
|
if (rightPostcode != null)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.RightPostcode != null && x.RightPostcode.Contains(rightPostcode));
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? TrimOrNull(string? value)
|
||||||
|
{
|
||||||
|
var trimmed = value?.Trim();
|
||||||
|
return string.IsNullOrEmpty(trimmed) ? null : trimmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<KpiAreaInfo> InsertInfoAsync(KpiAreaInfo info, CancellationToken cancellationToken = default)
|
public async Task<KpiAreaInfo> InsertInfoAsync(KpiAreaInfo info, CancellationToken cancellationToken = default)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user