From 1331477ac9af52adfa1465bc9632068ff1e99a94 Mon Sep 17 00:00:00 2001 From: yxw <17074267@qq.com> Date: Fri, 2 Jan 2026 17:02:00 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=9C=B0=E5=8C=BA=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Atomx.Admin/Controllers/AreaController.cs | 18 +- .../Controllers/CountryController.cs | 1 - .../Controllers/StateProvinceController.cs | 20 +- Atomx.Common/Constants/CacheKeys.cs | 2 +- Atomx.Data/CacheServices/AreaCacheService.cs | 229 ++++++++++++++---- Atomx.Utils/Extension/TreeExtension.cs | 36 --- 6 files changed, 199 insertions(+), 107 deletions(-) delete mode 100644 Atomx.Utils/Extension/TreeExtension.cs diff --git a/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs b/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs index 2123fe9..4bbc693 100644 --- a/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs +++ b/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs @@ -54,22 +54,6 @@ namespace Atomx.Admin.Controllers _localizer = localizer; } - /// - /// - /// - /// - [HttpGet("select/{id}")] - public IActionResult Select(long id) - { - var list = new List(); - 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>().IsSuccess(list)); - } - /// /// 数据查询 /// @@ -78,7 +62,7 @@ namespace Atomx.Admin.Controllers /// /// [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) { diff --git a/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs b/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs index 8e1a043..f2f9e96 100644 --- a/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs +++ b/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs @@ -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; diff --git a/Atomx.Admin/Atomx.Admin/Controllers/StateProvinceController.cs b/Atomx.Admin/Atomx.Admin/Controllers/StateProvinceController.cs index fc019bc..2a39a18 100644 --- a/Atomx.Admin/Atomx.Admin/Controllers/StateProvinceController.cs +++ b/Atomx.Admin/Atomx.Admin/Controllers/StateProvinceController.cs @@ -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; } + /// + /// 数据查询 + /// + /// + /// + /// + /// + [HttpGet("tree/{countryId:long}")] + public async Task GetTree(long countryId, int page, int size = 20) + { + var list = await _cacheService.GetAreaTree(countryId); + + return new JsonResult(new ApiResult>().IsSuccess(list)); + } + /// /// 数据查询 /// @@ -58,7 +74,7 @@ namespace Atomx.Admin.Controllers /// /// [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(); var query = from p in _dbContext.StateProvinces @@ -77,7 +93,7 @@ namespace Atomx.Admin.Controllers /// /// [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) { diff --git a/Atomx.Common/Constants/CacheKeys.cs b/Atomx.Common/Constants/CacheKeys.cs index 46c70c4..586899d 100644 --- a/Atomx.Common/Constants/CacheKeys.cs +++ b/Atomx.Common/Constants/CacheKeys.cs @@ -103,7 +103,7 @@ /// /// 省州数据缓存 /// - public const string Province = "Area.Province"; + public const string StateProvince = "Area.Province."; /// /// 城市数据缓存 diff --git a/Atomx.Data/CacheServices/AreaCacheService.cs b/Atomx.Data/CacheServices/AreaCacheService.cs index 6ed96a7..ddadd93 100644 --- a/Atomx.Data/CacheServices/AreaCacheService.cs +++ b/Atomx.Data/CacheServices/AreaCacheService.cs @@ -10,21 +10,37 @@ namespace Atomx.Data.CacheServices /// 获取国家数据 /// /// - Task> GetCountry(bool? reload = false); + Task> GetCountries(bool? reload = false); /// - /// 通过ID获取国家名称 + /// 通过ID获取国家 /// /// /// - Task GetCountryName(long countryId); + Task GetCountry(long countryId); /// - /// 根据上级ID获取下级数据 + /// 获取区域数据 /// /// /// - Task> GetAreas(long parentId, bool? reload = false); + Task> GetStateProvinces(long countryId, bool? reload = false); + + /// + /// 获取州省数据 + /// + /// + /// + /// + Task GetStateProvince(long countryId, long stateProvinceId); + + /// + /// 获取地区数据 + /// + /// + /// + /// + Task> GetAreas(long countryId, bool? reload = false); /// /// 更新调整缓存数据 @@ -33,51 +49,67 @@ namespace Atomx.Data.CacheServices /// Task ResetArea(Area area); + /// + /// 更新调整州省缓存数据 + /// + /// + /// + Task ResetStateProvince(StateProvince stateProvince); + + /// + /// 更新调整国家缓存数据 + /// + /// + /// + Task ResetCountry(Country country); + /// /// 获取国家-省份-城市树形数据 /// /// /// - List GetAreaTreeAsync(long countryId); - - + Task> GetAreaTree(long countryId, bool? reload = false); } public partial class CacheService : ICacheService { - public async Task> GetAreaTreeAsync(long countryId, bool? reload = false) + public async Task> GetAreaTree(long countryId, bool? reload = false) { + bool reloadData = reload.HasValue ? reload.Value : false; var cacheData = await GetCacheAsync>($"{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(); + + foreach (var state in states) + { + var item = new KeyValueTree + { + Key = state.Id.ToString(), + Value = state.Name, + Children = new List() + }; + + item.Children = BuildAreaTree(state.Id, cities, new List()); + tree.Add(item); + } + + await SetCacheAsync($"{CacheKeys.CountryTree}{countryId}", tree); } - return cacheData; + return cacheData; } - public async Task> GetCountry(bool? reload = false) + public async Task> GetCountries(bool? reload = false) { bool reloadData = reload.HasValue ? reload.Value : false; - var cacheData = await GetCacheAsync>(CacheKeys.Country); + var cacheData = await GetCacheAsync>(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 GetCountryName(long countryId) + public async Task 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> GetAreas(long parentId, bool? reload = false) + /// + /// 获取区域数据 + /// + /// + /// + public async Task> GetStateProvinces(long countryId, bool? reload = false) { - if (parentId == 0) + bool reloadData = reload.HasValue ? reload.Value : false; + var cacheData = await GetCacheAsync>($"{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>($"{CacheKeys.Area}.{parentId}"); + return cacheData; + } + + /// + /// 获取州省数据 + /// + /// + /// + public async Task GetStateProvince(long countryId, long stateProvinceId) + { + var cacheData = await GetStateProvinces(countryId); + var data = cacheData.SingleOrDefault(p => p.Id == stateProvinceId); + return data; + } + + /// + /// 获取地区数据 + /// + /// + /// + /// + public async Task> GetAreas(long countryId, bool? reload = false) + { + var cacheData = await GetCacheAsync>($"{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 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); + } + + + + /// + /// 更新调整州省缓存数据 + /// + /// + /// + 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); + } + + /// + /// 更新调整国家缓存数据 + /// + /// + /// + 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 BuildAreaTree(long parentId, List areas, List 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() + }; + 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; } } } diff --git a/Atomx.Utils/Extension/TreeExtension.cs b/Atomx.Utils/Extension/TreeExtension.cs deleted file mode 100644 index 118002a..0000000 --- a/Atomx.Utils/Extension/TreeExtension.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Atomx.Utils.Extension -{ - public static class TreeExtension - { - public static List ToTree(this List list, Func getId, Func getParentId, Action> setChildren, string rootParentId = "0") - { - var lookup = new Dictionary(); - var result = new List(); - 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(); - setChildren(parent, children); - children.Add(item); - } - } - return result; - } - } -}