fix 省市地区管理

This commit is contained in:
yxw
2026-01-05 19:09:54 +08:00
parent ea541fb6e4
commit 4eb09a79fc
12 changed files with 1704 additions and 36 deletions

View File

@@ -6,6 +6,8 @@ namespace Atomx.Admin.Client.Models
{ {
[IgnoreDataMember] [IgnoreDataMember]
public long? CountryId { get; set; } public long? CountryId { get; set; }
[IgnoreDataMember]
public long StateProvinceId { get; set; } public long StateProvinceId { get; set; }
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
} }

View File

@@ -27,7 +27,7 @@
<Input @bind-Value="@country.Name" Placeholder="国家名称" Disabled /> <Input @bind-Value="@country.Name" Placeholder="国家名称" Disabled />
</FormItem> </FormItem>
<FormItem Label="州/省/城市"> <FormItem Label="州/省/城市">
<Cascader Options="@stateProvinceTrees" @bind-Value="cities" SelectedNodesChanged="OnCitiesChange"></Cascader> <Cascader Options="@stateProvinceTrees" @bind-Value="cities" ChangeOnSelect="true" SelectedNodesChanged="OnCitiesChange"></Cascader>
</FormItem> </FormItem>
<FormItem Label="名称" Required> <FormItem Label="名称" Required>
<Input @bind-Value="@context.Name" Placeholder="名称" /> <Input @bind-Value="@context.Name" Placeholder="名称" />
@@ -81,9 +81,10 @@
{ {
model.CountryId = CountryId; model.CountryId = CountryId;
_ = LoadStateProvinceAndCities();
_ = LoadLanguage(); _ = LoadLanguage();
_ = LoadCountry(); _ = LoadCountry();
_ = LoadStateProvinceAndCities();
if (Id > 0) if (Id > 0)
{ {
LoadData(); LoadData();
@@ -164,14 +165,14 @@
{ {
area = apiResult.Data; area = apiResult.Data;
model = apiResult.Data.Adapt<AreaModel>(); model = apiResult.Data.Adapt<AreaModel>();
// if (model.ParentId > 0) if (model.ParentId > 0)
// { {
// cities = $"{model.StateProvinceId},{model.ParentId}"; cities = $"{model.ParentId}";
// } }
// else if (model.StateProvinceId > 0) else if (model.StateProvinceId > 0)
// { {
// cities = $"{model.StateProvinceId}"; cities = $"{model.StateProvinceId}";
// } }
} }
} }
else else
@@ -203,7 +204,7 @@
{ {
saving = false; saving = false;
await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" }); await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" });
Navigation.NavigateTo($"/area/list/{CountryId}"); Navigation.NavigateTo($"/area/list/{CountryId}/{StateProvinceId}");
} }
else else
{ {

View File

@@ -48,6 +48,7 @@
<PropertyColumn Property="c => c.Name" Title="名称" /> <PropertyColumn Property="c => c.Name" Title="名称" />
<PropertyColumn Property="c => c.StateProvinceName" Title="州/省" /> <PropertyColumn Property="c => c.StateProvinceName" Title="州/省" />
<PropertyColumn Property="c => c.Initial" Title="首字母" /> <PropertyColumn Property="c => c.Initial" Title="首字母" />
<PropertyColumn Property="c => c.Count" Title="地区数量" />
<PropertyColumn Property="c => c.Enabled" Title="状态"> <PropertyColumn Property="c => c.Enabled" Title="状态">
@if (context.Enabled) @if (context.Enabled)
{ {
@@ -172,22 +173,52 @@
{ {
if (page > 1) if (page > 1)
{ {
Navigation.NavigateTo($"/area/list/{CountryId}?page={page}"); if (StateProvinceId > 0)
{
Navigation.NavigateTo($"/area/list/{CountryId}/{StateProvinceId}?page={page}");
}
else
{
Navigation.NavigateTo($"/area/list/{CountryId}?page={page}");
}
} }
else else
{ {
Navigation.NavigateTo($"/area/list/{CountryId}"); if (StateProvinceId > 0)
{
Navigation.NavigateTo($"/area/list/{CountryId}/{StateProvinceId}");
}
else
{
Navigation.NavigateTo($"/area/list/{CountryId}");
}
} }
} }
else else
{ {
if (page > 1) if (page > 1)
{ {
Navigation.NavigateTo($"/area/list/{CountryId}?page={page}&{queryString}"); if (StateProvinceId > 0)
{
Navigation.NavigateTo($"/area/list/{CountryId}/{StateProvinceId}?page={page}&{queryString}");
}
else
{
Navigation.NavigateTo($"/area/list/{CountryId}?page={page}&{queryString}");
}
} }
else else
{ {
Navigation.NavigateTo($"/area/list/{CountryId}?{queryString}"); if (StateProvinceId > 0)
{
Navigation.NavigateTo($"/area/list/{CountryId}/{StateProvinceId}?{queryString}");
}
else
{
Navigation.NavigateTo($"/area/list/{CountryId}?{queryString}");
}
} }
} }
} }

View File

@@ -47,6 +47,7 @@
<PropertyColumn Property="c => c.Name" Title="名称" /> <PropertyColumn Property="c => c.Name" Title="名称" />
<PropertyColumn Property="c => c.Initial" Title="首字母" /> <PropertyColumn Property="c => c.Initial" Title="首字母" />
<PropertyColumn Property="c => c.Abbreviation" Title="缩写" /> <PropertyColumn Property="c => c.Abbreviation" Title="缩写" />
<PropertyColumn Property="c => c.Count" Title="城市数量" />
<PropertyColumn Property="c => c.Enabled" Title="状态"> <PropertyColumn Property="c => c.Enabled" Title="状态">
@if (context.Enabled) @if (context.Enabled)
{ {

View File

@@ -32,7 +32,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.1" /> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="10.0.1" />
<PackageReference Include="Scalar.AspNetCore" Version="2.11.7" /> <PackageReference Include="Scalar.AspNetCore" Version="2.11.10" />
<PackageReference Include="Serilog.Settings.Configuration" Version="10.0.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" /> <PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />

View File

@@ -188,7 +188,7 @@ namespace Atomx.Admin.Controllers
if (search.StateProvinceId > 0) if (search.StateProvinceId > 0)
{ {
query = from p in query query = from p in query
where p.ParentId == search.StateProvinceId where p.StateProvinceId == search.StateProvinceId
select p; select p;
} }
list.Count = query.Count(); list.Count = query.Count();
@@ -299,32 +299,79 @@ namespace Atomx.Admin.Controllers
{ {
return new JsonResult(new ApiResult<string>().IsFail("数据不存在", null)); return new JsonResult(new ApiResult<string>().IsFail("数据不存在", null));
} }
bool stateProvinceChanged = data.StateProvinceId != model.StateProvinceId;
bool parentChanged = data.ParentId != model.ParentId;
long oldStateProvinceId = data.StateProvinceId;
long oldParentId = data.ParentId;
data = _mapper.Map(model, data); data = _mapper.Map(model, data);
var parent = _dbContext.Areas.Where(p => p.Id == model.ParentId).SingleOrDefault(); if (stateProvinceChanged || parentChanged)
if (parent == null)
{ {
data.Depth = 0; var parent = _dbContext.Areas.Where(p => p.Id == model.ParentId).SingleOrDefault();
data.Path = model.Id.ToString(); if (parent == null)
}
else
{
if (parent.StateProvinceId == 0)
{ {
data.StateProvinceId = parent.Id; data.Depth = 0;
data.Path = model.Id.ToString();
} }
else else
{ {
data.StateProvinceId = parent.StateProvinceId; if (parent.StateProvinceId == 0)
} {
data.StateProvinceId = parent.Id;
}
else
{
data.StateProvinceId = parent.StateProvinceId;
}
data.Depth = parent.Depth + 1; data.Depth = parent.Depth + 1;
data.Path = $"{parent.Path},{data.Id}"; data.Path = $"{parent.Path},{data.Id}";
}
} }
_dbContext.SaveChanges(); _dbContext.SaveChanges();
if (stateProvinceChanged || parentChanged)
{
//更新数量
if (parentChanged)
{
if (oldParentId > 0)
{
var oldParent = _dbContext.Areas.SingleOrDefault(p => p.Id == oldParentId);
if (oldParent != null)
{
oldParent.Count = _dbContext.Areas.Count(p => p.ParentId == oldParent.Id);
_dbContext.SaveChanges();
}
}
var Parent = _dbContext.Areas.SingleOrDefault(p => p.Id == data.ParentId);
if (Parent != null)
{
Parent.Count = _dbContext.Areas.Count(p => p.ParentId == Parent.Id);
_dbContext.SaveChanges();
}
}
if (stateProvinceChanged)
{
if (oldStateProvinceId > 0)
{
var oldState = _dbContext.Areas.SingleOrDefault(p => p.Id == oldStateProvinceId);
if (oldState != null)
{
oldState.Count = _dbContext.Areas.Count(p => p.StateProvinceId == oldState.Id);
_dbContext.SaveChanges();
}
}
var state = _dbContext.Areas.SingleOrDefault(p => p.Id == data.StateProvinceId);
if (state != null)
{
state.Count = _dbContext.Areas.Count(p => p.StateProvinceId == state.Id);
_dbContext.SaveChanges();
}
}
}
} }
else else
{ {
@@ -346,6 +393,7 @@ namespace Atomx.Admin.Controllers
else else
{ {
data.StateProvinceId = parent.StateProvinceId; data.StateProvinceId = parent.StateProvinceId;
} }
data.Depth = parent.Depth + 1; data.Depth = parent.Depth + 1;
data.Path = $"{parent.Path},{data.Id}"; data.Path = $"{parent.Path},{data.Id}";
@@ -353,6 +401,26 @@ namespace Atomx.Admin.Controllers
_dbContext.Areas.Add(data); _dbContext.Areas.Add(data);
_dbContext.SaveChanges(); _dbContext.SaveChanges();
if (data.ParentId > 0)
{
//更新省份的数量
var state = _dbContext.Areas.SingleOrDefault(p => p.Id == data.StateProvinceId);
if (state != null)
{
state.Count = _dbContext.Areas.Count(p => p.StateProvinceId == state.Id);
_dbContext.SaveChanges();
}
//更新城市的数量
var city = _dbContext.Areas.SingleOrDefault(p => p.Id == data.ParentId);
if (city != null)
{
city.Count = _dbContext.Areas.Count(p => p.ParentId == city.Id);
_dbContext.SaveChanges();
}
}
} }
_backgroundService.ResetStateProvinceAndAreaTree(model.CountryId); _backgroundService.ResetStateProvinceAndAreaTree(model.CountryId);

View File

@@ -50,6 +50,11 @@ namespace Atomx.Common.Entities
[Column(TypeName = "varchar(32)")] [Column(TypeName = "varchar(32)")]
public string Abbreviation { get; set; } = string.Empty; public string Abbreviation { get; set; } = string.Empty;
/// <summary>
/// 下级地区数量
/// </summary>
public int Count { get; set; }
/// <summary> /// <summary>
/// 地区深度 /// 地区深度
/// </summary> /// </summary>

View File

@@ -4,6 +4,6 @@
{ {
public string Label { get; set; } = string.Empty; public string Label { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty; public string Value { get; set; } = string.Empty;
public List<KeyValueTree> Children { get; set; } = new List<KeyValueTree>(); public IList<KeyValueTree> Children { get; set; } = new List<KeyValueTree>();
} }
} }

View File

@@ -91,13 +91,13 @@ namespace Atomx.Data.CacheServices
Value = state.Id.ToString() Value = state.Id.ToString()
}; };
var citysInState = cities.Where(p => p.StateProvinceId == state.Id).ToList(); var citysInState = cities.Where(p => p.ParentId == state.Id).ToList();
foreach (var city in citysInState) foreach (var city in citysInState)
{ {
var cityItem = new KeyValueTree var cityItem = new KeyValueTree
{ {
Label = state.Name, Label = city.Name,
Value = state.Id.ToString() Value = city.Id.ToString()
}; };
cityItem.Children = BuildAreaTree(city.Id, cities, new List<KeyValueTree>()); cityItem.Children = BuildAreaTree(city.Id, cities, new List<KeyValueTree>());
@@ -250,7 +250,7 @@ namespace Atomx.Data.CacheServices
private List<KeyValueTree> BuildAreaTree(long parentId, List<Area> areas, List<KeyValueTree> result) private List<KeyValueTree> BuildAreaTree(long parentId, List<Area> areas, List<KeyValueTree> result)
{ {
var data = areas.Where(p => p.ParentId == parentId).ToList(); var data = areas.Where(p => p.ParentId == parentId).ToList();
foreach (var area in areas) foreach (var area in data)
{ {
var item = new KeyValueTree var item = new KeyValueTree
{ {
@@ -261,7 +261,7 @@ namespace Atomx.Data.CacheServices
if (childs.Count > 0) if (childs.Count > 0)
{ {
var childrenTrees = BuildAreaTree(area.Id, areas, result); var childrenTrees = BuildAreaTree(area.Id, areas, result);
item.Children.AddRange(childrenTrees); item.Children = childrenTrees;
} }
result.Add(item); result.Add(item);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Atomx.Data.Migrations
{
/// <inheritdoc />
public partial class _02 : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Count",
table: "Areas",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Count",
table: "Areas");
}
}
}

View File

@@ -243,6 +243,9 @@ namespace Atomx.Data.Migrations
b.Property<bool>("AllowShipping") b.Property<bool>("AllowShipping")
.HasColumnType("boolean"); .HasColumnType("boolean");
b.Property<int>("Count")
.HasColumnType("integer");
b.Property<long>("CountryId") b.Property<long>("CountryId")
.HasColumnType("bigint"); .HasColumnType("bigint");