✨
This commit is contained in:
240
StopShopping.Services/Implementions/DistrictService.cs
Normal file
240
StopShopping.Services/Implementions/DistrictService.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StopShopping.EF;
|
||||
using StopShopping.Services.Models.Req;
|
||||
using StopShopping.Services.Models.Resp;
|
||||
using O = StopShopping.OpenPlatform;
|
||||
|
||||
namespace StopShopping.Services.Implementions;
|
||||
|
||||
public class DistrictService : IDistrictService
|
||||
{
|
||||
public DistrictService(
|
||||
StopShoppingContext dbContext,
|
||||
O.IDistrictService districtService,
|
||||
ILogger<DistrictService> logger)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_oDistrictService = districtService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private readonly StopShoppingContext _dbContext;
|
||||
private readonly O.IDistrictService _oDistrictService;
|
||||
private readonly ILogger<DistrictService> _logger;
|
||||
|
||||
public async Task InitialDatabaseAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("开始初始化行政区划");
|
||||
|
||||
if (await _dbContext.Districts.AnyAsync(cancellationToken))
|
||||
{
|
||||
_logger.LogInformation("已经存在数据,无需初始化");
|
||||
}
|
||||
else
|
||||
{
|
||||
var districtsResp = await _oDistrictService.GetTop3LevelDistrictsAsync(cancellationToken);
|
||||
if (districtsResp?.IsSucced ?? false)
|
||||
{
|
||||
if (null != districtsResp?.Districts)
|
||||
{
|
||||
using var transaction = await _dbContext.Database.BeginTransactionAsync(cancellationToken);
|
||||
|
||||
short order = 1;
|
||||
int parentId = 0;
|
||||
var districtsProvince = districtsResp.Districts
|
||||
.Select(d => Cast(d, parentId, order++))
|
||||
.ToList();
|
||||
await _dbContext.Districts.AddRangeAsync(districtsProvince, cancellationToken);
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
foreach (var province in districtsResp.Districts)
|
||||
{
|
||||
parentId = districtsProvince.First(p => p.Code == province.Code).Id;
|
||||
order = 1;
|
||||
|
||||
var citys = province.Districts;
|
||||
|
||||
if (null == citys)
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
_logger.LogError("行政区划下级数据不完整:{Name}", province.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
var districtsCity = citys
|
||||
.Select(d => Cast(d, parentId, order++))
|
||||
.ToList();
|
||||
await _dbContext.Districts.AddRangeAsync(districtsCity, cancellationToken);
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 直辖市下属区
|
||||
// var directlyCitysDistrict = citys
|
||||
// .Where(d => d.Districts?.Count == 0)
|
||||
// .ToList();
|
||||
// if (0 == directlyCitysDistrict.Count)
|
||||
// {
|
||||
// await transaction.RollbackAsync(cancellationToken);
|
||||
// _logger.LogError("行政区划数据不完整,缺少直辖市数据");
|
||||
// return;
|
||||
// }
|
||||
|
||||
var semaphoreSlim = new SemaphoreSlim(50);
|
||||
//(parent id, district response)
|
||||
List<Task<(int, O.DistrictResponse?)>> districtTasks = [];
|
||||
|
||||
foreach (var city in citys)
|
||||
{
|
||||
parentId = districtsCity.First(c => c.Code == city.Code).Id;
|
||||
order = 1;
|
||||
if (city.Districts == null || city.Districts.Count == 0)//直辖市
|
||||
{
|
||||
try
|
||||
{
|
||||
await semaphoreSlim.WaitAsync(cancellationToken);
|
||||
districtTasks.Add(
|
||||
Task.FromResult((
|
||||
parentId
|
||||
, await _oDistrictService.GetChildrenAsync(city.Code, cancellationToken)))
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var districtsDistrict = city.Districts
|
||||
.Select(d => Cast(d, parentId, order++))
|
||||
.ToList();
|
||||
await _dbContext.Districts.AddRangeAsync(districtsDistrict, cancellationToken);
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
var districtTask = city.Districts!.Select(async (d) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
|
||||
return (
|
||||
districtsDistrict.First(dd => dd.Code == d.Code).Id
|
||||
, await _oDistrictService.GetChildrenAsync(d.Code, cancellationToken)
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
}
|
||||
});
|
||||
|
||||
districtTasks.AddRange(districtTask);
|
||||
}
|
||||
}
|
||||
|
||||
var streets = await Task.WhenAll(districtTasks);
|
||||
foreach (var s in streets)
|
||||
{
|
||||
order = 1;
|
||||
parentId = s.Item1;
|
||||
if (s.Item2?.IsSucced ?? false)
|
||||
{
|
||||
var districtsStreet = s.Item2.Districts
|
||||
?.Select(ds => Cast(ds, parentId, order++))
|
||||
.ToList();
|
||||
|
||||
if (null != districtsStreet)
|
||||
{
|
||||
await _dbContext.Districts.AddRangeAsync(districtsStreet, cancellationToken);
|
||||
await _dbContext.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await transaction.RollbackAsync(cancellationToken);
|
||||
_logger.LogError("街道数据请求失败:{Message}", s.Item2?.Message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogError("行政区划接口错误:{Message}", districtsResp?.Message);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("结束初始化行政区划");
|
||||
}
|
||||
|
||||
public async Task<ApiResponse<List<District>>> GetTop3LevelDistrictsAsync()
|
||||
{
|
||||
List<District> districts = [];
|
||||
|
||||
var top3Districts = await _dbContext.Districts
|
||||
.Where(d => d.Level <= 3)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
|
||||
if (0 != top3Districts.Count)
|
||||
{
|
||||
Dictionary<int, District> idDicts = [];
|
||||
foreach (var dbDistrict in top3Districts)
|
||||
{
|
||||
idDicts.Add(dbDistrict.Id, Cast(dbDistrict));
|
||||
}
|
||||
foreach (var kv in idDicts)
|
||||
{
|
||||
if (kv.Value.ParentId > 0)
|
||||
idDicts[kv.Value.ParentId].Children.Add(kv.Value);
|
||||
else
|
||||
districts.Add(kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
var result = new ApiResponse<List<District>>(districts);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ApiResponse<List<District>> GetChildren(DistrictParentIdParams model)
|
||||
{
|
||||
var children = _dbContext.Districts
|
||||
.Where(d => d.ParentId == model.ParentId)
|
||||
.AsNoTracking()
|
||||
.Select(Cast)
|
||||
.ToList();
|
||||
|
||||
return new ApiResponse<List<District>>(children);
|
||||
}
|
||||
|
||||
private District Cast(EF.Models.District district)
|
||||
{
|
||||
return new District
|
||||
{
|
||||
Children = [],
|
||||
FullName = district.FullName,
|
||||
Id = district.Id,
|
||||
Level = district.Level,
|
||||
ParentId = district.ParentId
|
||||
};
|
||||
}
|
||||
|
||||
private EF.Models.District Cast(O.DistrictResponse.District district, int parentId, short order)
|
||||
{
|
||||
return new EF.Models.District
|
||||
{
|
||||
Code = district.Code,
|
||||
FullName = district.FullName,
|
||||
Latitude = district.Latitude.ToString(),
|
||||
Level = (short)(district.Level ?? 0),
|
||||
Longitude = district.Longitude.ToString(),
|
||||
Name = district.Name,
|
||||
Order = order,
|
||||
ParentId = parentId,
|
||||
Pinyin = district.PinYin ?? ""
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user