新增字典功能,修复一堆bug
This commit is contained in:
parent
3370ce073e
commit
7d3cae2d8d
@ -136,7 +136,7 @@ namespace AGSS.Areas.Identity.Pages.Account
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
foreach (string role in roles)
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||
claims.Add(new Claim("role", role));
|
||||
}
|
||||
string jwtToken = _jwt.BuildToken(claims, jwtOptions.Value);
|
||||
|
||||
|
@ -148,7 +148,7 @@ namespace AGSS.Areas.Identity.Pages.Account
|
||||
var roles = await _userManager.GetRolesAsync(user);
|
||||
foreach (string role in roles)
|
||||
{
|
||||
claims.Add(new Claim(ClaimTypes.Role, role));
|
||||
claims.Add(new Claim("role", role));
|
||||
}
|
||||
string jwtToken = _jwt.BuildToken(claims, jwtOptions.Value);
|
||||
var frontendCallback = $"{Request.Query["frontendCallback"]}?token={jwtToken}";
|
||||
|
@ -1,203 +0,0 @@
|
||||
using System;
|
||||
using AGSS.Models.Entities;
|
||||
using AGSS.Models.Template;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AGSS.DbSet;
|
||||
|
||||
namespace AGSS.Controllers.Admin
|
||||
{
|
||||
|
||||
[Route("api/v1/[controller]/[action]")]
|
||||
public class AdminDictionaryController : ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _dbContext;
|
||||
private readonly UserManager<UserModel> _userManager;
|
||||
|
||||
public AdminDictionaryController(ApplicationDbContext dbContext, UserManager<UserModel> userManager)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> GetParentDictionaries([FromBody] string label)
|
||||
{
|
||||
|
||||
|
||||
// 确保 label 不是 null
|
||||
label ??= string.Empty;
|
||||
|
||||
var parentDictionaries = _dbContext.Dictionaries.Where(d => d.ParentId == null && (string.IsNullOrEmpty(label) || d.Label.Contains(label))).ToList();
|
||||
return Ok(new ReturnTemplate(200, "查询成功", parentDictionaries));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> AddParentDictionary([FromBody] DictionaryModel dictionary)
|
||||
{
|
||||
|
||||
|
||||
if (dictionary == null || string.IsNullOrWhiteSpace(dictionary.Label) || string.IsNullOrWhiteSpace(dictionary.Value))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Label和Value", null));
|
||||
}
|
||||
|
||||
dictionary.Uuid = Guid.NewGuid().ToString();
|
||||
dictionary.CreateTime = DateTime.UtcNow;
|
||||
dictionary.CreateUserId = _userManager.GetUserId(User);
|
||||
|
||||
_dbContext.Dictionaries.Add(dictionary);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "添加父级字典成功", dictionary));
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> UpdateParentDictionary([FromBody] DictionaryModel dictionary)
|
||||
{
|
||||
|
||||
|
||||
if (dictionary == null || string.IsNullOrWhiteSpace(dictionary.Uuid) || string.IsNullOrWhiteSpace(dictionary.Label))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Uuid和Label", null));
|
||||
}
|
||||
|
||||
var existingDictionary = _dbContext.Dictionaries.FirstOrDefault(d => d.Uuid == dictionary.Uuid && d.ParentId == null);
|
||||
if (existingDictionary == null)
|
||||
{
|
||||
return Ok(new ReturnTemplate(404, "未找到指定的父级字典", null));
|
||||
}
|
||||
|
||||
existingDictionary.Label = dictionary.Label;
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "更新父级字典成功", existingDictionary));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> DeleteParentDictionary([FromBody] string uuid)
|
||||
{
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(uuid))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Uuid", null));
|
||||
}
|
||||
|
||||
var parentDictionary = _dbContext.Dictionaries.FirstOrDefault(d => d.Uuid == uuid && d.ParentId == null);
|
||||
if (parentDictionary == null)
|
||||
{
|
||||
return Ok(new ReturnTemplate(404, "未找到指定的父级字典", null));
|
||||
}
|
||||
|
||||
_dbContext.Dictionaries.RemoveRange(_dbContext.Dictionaries.Where(d => d.ParentId == uuid));
|
||||
_dbContext.Dictionaries.Remove(parentDictionary);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "删除父级字典成功", null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> CreateChildDictionary([FromBody] DictionaryModel dictionary)
|
||||
{
|
||||
|
||||
|
||||
if (dictionary == null || string.IsNullOrWhiteSpace(dictionary.ParentId) || string.IsNullOrWhiteSpace(dictionary.ParentValue) || string.IsNullOrWhiteSpace(dictionary.Label) || string.IsNullOrWhiteSpace(dictionary.Value))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供ParentId、ParentValue、Label和Value", null));
|
||||
}
|
||||
|
||||
dictionary.Uuid = Guid.NewGuid().ToString();
|
||||
dictionary.CreateTime = DateTime.UtcNow;
|
||||
dictionary.CreateUserId = _userManager.GetUserId(User);
|
||||
|
||||
_dbContext.Dictionaries.Add(dictionary);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "创建子级字典成功", dictionary));
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> UpdateChildDictionary([FromBody] DictionaryModel dictionary)
|
||||
{
|
||||
|
||||
|
||||
if (dictionary == null || string.IsNullOrWhiteSpace(dictionary.Uuid) || string.IsNullOrWhiteSpace(dictionary.Label) || string.IsNullOrWhiteSpace(dictionary.Value))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Uuid、Label和Value", null));
|
||||
}
|
||||
|
||||
var existingDictionary = _dbContext.Dictionaries.FirstOrDefault(d => d.Uuid == dictionary.Uuid && d.ParentId != null);
|
||||
if (existingDictionary == null)
|
||||
{
|
||||
return Ok(new ReturnTemplate(404, "未找到指定的子级字典", null));
|
||||
}
|
||||
|
||||
existingDictionary.Label = dictionary.Label;
|
||||
existingDictionary.LabelEn = dictionary.LabelEn;
|
||||
existingDictionary.Remark = dictionary.Remark;
|
||||
existingDictionary.Value = dictionary.Value;
|
||||
existingDictionary.Tag = dictionary.Tag;
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "更新子级字典成功", existingDictionary));
|
||||
}
|
||||
|
||||
[HttpDelete]
|
||||
[Authorize(Roles = "Admin")]
|
||||
public async Task<IActionResult> DeleteChildDictionary([FromBody] string uuid)
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(uuid))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Uuid", null));
|
||||
}
|
||||
|
||||
var childDictionary = _dbContext.Dictionaries.FirstOrDefault(d => d.Uuid == uuid && d.ParentId != null);
|
||||
if (childDictionary == null)
|
||||
{
|
||||
return Ok(new ReturnTemplate(404, "未找到指定的子级字典", null));
|
||||
}
|
||||
|
||||
_dbContext.Dictionaries.Remove(childDictionary);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
return Ok(new ReturnTemplate(200, "删除子级字典成功", null));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult GetChildDictionaries([FromBody] ChildDictionaryRequest request)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Value))
|
||||
{
|
||||
return Ok(new ReturnTemplate(400, "请求参数无效,请提供Value", null));
|
||||
}
|
||||
|
||||
var childDictionaries = _dbContext.Dictionaries
|
||||
.Where(d => d.ParentValue == request.Value &&
|
||||
(request.Tag == null || (!string.IsNullOrEmpty(d.Tag) && d.Tag.Contains("," + request.Tag + ","))))
|
||||
.ToList();
|
||||
|
||||
if (request.Tag != null)
|
||||
{
|
||||
childDictionaries = childDictionaries.Where(d => !string.IsNullOrEmpty(d.Tag)).ToList();
|
||||
}
|
||||
|
||||
return Ok(new ReturnTemplate(200, "查询成功", childDictionaries));
|
||||
}
|
||||
public class ChildDictionaryRequest
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public string Tag { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -18,8 +18,8 @@ namespace AGSS.Controllers.Admin;
|
||||
/// 控制器类,用于管理角色相关的操作,包括添加角色、分配角色给用户以及通过角色查询用户。
|
||||
/// 该控制器仅限具有"Admin"角色的用户访问。
|
||||
/// </summary>
|
||||
[Authorize]
|
||||
[Route("api/v1/[controller]/[action]")]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[Route("api/v1/[controller]")]
|
||||
public class AdminRoleControllers:ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
@ -60,7 +60,7 @@ public class AdminRoleControllers:ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="role">要添加的角色信息</param>
|
||||
/// <returns>返回操作结果,包含状态码、消息和数据</returns>
|
||||
[HttpPost]
|
||||
[HttpPost("role")]
|
||||
public async Task<IActionResult> AddRole(string rolename,string normalizedname)
|
||||
{
|
||||
|
||||
@ -84,7 +84,8 @@ public class AdminRoleControllers:ControllerBase
|
||||
/// <param name="userId">用户的唯一标识符</param>
|
||||
/// <param name="roleName">要分配的角色名称</param>
|
||||
/// <returns>返回一个包含操作结果的ReturnTemplate对象,其中Code表示状态码,Msg表示消息,Data表示附加数据(如果有的话)</returns>
|
||||
[HttpPost]
|
||||
|
||||
[HttpPost("role/endow")]
|
||||
public async Task<IActionResult> EndowRole(string userId, string roleName)
|
||||
{
|
||||
var user = await _userManager.FindByIdAsync(userId);
|
||||
@ -116,7 +117,7 @@ public class AdminRoleControllers:ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="userId">要删除的用户的唯一标识符。</param>
|
||||
/// <returns>返回操作结果,包含状态码、消息和数据。如果删除成功,则返回200状态码;如果用户ID为空或未找到指定用户,则分别返回400或404状态码;若删除过程中出现错误,则返回500状态码并附带错误信息。</returns>
|
||||
[HttpPost]
|
||||
[HttpDelete("user")]
|
||||
public async Task<IActionResult> DelUser(string userId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
@ -143,7 +144,7 @@ public class AdminRoleControllers:ControllerBase
|
||||
}
|
||||
|
||||
|
||||
[HttpPost]
|
||||
[HttpPost("menu")]
|
||||
public async Task<IActionResult> SetMenu([FromBody]UserMenuRequest request)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(request.Id) || string.IsNullOrWhiteSpace(request.MenuName))
|
||||
@ -169,7 +170,7 @@ public class AdminRoleControllers:ControllerBase
|
||||
|
||||
|
||||
}
|
||||
[HttpGet]
|
||||
[HttpGet("role/all")]
|
||||
public async Task<IActionResult> AllRole()
|
||||
{
|
||||
|
||||
@ -184,7 +185,7 @@ public class AdminRoleControllers:ControllerBase
|
||||
/// </summary>
|
||||
/// <param name="request">包含角色名称、页码和每页大小的请求对象</param>
|
||||
/// <returns>返回包含总用户数和当前页用户的响应对象</returns>
|
||||
[HttpPost]
|
||||
[HttpPost("user")]
|
||||
public async Task<IActionResult> SearchUserFromRole([FromBody] SearchUserFromRoleRequest request)
|
||||
{
|
||||
|
||||
|
228
AGSS/Controllers/Dict/DictController.cs
Normal file
228
AGSS/Controllers/Dict/DictController.cs
Normal file
@ -0,0 +1,228 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using AGSS.Models.Template;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AGSS.Controllers.Dict
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
// [Produces("application/json")]
|
||||
public class DictController : ControllerBase
|
||||
{
|
||||
private readonly DictService _dictService;
|
||||
private readonly ILogger<DictController> _logger;
|
||||
|
||||
public DictController(DictService dictService, ILogger<DictController> logger)
|
||||
{
|
||||
_dictService = dictService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
// 1. 获取父级列表
|
||||
[HttpGet("parents")]
|
||||
public async Task<ActionResult> GetParents([FromQuery] string? label)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _dictService.GetParentsAsync(label);
|
||||
return Ok(new ReturnTemplate(200, "获取成功啦!", result));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(500, "失败,服务器类错误!", ex));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 创建父级项
|
||||
|
||||
// [Authorize(Roles = "Admin")]
|
||||
[HttpPost("parents")]
|
||||
public async Task<ActionResult> CreateParent([FromBody] CreateParentRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _dictService.CreateParentAsync(request.Label, request.Value);
|
||||
return Ok(new ReturnTemplate(200, "创建成功啦!", result));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(500, "错误", ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
// 请求模型
|
||||
public class CreateParentRequest
|
||||
{
|
||||
[Required(ErrorMessage = "字典标签不能为空")]
|
||||
[StringLength(100, ErrorMessage = "标签长度不能超过100字符")]
|
||||
public string Label { get; set; } = null!;
|
||||
|
||||
[Required(ErrorMessage = "字典值不能为空")]
|
||||
[StringLength(50, ErrorMessage = "值长度不能超过50字符")]
|
||||
public string Value { get; set; } = null!;
|
||||
}
|
||||
|
||||
// 2.1 更新父级项
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPut("parents/{uuid}")]
|
||||
public async Task<ActionResult> UpdateParent(
|
||||
[FromRoute] Guid uuid,
|
||||
[FromBody] UpdateParentRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dictService.UpdateParentAsync(uuid, request.Label);
|
||||
return Ok(new ReturnTemplate(200, "创建成功啦!", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "失败", ex));
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateParentRequest
|
||||
{
|
||||
[Required(ErrorMessage = "字典标签不能为空")]
|
||||
[StringLength(100, ErrorMessage = "标签长度不能超过100字符")]
|
||||
public string Label { get; set; } = null!;
|
||||
}
|
||||
|
||||
// 3. 删除父级项
|
||||
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpDelete("parents/{uuid}")]
|
||||
public async Task<ActionResult> DeleteParent([FromRoute] Guid uuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dictService.DeleteParentAsync(uuid);
|
||||
return Ok(new ReturnTemplate(200, "删除成功啦!", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "失败", ex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 4. 创建子项
|
||||
[HttpPost("children")]
|
||||
public async Task<ActionResult> CreateChild([FromBody] CreateChildRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _dictService.CreateChildAsync(
|
||||
request.ParentId,
|
||||
request.ParentValue,
|
||||
request.Label,
|
||||
request.Value,
|
||||
request.LabelEn,
|
||||
request.Remark,
|
||||
request.Tag);
|
||||
|
||||
return Ok(new ReturnTemplate(200, "创建成功啦!", result));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "我们遇到了一些问题,无法删除!", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateChildRequest
|
||||
{
|
||||
[Required(ErrorMessage = "父级ID不能为空")] public Guid ParentId { get; set; }
|
||||
|
||||
[Required(ErrorMessage = "父级值不能为空")] public string ParentValue { get; set; } = null!;
|
||||
|
||||
[Required(ErrorMessage = "字典标签不能为空")] public string Label { get; set; } = null!;
|
||||
|
||||
[Required(ErrorMessage = "字典值不能为空")] public string Value { get; set; } = null!;
|
||||
|
||||
public string? LabelEn { get; set; }
|
||||
public string? Remark { get; set; }
|
||||
public string? Tag { get; set; }
|
||||
}
|
||||
|
||||
// 4.1 更新子项
|
||||
[HttpPut("children/{uuid}")]
|
||||
public async Task<ActionResult> UpdateChild(
|
||||
[FromRoute] Guid uuid,
|
||||
[FromBody] UpdateChildRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dictService.UpdateChildAsync(
|
||||
uuid,
|
||||
request.Label,
|
||||
request.Value,
|
||||
request.LabelEn,
|
||||
request.Remark,
|
||||
request.Tag);
|
||||
|
||||
return Ok(new ReturnTemplate(200, "更新成功啦!", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "失败!", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public class UpdateChildRequest
|
||||
{
|
||||
[Required(ErrorMessage = "字典标签不能为空")] public string Label { get; set; } = null!;
|
||||
|
||||
[Required(ErrorMessage = "字典值不能为空")] public string Value { get; set; } = null!;
|
||||
|
||||
public string? LabelEn { get; set; }
|
||||
public string? Remark { get; set; }
|
||||
public string? Tag { get; set; }
|
||||
}
|
||||
|
||||
// 5. 删除子项
|
||||
[HttpDelete("children/{uuid}")]
|
||||
public async Task<ActionResult> DeleteChild([FromRoute] Guid uuid)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dictService.DeleteChildAsync(uuid);
|
||||
return Ok(new ReturnTemplate(200, "删除成功啦!", ""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "删除失败!", ""));
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 获取子项
|
||||
[HttpGet("children")]
|
||||
public async Task<ActionResult> GetChildren(
|
||||
[FromQuery, Required] string value,
|
||||
[FromQuery] string? tag = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _dictService.GetChildrenAsync(value, tag);
|
||||
return Ok(new ReturnTemplate(200, "查询成功啦!", result));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Ok(new ReturnTemplate(200, "查询失败!", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 统一响应模型
|
||||
public class ApiResponse
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class ApiResponse<T> : ApiResponse
|
||||
{
|
||||
public T? Data { get; set; }
|
||||
}
|
||||
}
|
@ -4,27 +4,58 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AGSS.DbSet
|
||||
{
|
||||
public class ApplicationDbContext : IdentityDbContext<UserModel,RoleModel,string>
|
||||
public class ApplicationDbContext : IdentityDbContext<UserModel, RoleModel, string>
|
||||
{
|
||||
|
||||
public override DbSet<UserModel> Users { get; set; }
|
||||
public override DbSet<RoleModel> Roles { get; set; }
|
||||
public DbSet<DictionaryModel> Dictionaries { get; set; }
|
||||
public DbSet<DictItem> DictItems { get; set; }
|
||||
public DbSet<MenuModel> Menus { get; set; }
|
||||
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
modelBuilder.Entity<DictItem>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Uuid);
|
||||
entity.Property(e => e.ParentId).HasColumnName("parentid");
|
||||
entity.Property(e => e.Tag).HasColumnName("tag");
|
||||
entity.Property(e => e.CreateTime).HasColumnName("createtime");
|
||||
entity.Property(e => e.ParentValue).HasColumnName("parentvalue");
|
||||
entity.Property(e => e.Value).HasColumnName("value");
|
||||
entity.Property(e => e.Label).HasColumnName("label");
|
||||
entity.Property(e => e.Tag).HasColumnName("tag");
|
||||
});
|
||||
|
||||
// 配置自引用关系
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasOne(d => d.Parent)
|
||||
.WithMany(d => d.Children)
|
||||
.HasForeignKey(d => d.ParentId)
|
||||
.OnDelete(DeleteBehavior.Cascade); // 级联删除
|
||||
|
||||
// 添加索引
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasIndex(d => d.ParentId);
|
||||
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasIndex(d => d.ParentValue);
|
||||
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasIndex(d => d.Value);
|
||||
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasIndex(d => d.Tag);
|
||||
|
||||
// 确保顶级项的约束
|
||||
modelBuilder.Entity<DictItem>()
|
||||
.HasCheckConstraint("CK_TopLevelItems",
|
||||
"ParentId IS NULL OR (Tag IS NOT NULL AND ParentValue IS NOT NULL)");
|
||||
|
||||
|
||||
modelBuilder.Entity<DictionaryModel>()
|
||||
.HasKey(d => d.Uuid); // 假设 Id 是 DictionaryModel 的主键字段
|
||||
|
||||
modelBuilder.Entity<MenuModel>()
|
||||
.HasKey(m => m.Uuid);
|
||||
|
@ -1,425 +0,0 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using AGSS.DbSet;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AGSS.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20250714035418_AddMenuTableV2")]
|
||||
partial class AddMenuTableV2
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.6")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.DictionaryModel", b =>
|
||||
{
|
||||
b.Property<string>("Uuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CreateUserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LabelEn")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ParentValue")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Remark")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Uuid");
|
||||
|
||||
b.ToTable("Dictionaries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.MenuModel", b =>
|
||||
{
|
||||
b.Property<string>("Uuid")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Adaptability")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<string>("Component")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<DateTime>("CreateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Icon")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("MenuCode")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Query")
|
||||
.HasMaxLength(1000)
|
||||
.HasColumnType("character varying(1000)");
|
||||
|
||||
b.Property<int>("Sort")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasMaxLength(1)
|
||||
.HasColumnType("character varying(1)");
|
||||
|
||||
b.Property<DateTime?>("UpdateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Uuid");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.ToTable("Menus");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.RoleModel", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.UserModel", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Birthday")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("character varying(20)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Config")
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("character varying(200)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("JobCode")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character varying(10)");
|
||||
|
||||
b.Property<string>("JobName")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character varying(10)");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("MenuCode")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("MenuName")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Sex")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("character varying(256)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.MenuModel", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.MenuModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.RoleModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.UserModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.UserModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.RoleModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("AGSS.Models.Entities.UserModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.UserModel", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace AGSS.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddMenuTableV2 : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -22,51 +22,6 @@ namespace AGSS.Migrations
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.DictionaryModel", b =>
|
||||
{
|
||||
b.Property<string>("Uuid")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("CreateUserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LabelEn")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ParentId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ParentValue")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Remark")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tag")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Uuid");
|
||||
|
||||
b.ToTable("Dictionaries");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AGSS.Models.Entities.MenuModel", b =>
|
||||
{
|
||||
b.Property<string>("Uuid")
|
||||
@ -252,6 +207,68 @@ namespace AGSS.Migrations
|
||||
b.ToTable("AspNetUsers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DictItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Uuid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreateTime")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("createtime");
|
||||
|
||||
b.Property<Guid>("CreateUserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)")
|
||||
.HasColumnName("label");
|
||||
|
||||
b.Property<string>("LabelEn")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("character varying(100)");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid")
|
||||
.HasColumnName("parentid");
|
||||
|
||||
b.Property<string>("ParentValue")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("parentvalue");
|
||||
|
||||
b.Property<string>("Remark")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)");
|
||||
|
||||
b.Property<string>("Tag")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("character varying(500)")
|
||||
.HasColumnName("tag");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("character varying(50)")
|
||||
.HasColumnName("value");
|
||||
|
||||
b.HasKey("Uuid");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("ParentValue");
|
||||
|
||||
b.HasIndex("Tag");
|
||||
|
||||
b.HasIndex("Value");
|
||||
|
||||
b.ToTable("DictItems", t =>
|
||||
{
|
||||
t.HasCheckConstraint("CK_TopLevelItems", "ParentId IS NULL OR (Tag IS NOT NULL AND ParentValue IS NOT NULL)");
|
||||
});
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -366,6 +383,16 @@ namespace AGSS.Migrations
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DictItem", b =>
|
||||
{
|
||||
b.HasOne("DictItem", "Parent")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("AGSS.Models.Entities.RoleModel", null)
|
||||
@ -416,6 +443,11 @@ namespace AGSS.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DictItem", b =>
|
||||
{
|
||||
b.Navigation("Children");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ namespace AGSS.Models.DTOs
|
||||
public string ParentId { get; set; }
|
||||
public string ParentValue { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string LabelEn { get; set; }
|
||||
public string Remark { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string Tag { get; set; }
|
||||
|
@ -1,18 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
namespace AGSS.Models.Entities
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
public class DictItem
|
||||
{
|
||||
public class DictionaryModel
|
||||
{
|
||||
public string Uuid { get; set; }
|
||||
public string ParentId { get; set; }
|
||||
public string ParentValue { get; set; }
|
||||
public string Label { get; set; }
|
||||
public string LabelEn { get; set; }
|
||||
public string Remark { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string Tag { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
public string CreateUserId { get; set; }
|
||||
}
|
||||
}
|
||||
// 主键
|
||||
public Guid Uuid { get; set; } = Guid.NewGuid();
|
||||
|
||||
// 层级关系
|
||||
public Guid? ParentId { get; set; }
|
||||
public string? ParentValue { get; set; }
|
||||
|
||||
// 基础信息
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Label { get; set; } = null!; // 中文标签
|
||||
|
||||
[StringLength(100)]
|
||||
public string? LabelEn { get; set; } // 英文标签
|
||||
|
||||
[StringLength(500)]
|
||||
public string? Remark { get; set; } // 备注
|
||||
|
||||
[Required]
|
||||
[StringLength(50)]
|
||||
public string Value { get; set; } = null!; // 字典值
|
||||
|
||||
[StringLength(500)]
|
||||
public string? Tag { get; set; } // 逗号分隔的标签
|
||||
|
||||
// 审计字段
|
||||
public DateTime CreateTime { get; set; } = DateTime.UtcNow;
|
||||
public Guid CreateUserId { get; set; }
|
||||
|
||||
// 导航属性
|
||||
public DictItem? Parent { get; set; }
|
||||
public ICollection<DictItem> Children { get; set; } = new List<DictItem>();
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using AGSS.DbSet;
|
||||
using AGSS.Models;
|
||||
@ -56,6 +57,8 @@ builder.Services.AddIdentityCore<UserModel>(options =>
|
||||
builder.Services.AddScoped<Jwt>();
|
||||
builder.Services.AddScoped<UserService>();
|
||||
builder.Services.AddScoped<MenuService>();
|
||||
builder.Services.AddScoped<DictService>();
|
||||
builder.Services.AddScoped<ICurrentUserService, CurrentUserService>();
|
||||
|
||||
|
||||
|
||||
@ -82,6 +85,10 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
builder.Services.Configure<JwtBearerOptions>(options =>
|
||||
{
|
||||
options.TokenValidationParameters.RoleClaimType = "role";
|
||||
});
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
|
25
AGSS/Services/CurrentUserService.cs
Normal file
25
AGSS/Services/CurrentUserService.cs
Normal file
@ -0,0 +1,25 @@
|
||||
// 用于获取当前用户信息
|
||||
|
||||
using System.Security.Claims;
|
||||
|
||||
public interface ICurrentUserService
|
||||
{
|
||||
Guid UserId { get; }
|
||||
bool IsAdmin { get; }
|
||||
}
|
||||
|
||||
public class CurrentUserService : ICurrentUserService
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
}
|
||||
|
||||
public Guid UserId =>
|
||||
Guid.Parse(_httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value);
|
||||
|
||||
public bool IsAdmin =>
|
||||
_httpContextAccessor.HttpContext?.User?.IsInRole("luolan") ?? false;
|
||||
}
|
175
AGSS/Services/DictService.cs
Normal file
175
AGSS/Services/DictService.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using AGSS.DbSet;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
public class DictService
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
|
||||
public DictService(ApplicationDbContext context, ICurrentUserService currentUserService)
|
||||
{
|
||||
_context = context;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
|
||||
|
||||
// 1. 获取父级列表
|
||||
public async Task<List<DictItem>> GetParentsAsync(string? label)
|
||||
{
|
||||
var query = _context.DictItems
|
||||
.Where(d => d.ParentId == null);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(label))
|
||||
{
|
||||
query = query.Where(d => d.Label.Contains(label));
|
||||
}
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
// 2. 创建父级项
|
||||
public async Task<DictItem> CreateParentAsync(string label, string value)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var newItem = new DictItem
|
||||
{
|
||||
Label = label,
|
||||
Value = value,
|
||||
CreateUserId = _currentUserService.UserId
|
||||
};
|
||||
|
||||
_context.DictItems.Add(newItem);
|
||||
await _context.SaveChangesAsync();
|
||||
return newItem;
|
||||
}
|
||||
|
||||
// 2.1 更新父级项
|
||||
public async Task UpdateParentAsync(Guid uuid, string label)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var item = await _context.DictItems
|
||||
.FirstOrDefaultAsync(d => d.Uuid == uuid && d.ParentId == null);
|
||||
|
||||
if (item == null) throw new KeyNotFoundException("字典项不存在");
|
||||
|
||||
item.Label = label;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// 3. 删除父级项(级联删除)
|
||||
public async Task DeleteParentAsync(Guid uuid)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var item = await _context.DictItems
|
||||
.Include(d => d.Children)
|
||||
.FirstOrDefaultAsync(d => d.Uuid == uuid && d.ParentId == null);
|
||||
|
||||
if (item == null) throw new KeyNotFoundException("字典项不存在");
|
||||
|
||||
_context.DictItems.Remove(item);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// 4. 创建子项
|
||||
public async Task<DictItem> CreateChildAsync(
|
||||
Guid parentId,
|
||||
string parentValue,
|
||||
string label,
|
||||
string value,
|
||||
string? labelEn = null,
|
||||
string? remark = null,
|
||||
string? tag = null)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var parent = await _context.DictItems
|
||||
.FirstOrDefaultAsync(d => d.Uuid == parentId && d.ParentId == null);
|
||||
|
||||
if (parent == null) throw new KeyNotFoundException("父级字典项不存在");
|
||||
|
||||
var newItem = new DictItem
|
||||
{
|
||||
ParentId = parentId,
|
||||
ParentValue = parentValue,
|
||||
Label = label,
|
||||
Value = value,
|
||||
LabelEn = labelEn,
|
||||
Remark = remark,
|
||||
Tag = tag,
|
||||
CreateUserId = _currentUserService.UserId
|
||||
};
|
||||
|
||||
_context.DictItems.Add(newItem);
|
||||
await _context.SaveChangesAsync();
|
||||
return newItem;
|
||||
}
|
||||
|
||||
// 4.1 更新子项
|
||||
public async Task UpdateChildAsync(
|
||||
Guid uuid,
|
||||
string label,
|
||||
string value,
|
||||
string? labelEn = null,
|
||||
string? remark = null,
|
||||
string? tag = null)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var item = await _context.DictItems
|
||||
.FirstOrDefaultAsync(d => d.Uuid == uuid && d.ParentId != null);
|
||||
|
||||
if (item == null) throw new KeyNotFoundException("字典项不存在");
|
||||
|
||||
item.Label = label;
|
||||
item.Value = value;
|
||||
item.LabelEn = labelEn;
|
||||
item.Remark = remark;
|
||||
item.Tag = tag;
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// 5. 删除子项
|
||||
public async Task DeleteChildAsync(Guid uuid)
|
||||
{
|
||||
if (!_currentUserService.IsAdmin)
|
||||
throw new UnauthorizedAccessException("您不是管理员,无权限");
|
||||
|
||||
var item = await _context.DictItems
|
||||
.FirstOrDefaultAsync(d => d.Uuid == uuid && d.ParentId != null);
|
||||
|
||||
if (item == null) throw new KeyNotFoundException("字典项不存在");
|
||||
|
||||
_context.DictItems.Remove(item);
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// 6. 获取子项(带标签过滤)
|
||||
public async Task<List<DictItem>> GetChildrenAsync(string value, string? tag = null)
|
||||
{
|
||||
var query = _context.DictItems
|
||||
.Where(d => d.ParentValue == value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
{
|
||||
// 精确标签匹配逻辑
|
||||
var tags = tag.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(t => t.Trim())
|
||||
.ToList();
|
||||
|
||||
query = query.Where(d => d.Tag != null &&
|
||||
tags.All(t => d.Tag.Contains(t)));
|
||||
}
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
}
|
117
script.sql
117
script.sql
@ -1,105 +1,32 @@
|
||||
CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
||||
"MigrationId" character varying(150) NOT NULL,
|
||||
"ProductVersion" character varying(32) NOT NULL,
|
||||
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
|
||||
START TRANSACTION;
|
||||
DROP TABLE "Dictionaries";
|
||||
|
||||
CREATE TABLE "DictItems" (
|
||||
"Uuid" uuid NOT NULL,
|
||||
parentid uuid,
|
||||
parentvalue text,
|
||||
label character varying(100) NOT NULL,
|
||||
"LabelEn" character varying(100),
|
||||
"Remark" character varying(500),
|
||||
value character varying(50) NOT NULL,
|
||||
tag character varying(500),
|
||||
createtime timestamp with time zone NOT NULL,
|
||||
"CreateUserId" uuid NOT NULL,
|
||||
CONSTRAINT "PK_DictItems" PRIMARY KEY ("Uuid"),
|
||||
CONSTRAINT "CK_TopLevelItems" CHECK (ParentId IS NULL OR (Tag IS NOT NULL AND ParentValue IS NOT NULL)),
|
||||
CONSTRAINT "FK_DictItems_DictItems_parentid" FOREIGN KEY (parentid) REFERENCES "DictItems" ("Uuid") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
START TRANSACTION;
|
||||
CREATE TABLE "AspNetRoles" (
|
||||
"Id" text NOT NULL,
|
||||
"Name" character varying(256),
|
||||
"NormalizedName" character varying(256),
|
||||
"ConcurrencyStamp" text,
|
||||
CONSTRAINT "PK_AspNetRoles" PRIMARY KEY ("Id")
|
||||
);
|
||||
CREATE INDEX "IX_DictItems_parentid" ON "DictItems" (parentid);
|
||||
|
||||
CREATE TABLE "AspNetUsers" (
|
||||
"Id" text NOT NULL,
|
||||
"Sex" text,
|
||||
"Description" character varying(100),
|
||||
"Config" character varying(200),
|
||||
"JobCode" character varying(10),
|
||||
"JobName" character varying(10),
|
||||
"Birthday" character varying(20),
|
||||
"MenuCode" character varying(500),
|
||||
"MenuName" character varying(500),
|
||||
"UserName" character varying(256),
|
||||
"NormalizedUserName" character varying(256),
|
||||
"Email" character varying(256),
|
||||
"NormalizedEmail" character varying(256),
|
||||
"EmailConfirmed" boolean NOT NULL,
|
||||
"PasswordHash" text,
|
||||
"SecurityStamp" text,
|
||||
"ConcurrencyStamp" text,
|
||||
"PhoneNumber" text,
|
||||
"PhoneNumberConfirmed" boolean NOT NULL,
|
||||
"TwoFactorEnabled" boolean NOT NULL,
|
||||
"LockoutEnd" timestamp with time zone,
|
||||
"LockoutEnabled" boolean NOT NULL,
|
||||
"AccessFailedCount" integer NOT NULL,
|
||||
CONSTRAINT "PK_AspNetUsers" PRIMARY KEY ("Id")
|
||||
);
|
||||
CREATE INDEX "IX_DictItems_parentvalue" ON "DictItems" (parentvalue);
|
||||
|
||||
CREATE TABLE "AspNetRoleClaims" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
|
||||
"RoleId" text NOT NULL,
|
||||
"ClaimType" text,
|
||||
"ClaimValue" text,
|
||||
CONSTRAINT "PK_AspNetRoleClaims" PRIMARY KEY ("Id"),
|
||||
CONSTRAINT "FK_AspNetRoleClaims_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX "IX_DictItems_tag" ON "DictItems" (tag);
|
||||
|
||||
CREATE TABLE "AspNetUserClaims" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
|
||||
"UserId" text NOT NULL,
|
||||
"ClaimType" text,
|
||||
"ClaimValue" text,
|
||||
CONSTRAINT "PK_AspNetUserClaims" PRIMARY KEY ("Id"),
|
||||
CONSTRAINT "FK_AspNetUserClaims_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE "AspNetUserLogins" (
|
||||
"LoginProvider" text NOT NULL,
|
||||
"ProviderKey" text NOT NULL,
|
||||
"ProviderDisplayName" text,
|
||||
"UserId" text NOT NULL,
|
||||
CONSTRAINT "PK_AspNetUserLogins" PRIMARY KEY ("LoginProvider", "ProviderKey"),
|
||||
CONSTRAINT "FK_AspNetUserLogins_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE "AspNetUserRoles" (
|
||||
"UserId" text NOT NULL,
|
||||
"RoleId" text NOT NULL,
|
||||
CONSTRAINT "PK_AspNetUserRoles" PRIMARY KEY ("UserId", "RoleId"),
|
||||
CONSTRAINT "FK_AspNetUserRoles_AspNetRoles_RoleId" FOREIGN KEY ("RoleId") REFERENCES "AspNetRoles" ("Id") ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_AspNetUserRoles_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE "AspNetUserTokens" (
|
||||
"UserId" text NOT NULL,
|
||||
"LoginProvider" text NOT NULL,
|
||||
"Name" text NOT NULL,
|
||||
"Value" text,
|
||||
CONSTRAINT "PK_AspNetUserTokens" PRIMARY KEY ("UserId", "LoginProvider", "Name"),
|
||||
CONSTRAINT "FK_AspNetUserTokens_AspNetUsers_UserId" FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX "IX_AspNetRoleClaims_RoleId" ON "AspNetRoleClaims" ("RoleId");
|
||||
|
||||
CREATE UNIQUE INDEX "RoleNameIndex" ON "AspNetRoles" ("NormalizedName");
|
||||
|
||||
CREATE INDEX "IX_AspNetUserClaims_UserId" ON "AspNetUserClaims" ("UserId");
|
||||
|
||||
CREATE INDEX "IX_AspNetUserLogins_UserId" ON "AspNetUserLogins" ("UserId");
|
||||
|
||||
CREATE INDEX "IX_AspNetUserRoles_RoleId" ON "AspNetUserRoles" ("RoleId");
|
||||
|
||||
CREATE INDEX "EmailIndex" ON "AspNetUsers" ("NormalizedEmail");
|
||||
|
||||
CREATE UNIQUE INDEX "UserNameIndex" ON "AspNetUsers" ("NormalizedUserName");
|
||||
CREATE INDEX "IX_DictItems_value" ON "DictItems" (value);
|
||||
|
||||
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES ('20250709144855_Initial', '9.0.6');
|
||||
VALUES ('20250715135627_dic1', '9.0.6');
|
||||
|
||||
COMMIT;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user