省市区
This commit is contained in:
parent
47190401fe
commit
1664b9c70d
@ -1,11 +1,34 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using SqlSugar;
|
||||
|
||||
namespace YD_Event.Application.Region.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// 区域分页查询输入
|
||||
/// </summary>
|
||||
public class RegionPageInput : Pagination
|
||||
{
|
||||
/// <summary>
|
||||
/// 区域名称(模糊查询)
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 区域编码
|
||||
/// </summary>
|
||||
public string? Code { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 行政区域数据传输对象
|
||||
/// </summary>
|
||||
public class RegionDto
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键ID
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 区域编码
|
||||
/// </summary>
|
||||
@ -15,5 +38,41 @@ namespace YD_Event.Application.Region.Dtos
|
||||
/// 区域名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父级编码 (省份为大区Code,城市为省份Code,区县为城市Code)
|
||||
/// </summary>
|
||||
public string ParentCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增/更新行政区域输入
|
||||
/// </summary>
|
||||
public class RegionInput
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键ID (更新时必填)
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 区域编码
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "区域编码不能为空")]
|
||||
[MaxLength(50, ErrorMessage = "区域编码最大长度为50")]
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 区域名称
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "区域名称不能为空")]
|
||||
[MaxLength(50, ErrorMessage = "区域名称最大长度为50")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 父级编码
|
||||
/// </summary>
|
||||
[MaxLength(50, ErrorMessage = "父级编码最大长度为50")]
|
||||
public string ParentCode { get; set; }
|
||||
}
|
||||
}
|
||||
@ -3,63 +3,227 @@ using Mapster;
|
||||
using System.ComponentModel;
|
||||
using Furion.DynamicApiController;
|
||||
using YD_Event.Application.Region.Dtos;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using EasyCaching.Core;
|
||||
using SqlSugar;
|
||||
using Furion.FriendlyException;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using YD_Event.Core.Shared;
|
||||
|
||||
namespace YD_Event.Application.Region
|
||||
{
|
||||
/// <summary>
|
||||
/// 行政区域服务
|
||||
/// </summary>
|
||||
[ApiDescriptionSettings("系统管理", Name = "Region", Order = 100)]
|
||||
public class RegionService : ITransient, IDynamicApiController
|
||||
{
|
||||
private readonly ISqlSugarRepository<SysProvince> _provinceRepository;
|
||||
private readonly ISqlSugarRepository<SysCity> _cityRepository;
|
||||
private readonly ISqlSugarRepository<SysDistrict> _districtRepository;
|
||||
private readonly IEasyCachingProvider _easyCachingProvider;
|
||||
private readonly IIdGenerator _idGenerator;
|
||||
|
||||
// 缓存键定义
|
||||
private const string CacheKey_Provinces = "Region:Provinces";
|
||||
private const string CacheKey_Cities = "Region:Cities:";
|
||||
private const string CacheKey_Districts = "Region:Districts:";
|
||||
|
||||
public RegionService(
|
||||
ISqlSugarRepository<SysProvince> provinceRepository,
|
||||
ISqlSugarRepository<SysCity> cityRepository,
|
||||
ISqlSugarRepository<SysDistrict> districtRepository)
|
||||
ISqlSugarRepository<SysDistrict> districtRepository,
|
||||
IEasyCachingProvider easyCachingProvider,
|
||||
IIdGenerator idGenerator)
|
||||
{
|
||||
_provinceRepository = provinceRepository;
|
||||
_cityRepository = cityRepository;
|
||||
_districtRepository = districtRepository;
|
||||
_easyCachingProvider = easyCachingProvider;
|
||||
_idGenerator = idGenerator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有省份
|
||||
/// 获取所有省份 (带缓存)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[DisplayName("获取所有省份")]
|
||||
[AllowAnonymous]
|
||||
public async Task<List<RegionDto>> GetProvinces()
|
||||
{
|
||||
var provinces = await _provinceRepository.GetListAsync();
|
||||
return provinces.Adapt<List<RegionDto>>();
|
||||
var cacheValue = await _easyCachingProvider.GetAsync<List<RegionDto>>(CacheKey_Provinces);
|
||||
if (cacheValue.HasValue) return cacheValue.Value;
|
||||
|
||||
var provinces = await _provinceRepository.GetListAsync(x => true);
|
||||
var dtos = provinces.Select(x => new RegionDto
|
||||
{
|
||||
Id = x.Id,
|
||||
Code = x.ProvinceCode,
|
||||
Name = x.ProvinceName,
|
||||
ParentCode = x.RegionCode
|
||||
}).ToList();
|
||||
|
||||
// 防击穿与雪崩:设置随机过期时间 (12-24小时)
|
||||
var expire = TimeSpan.FromHours(new Random().Next(12, 24));
|
||||
await _easyCachingProvider.SetAsync(CacheKey_Provinces, dtos, expire);
|
||||
|
||||
return dtos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据省份代码获取城市列表
|
||||
/// 根据省份代码获取城市列表 (带缓存)
|
||||
/// </summary>
|
||||
/// <param name="provinceCode"></param>
|
||||
/// <param name="provinceCode">省份代码</param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("根据省份代码获取城市列表")]
|
||||
public async Task<List<RegionDto>> GetCitiesByProvince(string provinceCode)
|
||||
[AllowAnonymous]
|
||||
public async Task<List<RegionDto>> GetCitiesByProvince([FromQuery] string provinceCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(provinceCode)) throw Oops.Oh("省份代码不能为空");
|
||||
|
||||
string cacheKey = $"{CacheKey_Cities}{provinceCode}";
|
||||
var cacheValue = await _easyCachingProvider.GetAsync<List<RegionDto>>(cacheKey);
|
||||
if (cacheValue.HasValue) return cacheValue.Value;
|
||||
|
||||
var cities = await _cityRepository.GetListAsync(c => c.ProvinceCode == provinceCode);
|
||||
return cities.Adapt<List<RegionDto>>();
|
||||
// 防穿透:如果查询为空,也缓存一个空列表,时间较短
|
||||
if (!cities.Any())
|
||||
{
|
||||
await _easyCachingProvider.SetAsync(cacheKey, new List<RegionDto>(), TimeSpan.FromMinutes(5));
|
||||
return new List<RegionDto>();
|
||||
}
|
||||
|
||||
var dtos = cities.Select(x => new RegionDto
|
||||
{
|
||||
Id = x.Id,
|
||||
Code = x.CityCode,
|
||||
Name = x.CityName,
|
||||
ParentCode = x.ProvinceCode
|
||||
}).ToList();
|
||||
|
||||
await _easyCachingProvider.SetAsync(cacheKey, dtos, TimeSpan.FromHours(new Random().Next(12, 24)));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 根据城市代码获取区县列表
|
||||
/// 根据城市代码获取区县列表 (带缓存)
|
||||
/// </summary>
|
||||
/// <param name="cityCode"></param>
|
||||
/// <param name="cityCode">城市代码</param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("根据城市代码获取区县列表")]
|
||||
public async Task<List<RegionDto>> GetDistrictsByCity(string cityCode)
|
||||
[AllowAnonymous]
|
||||
public async Task<List<RegionDto>> GetDistrictsByCity([FromQuery] string cityCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cityCode)) throw Oops.Oh("城市代码不能为空");
|
||||
|
||||
string cacheKey = $"{CacheKey_Districts}{cityCode}";
|
||||
var cacheValue = await _easyCachingProvider.GetAsync<List<RegionDto>>(cacheKey);
|
||||
if (cacheValue.HasValue) return cacheValue.Value;
|
||||
|
||||
var districts = await _districtRepository.GetListAsync(d => d.CityCode == cityCode);
|
||||
return districts.Adapt<List<RegionDto>>();
|
||||
if (!districts.Any())
|
||||
{
|
||||
await _easyCachingProvider.SetAsync(cacheKey, new List<RegionDto>(), TimeSpan.FromMinutes(5));
|
||||
return new List<RegionDto>();
|
||||
}
|
||||
|
||||
var dtos = districts.Select(x => new RegionDto
|
||||
{
|
||||
Id = x.Id,
|
||||
Code = x.DistrictCode,
|
||||
Name = x.DistrictName,
|
||||
ParentCode = x.CityCode
|
||||
}).ToList();
|
||||
|
||||
await _easyCachingProvider.SetAsync(cacheKey, dtos, TimeSpan.FromHours(new Random().Next(12, 24)));
|
||||
return dtos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询省份信息
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[DisplayName("分页查询省份信息")]
|
||||
[HttpPost("page/provinces")]
|
||||
public async Task<SqlSugar.PageResult<RegionDto>> GetProvincePage([FromBody] RegionPageInput input)
|
||||
{
|
||||
var result = await _provinceRepository.AsQueryable()
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.Name), x => x.ProvinceName.Contains(input.Name))
|
||||
.WhereIF(!string.IsNullOrWhiteSpace(input.Code), x => x.ProvinceCode.Contains(input.Code))
|
||||
.OrderBy(x => x.ProvinceCode)
|
||||
.Select(x => new RegionDto
|
||||
{
|
||||
Id = x.Id,
|
||||
Code = x.ProvinceCode,
|
||||
Name = x.ProvinceName,
|
||||
ParentCode = x.RegionCode
|
||||
})
|
||||
.ToPagedListAsync(input);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加省份
|
||||
/// </summary>
|
||||
[DisplayName("添加省份")]
|
||||
[UnitOfWork]
|
||||
public async Task AddProvince(RegionInput input)
|
||||
{
|
||||
var exists = await _provinceRepository.IsAnyAsync(x => x.ProvinceCode == input.Code);
|
||||
if (exists) throw Oops.Oh("省份编码已存在");
|
||||
|
||||
var entity = new SysProvince
|
||||
{
|
||||
Id = _idGenerator.NewLong(),
|
||||
ProvinceCode = input.Code,
|
||||
ProvinceName = input.Name,
|
||||
RegionCode = input.ParentCode,
|
||||
CreatedTime = DateTime.Now
|
||||
};
|
||||
|
||||
await _provinceRepository.InsertAsync(entity);
|
||||
await _easyCachingProvider.RemoveAsync(CacheKey_Provinces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新省份
|
||||
/// </summary>
|
||||
[DisplayName("更新省份")]
|
||||
[UnitOfWork]
|
||||
public async Task UpdateProvince(RegionInput input)
|
||||
{
|
||||
var entity = await _provinceRepository.GetByIdAsync(input.Id);
|
||||
if (entity == null) throw Oops.Oh("省份不存在");
|
||||
|
||||
var exists = await _provinceRepository.IsAnyAsync(x => x.ProvinceCode == input.Code && x.Id != input.Id);
|
||||
if (exists) throw Oops.Oh("省份编码已存在");
|
||||
|
||||
entity.ProvinceCode = input.Code;
|
||||
entity.ProvinceName = input.Name;
|
||||
entity.RegionCode = input.ParentCode;
|
||||
entity.UpdatedTime = DateTime.Now;
|
||||
|
||||
await _provinceRepository.UpdateAsync(entity);
|
||||
await _easyCachingProvider.RemoveAsync(CacheKey_Provinces);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除省份
|
||||
/// </summary>
|
||||
[DisplayName("删除省份")]
|
||||
[UnitOfWork]
|
||||
public async Task DeleteProvince([FromQuery] long id)
|
||||
{
|
||||
var entity = await _provinceRepository.GetByIdAsync(id);
|
||||
if (entity == null) throw Oops.Oh("省份不存在");
|
||||
|
||||
var hasCity = await _cityRepository.IsAnyAsync(x => x.ProvinceCode == entity.ProvinceCode);
|
||||
if (hasCity) throw Oops.Oh("该省份下存在城市,无法删除");
|
||||
|
||||
await _provinceRepository.DeleteAsync(entity);
|
||||
await _easyCachingProvider.RemoveAsync(CacheKey_Provinces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4536,11 +4536,31 @@
|
||||
<param name="eventStartTime">赛事开始时间</param>
|
||||
<returns>应退金额</returns>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Region.Dtos.RegionPageInput">
|
||||
<summary>
|
||||
区域分页查询输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionPageInput.Name">
|
||||
<summary>
|
||||
区域名称(模糊查询)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionPageInput.Code">
|
||||
<summary>
|
||||
区域编码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Region.Dtos.RegionDto">
|
||||
<summary>
|
||||
行政区域数据传输对象
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionDto.Id">
|
||||
<summary>
|
||||
主键ID
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionDto.Code">
|
||||
<summary>
|
||||
区域编码
|
||||
@ -4551,6 +4571,36 @@
|
||||
区域名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionDto.ParentCode">
|
||||
<summary>
|
||||
父级编码 (省份为大区Code,城市为省份Code,区县为城市Code)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Region.Dtos.RegionInput">
|
||||
<summary>
|
||||
新增/更新行政区域输入
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionInput.Id">
|
||||
<summary>
|
||||
主键ID (更新时必填)
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionInput.Code">
|
||||
<summary>
|
||||
区域编码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionInput.Name">
|
||||
<summary>
|
||||
区域名称
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Region.Dtos.RegionInput.ParentCode">
|
||||
<summary>
|
||||
父级编码
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:YD_Event.Application.Region.RegionService">
|
||||
<summary>
|
||||
行政区域服务
|
||||
@ -4558,24 +4608,46 @@
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.GetProvinces">
|
||||
<summary>
|
||||
获取所有省份
|
||||
获取所有省份 (带缓存)
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.GetCitiesByProvince(System.String)">
|
||||
<summary>
|
||||
根据省份代码获取城市列表
|
||||
根据省份代码获取城市列表 (带缓存)
|
||||
</summary>
|
||||
<param name="provinceCode"></param>
|
||||
<param name="provinceCode">省份代码</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.GetDistrictsByCity(System.String)">
|
||||
<summary>
|
||||
根据城市代码获取区县列表
|
||||
根据城市代码获取区县列表 (带缓存)
|
||||
</summary>
|
||||
<param name="cityCode"></param>
|
||||
<param name="cityCode">城市代码</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.GetProvincePage(YD_Event.Application.Region.Dtos.RegionPageInput)">
|
||||
<summary>
|
||||
分页查询省份信息
|
||||
</summary>
|
||||
<param name="input"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.AddProvince(YD_Event.Application.Region.Dtos.RegionInput)">
|
||||
<summary>
|
||||
添加省份
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.UpdateProvince(YD_Event.Application.Region.Dtos.RegionInput)">
|
||||
<summary>
|
||||
更新省份
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:YD_Event.Application.Region.RegionService.DeleteProvince(System.Int64)">
|
||||
<summary>
|
||||
删除省份
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Application.Role.Dtos.AddSysRoleInput.Name">
|
||||
<summary>
|
||||
角色名称
|
||||
|
||||
@ -3011,11 +3011,6 @@
|
||||
城市表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysCity.CityId">
|
||||
<summary>
|
||||
城市Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysCity.ProvinceCode">
|
||||
<summary>
|
||||
省份Code
|
||||
@ -3061,11 +3056,6 @@
|
||||
区县表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysDistrict.DistrictId">
|
||||
<summary>
|
||||
区县Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysDistrict.CityCode">
|
||||
<summary>
|
||||
城市Code
|
||||
@ -3401,11 +3391,6 @@
|
||||
省份表
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysProvince.ProvinceId">
|
||||
<summary>
|
||||
省份Id
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:YD_Event.Core.Entities.SysProvince.ProvinceCode">
|
||||
<summary>
|
||||
省份Code
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user