From b098b3f8153923688b32807ec8041c5c8dd4d9f6 Mon Sep 17 00:00:00 2001 From: yxw <17074267@qq.com> Date: Tue, 6 Jan 2026 18:46:52 +0800 Subject: [PATCH] chore --- .../Atomx.Admin.Client/Models/AreaItem.cs | 2 +- .../Pages/Settings/AreaList.razor | 22 +++++-- .../Pages/Settings/CountryList.razor | 23 +++++-- .../Pages/Settings/StateProvinceList.razor | 20 ++++++- .../Atomx.Admin/Controllers/AreaController.cs | 18 ++++-- .../Controllers/CountryController.cs | 9 ++- Atomx.Common/Entities/DeviceAccessControl.cs | 60 +++++++++++++++++++ Atomx.Common/Entities/IpAccessControl.cs | 49 +++++++++++++++ Atomx.Common/Entities/UserAccessControl.cs | 19 ++++++ Atomx.Data/CacheServices/AreaCacheService.cs | 21 +++++++ 10 files changed, 225 insertions(+), 18 deletions(-) create mode 100644 Atomx.Common/Entities/DeviceAccessControl.cs create mode 100644 Atomx.Common/Entities/IpAccessControl.cs create mode 100644 Atomx.Common/Entities/UserAccessControl.cs diff --git a/Atomx.Admin/Atomx.Admin.Client/Models/AreaItem.cs b/Atomx.Admin/Atomx.Admin.Client/Models/AreaItem.cs index 3b535dd..a064bb8 100644 --- a/Atomx.Admin/Atomx.Admin.Client/Models/AreaItem.cs +++ b/Atomx.Admin/Atomx.Admin.Client/Models/AreaItem.cs @@ -6,6 +6,6 @@ namespace Atomx.Admin.Client.Models { public string CountryName { get; set; } = string.Empty; public string StateProvinceName { get; set; } = string.Empty; - + public string ParentName { get; set; } = string.Empty; } } diff --git a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/AreaList.razor b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/AreaList.razor index a1f23f6..6065441 100644 --- a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/AreaList.razor +++ b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/AreaList.razor @@ -66,14 +66,14 @@ 编辑 - @* + 删除 - *@ + @@ -218,7 +218,7 @@ { Navigation.NavigateTo($"/area/list/{CountryId}?{queryString}"); } - + } } } @@ -245,7 +245,7 @@ { Navigation.NavigateTo($"/area/create/{CountryId}"); } - + } @@ -254,4 +254,18 @@ Navigation.NavigateTo($"/area/edit/{model.CountryId}/{model.StateProvinceId}/{model.Id}"); } + async Task HandleDeleteConfirmAsync(MouseEventArgs e, long id) + { + var url = $"/api/area/delete/{id}"; + var apiResult = await HttpService.Post>(url, new()); + if (apiResult.Success) + { + await LoadListAsync(); + await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" }); + } + else + { + await ModalService.ErrorAsync(new ConfirmOptions() { Title = "操作提示", Content = $"数据删除失败.{apiResult.Message}" }); + } + } } diff --git a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/CountryList.razor b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/CountryList.razor index a0497cf..91d514f 100644 --- a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/CountryList.razor +++ b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/CountryList.razor @@ -60,22 +60,22 @@ - 州省管理 + 查看州/省 - 城市管理 + 查看城市 编辑 - @* + 删除 - *@ + @@ -221,4 +221,19 @@ { Navigation.NavigateTo($"/area/list/{model.Id}"); } + + async Task HandleDeleteConfirmAsync(MouseEventArgs e, long id) + { + var url = $"/api/country/delete/{id}"; + var apiResult = await HttpService.Post>(url, new()); + if (apiResult.Success) + { + await LoadListAsync(); + await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" }); + } + else + { + await ModalService.ErrorAsync(new ConfirmOptions() { Title = "操作提示", Content = $"数据删除失败.{apiResult.Message}" }); + } + } } diff --git a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/StateProvinceList.razor b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/StateProvinceList.razor index 124ba95..f62968c 100644 --- a/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/StateProvinceList.razor +++ b/Atomx.Admin/Atomx.Admin.Client/Pages/Settings/StateProvinceList.razor @@ -62,19 +62,19 @@ - 城市管理 + 查看城市 编辑 - @* + 删除 - *@ + @@ -220,4 +220,18 @@ Navigation.NavigateTo($"/area/list/{CountryId}/{model.Id}"); } + async Task HandleDeleteConfirmAsync(MouseEventArgs e, long id) + { + var url = $"/api/area/delete/{id}"; + var apiResult = await HttpService.Post>(url, new()); + if (apiResult.Success) + { + await LoadListAsync(); + await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" }); + } + else + { + await ModalService.ErrorAsync(new ConfirmOptions() { Title = "操作提示", Content = $"数据删除失败.{apiResult.Message}" }); + } + } } \ No newline at end of file diff --git a/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs b/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs index 0a7edd1..d25564d 100644 --- a/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs +++ b/Atomx.Admin/Atomx.Admin/Controllers/AreaController.cs @@ -216,11 +216,17 @@ namespace Atomx.Admin.Controllers { model.CountryName = country.Name; } - var state = await _cacheService.GetStateProvince(item.CountryId, item.ParentId); + var state = await _cacheService.GetStateProvince(item.CountryId, item.StateProvinceId); if (state != null) { model.StateProvinceName = state.Name; } + var parent = await _cacheService.GetArea(item.CountryId, item.ParentId); + if (parent != null) + { + model.ParentName = parent.Name; + } + list.Items.Add(model); } @@ -435,14 +441,18 @@ namespace Atomx.Admin.Controllers /// /// - [HttpPost("delete")] + [HttpPost("delete/{id:long}")] public async Task DeleteAsync(long id) { var result = new ApiResult(); try { - Console.WriteLine($"{id} deleted"); - var count = _dbContext.Areas.Where(p => p.Id == id).ExecuteDelete(); + var count = _dbContext.Areas.Count(p => p.ParentId == id || p.StateProvinceId == id); + if (count > 0) + { + return new JsonResult(new ApiResult().IsFail("请先删除下级数据", null)); + } + count = _dbContext.Areas.Where(p => p.Id == id).ExecuteDelete(); result = result.IsSuccess(count.ToString()); } catch (Exception ex) diff --git a/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs b/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs index f2f9e96..264eec3 100644 --- a/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs +++ b/Atomx.Admin/Atomx.Admin/Controllers/CountryController.cs @@ -259,14 +259,19 @@ namespace Atomx.Admin.Controllers /// /// - [HttpPost("delete")] + [HttpPost("delete/{id:long}")] public async Task Delete(long id) { var result = new ApiResult(); try { + var count = _dbContext.Areas.Count(p => p.CountryId == id); + if (count > 0) + { + return new JsonResult(new ApiResult().IsFail("当前数据存在城市关联数据,不能删除", null)); + } Console.WriteLine($"{id} deleted"); - var count = _dbContext.Countries.Where(p => p.Id == id).ExecuteDelete(); + count = _dbContext.Countries.Where(p => p.Id == id).ExecuteDelete(); result = result.IsSuccess(count.ToString()); } catch (Exception ex) diff --git a/Atomx.Common/Entities/DeviceAccessControl.cs b/Atomx.Common/Entities/DeviceAccessControl.cs new file mode 100644 index 0000000..af8d52a --- /dev/null +++ b/Atomx.Common/Entities/DeviceAccessControl.cs @@ -0,0 +1,60 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Atomx.Common.Entities +{ + /// + /// 设备访问控制表 + /// + [Table("DeviceAccessControls")] + public class DeviceAccessControl + { + /// + /// 数据ID + /// + [DatabaseGenerated(DatabaseGeneratedOption.None)] + [Key] + public long Id { get; set; } + + /// + /// 限制类型,1黑名单,2白名单 + /// + public int Type { get; set; } + + /// + /// 设备ID + /// + [Column(TypeName = "varchar(256)")] + public string DeviceId { get; set; } = string.Empty; + + /// + /// 设备哈希值,用于唯一标识设备 + /// + [Column(TypeName = "varchar(64)")] + public string DeviceHash { get; set; } = string.Empty; + + /// + /// 设备平台 + /// + [Column(TypeName = "varchar(64)")] + public string Platform { get; set; } = string.Empty; + + /// + /// 浏览器 + /// + [Column(TypeName = "varchar(64)")] + public string Browser { get; set; } = string.Empty; + + /// + /// 建立时间 + /// + [Column(TypeName = "timestamptz")] + public DateTime CreateTime { get; set; } + + /// + /// 最后更新时间 + /// + [Column(TypeName = "timestamptz")] + public DateTime? UpdateTime { get; set; } + } +} diff --git a/Atomx.Common/Entities/IpAccessControl.cs b/Atomx.Common/Entities/IpAccessControl.cs new file mode 100644 index 0000000..e9f3304 --- /dev/null +++ b/Atomx.Common/Entities/IpAccessControl.cs @@ -0,0 +1,49 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Atomx.Common.Entities +{ + /// + /// IP访问控制 + /// + [Table("IpAccessControls")] + public class IpAccessControl + { + /// + /// 数据ID + /// + [DatabaseGenerated(DatabaseGeneratedOption.None)] + [Key] + public long Id { get; set; } + + /// + /// 限制类型,1黑名单,2白名单 + /// + public int Type { get; set; } + + /// + /// 开始IP + /// + [Column(TypeName = "varchar(64)")] + public string StartIp { get; set; } = string.Empty; + + /// + /// 结束IP + /// + [Column(TypeName = "varchar(64)")] + public string EndIp { get; set; } = string.Empty; + + /// + /// 建立时间 + /// + [Column(TypeName = "timestamptz")] + public DateTime CreateTime { get; set; } + + /// + /// 最后更新时间 + /// + [Column(TypeName = "timestamptz")] + public DateTime? UpdateTime { get; set; } + + } +} diff --git a/Atomx.Common/Entities/UserAccessControl.cs b/Atomx.Common/Entities/UserAccessControl.cs new file mode 100644 index 0000000..0d3e394 --- /dev/null +++ b/Atomx.Common/Entities/UserAccessControl.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Atomx.Common.Entities +{ + /// + /// 用户访问控制表 + /// + [Table("UserAccessControls")] + public class UserAccessControl + { + /// + /// 数据ID + /// + [DatabaseGenerated(DatabaseGeneratedOption.None)] + [Key] + public long Id { get; set; } + } +} diff --git a/Atomx.Data/CacheServices/AreaCacheService.cs b/Atomx.Data/CacheServices/AreaCacheService.cs index 94d8743..b392196 100644 --- a/Atomx.Data/CacheServices/AreaCacheService.cs +++ b/Atomx.Data/CacheServices/AreaCacheService.cs @@ -42,6 +42,14 @@ namespace Atomx.Data.CacheServices /// Task> GetAreas(long countryId, bool? reload = false); + /// + /// 获取城市地区数据 + /// + /// + /// + /// + Task GetArea(long countryId, long areaId); + /// /// 更新调整缓存数据 /// @@ -199,6 +207,19 @@ namespace Atomx.Data.CacheServices return cacheData; } + /// + /// 获取城市地区数据 + /// + /// + /// + /// + public async Task GetArea(long countryId, long areaId) + { + var cacheData = await GetAreas(countryId); + var data = cacheData.SingleOrDefault(p => p.Id == areaId); + return data; + } + public async Task UpdateArea(Area area) { var cacheData = await GetAreas(area.CountryId);