调整地区数据缓存

This commit is contained in:
yxw
2026-01-02 17:02:00 +08:00
parent 85c91244cd
commit 1331477ac9
6 changed files with 199 additions and 107 deletions

View File

@@ -54,22 +54,6 @@ namespace Atomx.Admin.Controllers
_localizer = localizer;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet("select/{id}")]
public IActionResult Select(long id)
{
var list = new List<KeyValue>();
var query = from p in _dbContext.Areas
where p.ParentId == id && p.Enabled
select p;
list = query.OrderByDescending(p => p.DisplayOrder).Select(p => new KeyValue() { Key = p.Id.ToString(), Value = p.Name }).ToList();
return new JsonResult(new ApiResult<List<KeyValue>>().IsSuccess(list));
}
/// <summary>
/// 数据查询
/// </summary>
@@ -78,7 +62,7 @@ namespace Atomx.Admin.Controllers
/// <param name="size"></param>
/// <returns></returns>
[HttpPost("search")]
public IActionResult AddressList(AreaSearch search, int page, int size = 20)
public IActionResult Search(AreaSearch search, int page, int size = 20)
{
if (page < 1)
{

View File

@@ -1,6 +1,5 @@
using Atomx.Admin.Client.Models;
using Atomx.Admin.Services;
using Atomx.Common.Constants;
using Atomx.Common.Entities;
using Atomx.Common.Enums;
using Atomx.Common.Models;

View File

@@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
namespace Atomx.Admin.Controllers
{
@@ -50,6 +51,21 @@ namespace Atomx.Admin.Controllers
_localizer = localizer;
}
/// <summary>
/// 数据查询
/// </summary>
/// <param name="search"></param>
/// <param name="page"></param>
/// <param name="size"></param>
/// <returns></returns>
[HttpGet("tree/{countryId:long}")]
public async Task<IActionResult> GetTree(long countryId, int page, int size = 20)
{
var list = await _cacheService.GetAreaTree(countryId);
return new JsonResult(new ApiResult<List<KeyValueTree>>().IsSuccess(list));
}
/// <summary>
/// 数据查询
/// </summary>
@@ -58,7 +74,7 @@ namespace Atomx.Admin.Controllers
/// <param name="size"></param>
/// <returns></returns>
[HttpGet("select/{countryId:long}")]
public IActionResult AddressList(long countryId, int page, int size = 20)
public IActionResult Select(long countryId, int page, int size = 20)
{
var list = new List<KeyValue>();
var query = from p in _dbContext.StateProvinces
@@ -77,7 +93,7 @@ namespace Atomx.Admin.Controllers
/// <param name="size"></param>
/// <returns></returns>
[HttpPost("search")]
public IActionResult AddressList(StateProvinceSearch search, int page, int size = 20)
public IActionResult Search(StateProvinceSearch search, int page, int size = 20)
{
if (page < 1)
{

View File

@@ -103,7 +103,7 @@
/// <summary>
/// 省州数据缓存
/// </summary>
public const string Province = "Area.Province";
public const string StateProvince = "Area.Province.";
/// <summary>
/// 城市数据缓存

View File

@@ -10,21 +10,37 @@ namespace Atomx.Data.CacheServices
/// 获取国家数据
/// </summary>
/// <returns></returns>
Task<List<Area>> GetCountry(bool? reload = false);
Task<List<Country>> GetCountries(bool? reload = false);
/// <summary>
/// 通过ID获取国家名称
/// 通过ID获取国家
/// </summary>
/// <param name="countryId"></param>
/// <returns></returns>
Task<string> GetCountryName(long countryId);
Task<Country> GetCountry(long countryId);
/// <summary>
/// 根据上级ID获取下级数据
/// 获取区域数据
/// </summary>
/// <param name="parentId"></param>
/// <returns></returns>
Task<List<Area>> GetAreas(long parentId, bool? reload = false);
Task<List<StateProvince>> GetStateProvinces(long countryId, bool? reload = false);
/// <summary>
/// 获取州省数据
/// </summary>
/// <param name="countryId"></param>
/// <param name="stateProvinceId"></param>
/// <returns></returns>
Task<StateProvince> GetStateProvince(long countryId, long stateProvinceId);
/// <summary>
/// 获取地区数据
/// </summary>
/// <param name="countryId"></param>
/// <param name="reload"></param>
/// <returns></returns>
Task<List<Area>> GetAreas(long countryId, bool? reload = false);
/// <summary>
/// 更新调整缓存数据
@@ -33,51 +49,67 @@ namespace Atomx.Data.CacheServices
/// <returns></returns>
Task ResetArea(Area area);
/// <summary>
/// 更新调整州省缓存数据
/// </summary>
/// <param name="stateProvince"></param>
/// <returns></returns>
Task ResetStateProvince(StateProvince stateProvince);
/// <summary>
/// 更新调整国家缓存数据
/// </summary>
/// <param name="country"></param>
/// <returns></returns>
Task ResetCountry(Country country);
/// <summary>
/// 获取国家-省份-城市树形数据
/// </summary>
/// <param name="countryId"></param>
/// <returns></returns>
List<KeyValueTree> GetAreaTreeAsync(long countryId);
Task<List<KeyValueTree>> GetAreaTree(long countryId, bool? reload = false);
}
public partial class CacheService : ICacheService
{
public async Task<List<KeyValueTree>> GetAreaTreeAsync(long countryId, bool? reload = false)
public async Task<List<KeyValueTree>> GetAreaTree(long countryId, bool? reload = false)
{
bool reloadData = reload.HasValue ? reload.Value : false;
var cacheData = await GetCacheAsync<List<KeyValueTree>>($"{CacheKeys.CountryTree}{countryId}");
if (cacheData == null || reload.HasValue && reload.Value)
if (cacheData == null || reloadData)
{
var state = _dbContext.StateProvinces.Where(p => p.CountryId == countryId).ToList();
var cities = _dbContext.Areas.Where(p => p.CountryId == countryId).ToList();
cacheData = (from s in state
select new KeyValueTree
{
Key = s.Id.ToString(),
Value = s.Name,
Children = (from c in cities
where c.ParentId == s.Id
select new KeyValueTree
{
Key = c.Id.ToString(),
Value = c.Name
}).ToList()
}).ToList();
await SetCacheAsync(CacheKeys.Country, cacheData);
var states = await GetStateProvinces(countryId);
var cities = await GetAreas(countryId);
var tree = new List<KeyValueTree>();
foreach (var state in states)
{
var item = new KeyValueTree
{
Key = state.Id.ToString(),
Value = state.Name,
Children = new List<KeyValueTree>()
};
item.Children = BuildAreaTree(state.Id, cities, new List<KeyValueTree>());
tree.Add(item);
}
await SetCacheAsync($"{CacheKeys.CountryTree}{countryId}", tree);
}
return cacheData;
return cacheData;
}
public async Task<List<Area>> GetCountry(bool? reload = false)
public async Task<List<Country>> GetCountries(bool? reload = false)
{
bool reloadData = reload.HasValue ? reload.Value : false;
var cacheData = await GetCacheAsync<List<Area>>(CacheKeys.Country);
var cacheData = await GetCacheAsync<List<Country>>(CacheKeys.Country);
if (cacheData == null || reloadData)
{
var countries = (from p in _dbContext.Areas
where p.ParentId == 0
var countries = (from p in _dbContext.Countries
where p.Enabled
select p).ToList();
await SetCacheAsync(CacheKeys.Country, countries);
return countries;
@@ -86,47 +118,144 @@ namespace Atomx.Data.CacheServices
return cacheData;
}
public async Task<string> GetCountryName(long countryId)
public async Task<Country> GetCountry(long countryId)
{
var cacheData = await GetCountry();
var cacheData = await GetCountries();
var data = cacheData.SingleOrDefault(p => p.Id == countryId);
if (data == null)
{
return string.Empty;
}
return data.Name;
return data;
}
public async Task<List<Area>> GetAreas(long parentId, bool? reload = false)
/// <summary>
/// 获取区域数据
/// </summary>
/// <param name="countryId"></param>
/// <returns></returns>
public async Task<List<StateProvince>> GetStateProvinces(long countryId, bool? reload = false)
{
if (parentId == 0)
bool reloadData = reload.HasValue ? reload.Value : false;
var cacheData = await GetCacheAsync<List<StateProvince>>($"{CacheKeys.StateProvince}.{countryId}");
if (cacheData == null || reloadData)
{
return await GetCountry();
var stateProvinces = (from p in _dbContext.StateProvinces
where p.CountryId == countryId && p.Enabled
select p).ToList();
await SetCacheAsync($"{CacheKeys.StateProvince}.{countryId}", stateProvinces);
return stateProvinces;
}
var cacheData = await GetCacheAsync<List<Area>>($"{CacheKeys.Area}.{parentId}");
return cacheData;
}
/// <summary>
/// 获取州省数据
/// </summary>
/// <param name="stateProvinceId"></param>
/// <returns></returns>
public async Task<StateProvince> GetStateProvince(long countryId, long stateProvinceId)
{
var cacheData = await GetStateProvinces(countryId);
var data = cacheData.SingleOrDefault(p => p.Id == stateProvinceId);
return data;
}
/// <summary>
/// 获取地区数据
/// </summary>
/// <param name="countryId"></param>
/// <param name="reload"></param>
/// <returns></returns>
public async Task<List<Area>> GetAreas(long countryId, bool? reload = false)
{
var cacheData = await GetCacheAsync<List<Area>>($"{CacheKeys.City}.{countryId}");
bool reloadData = reload.HasValue ? reload.Value : false;
if (cacheData == null || reloadData)
{
var data = (from p in _dbContext.Areas
where p.ParentId == 0
select p).ToList();
await SetCacheAsync(CacheKeys.Country, data);
return data;
List<Area> areas = new();
var query = from p in _dbContext.Areas
where p.CountryId == countryId && p.Enabled
select p;
var count = query.Count();
int size = 50;
var pageCount = (int)Math.Ceiling(count / (double)size) + 1;
for (var i = 1; i < pageCount; i++)
{
var list = query.Skip((i - 1) * size).Take(size).ToList();
areas.AddRange(list);
}
await SetCacheAsync(CacheKeys.Country, areas);
return areas;
}
return cacheData;
}
public async Task ResetArea(Area area)
{
var cacheData = await GetAreas(area.ParentId);
var cacheData = await GetAreas(area.CountryId);
var data = cacheData.Where(p => p.Id == area.Id).SingleOrDefault();
if (data != null)
{
cacheData.Remove(data);
}
cacheData.Add(area);
await SetCacheAsync($"{CacheKeys.Area}.{area.ParentId}", cacheData);
await SetCacheAsync($"{CacheKeys.City}.{area.CountryId}", cacheData);
}
/// <summary>
/// 更新调整州省缓存数据
/// </summary>
/// <param name="stateProvince"></param>
/// <returns></returns>
public async Task ResetStateProvince(StateProvince stateProvince)
{
var cacheData = await GetStateProvinces(stateProvince.CountryId);
var data = cacheData.Where(p => p.Id == stateProvince.Id).SingleOrDefault();
if (data != null)
{
cacheData.Remove(data);
}
cacheData.Add(stateProvince);
await SetCacheAsync($"{CacheKeys.StateProvince}.{stateProvince.CountryId}", cacheData);
}
/// <summary>
/// 更新调整国家缓存数据
/// </summary>
/// <param name="country"></param>
/// <returns></returns>
public async Task ResetCountry(Country country)
{
var cacheData = await GetCountries();
var data = cacheData.Where(p => p.Id == country.Id).SingleOrDefault();
if (data != null)
{
cacheData.Remove(data);
}
cacheData.Add(country);
await SetCacheAsync($"{CacheKeys.Country}", cacheData);
}
private List<KeyValueTree> BuildAreaTree(long parentId, List<Area> areas, List<KeyValueTree> result)
{
var data = areas.Where(p => p.ParentId == parentId).ToList();
foreach (var area in areas)
{
var item = new KeyValueTree
{
Key = area.Id.ToString(),
Value = area.Name,
Children = new List<KeyValueTree>()
};
var childs = areas.Where(p => p.ParentId == area.Id).ToList();
if (childs.Count > 0)
{
var childrenTrees = BuildAreaTree(area.Id, areas, result);
item.Children.AddRange(childrenTrees);
}
result.Add(item);
}
return result;
}
}
}

View File

@@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Atomx.Utils.Extension
{
public static class TreeExtension
{
public static List<T> ToTree<T>(this List<T> list, Func<T, string> getId, Func<T, string> getParentId, Action<T, List<T>> setChildren, string rootParentId = "0")
{
var lookup = new Dictionary<string, T>();
var result = new List<T>();
foreach (var item in list)
{
var id = getId(item);
lookup[id] = item;
}
foreach (var item in list)
{
var parentId = getParentId(item);
if (parentId == rootParentId || !lookup.ContainsKey(parentId))
{
result.Add(item);
}
else
{
var parent = lookup[parentId];
var children = new List<T>();
setChildren(parent, children);
children.Add(item);
}
}
return result;
}
}
}