first commit
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using F9WebAiTest.Domain.Enums.SYS.RBAC;
|
||||
using F9WebAiTest.Domain.Events.SYS.RBAC;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>资源:权限作用的对象,如菜单项、按钮、报表等。</summary>
|
||||
[Table(Name = "sys_rbac_menus")]
|
||||
public class Menu : AggregateRoot
|
||||
{
|
||||
[Column(Name = "icon_svg")]
|
||||
public string IconSvg { get; private set; } // 图标
|
||||
|
||||
[Column(Name = "code")]
|
||||
public string Code { get; private set; } // 唯一标识
|
||||
|
||||
[Column(Name = "name")]
|
||||
public string Name { get; private set; } // 显示名称
|
||||
|
||||
[Column(Name = "menu_type")]
|
||||
public MenuType_Enum MenuType { get; private set; } // 菜单类型:分组/页面
|
||||
|
||||
[Column(Name = "assembly_name")]
|
||||
public string? AssemblyName { get; private set; }
|
||||
|
||||
[Column(Name = "type_full_name")]
|
||||
public string? TypeFullName { get; private set; }
|
||||
|
||||
[Column(Name = "parent_id")]
|
||||
public long ParentId { get; private set; } // 支持菜单层级
|
||||
|
||||
[Column(Name = "level")]
|
||||
public int Level { get; private set; } // 层级
|
||||
|
||||
[Column(Name = "is_active")]
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
[Column(Name = "sort_order")]
|
||||
public int SortOrder { get; private set; }
|
||||
|
||||
[Column(Name = "path")]
|
||||
public string Path { get; private set; } = ""; // Web 路由路径
|
||||
|
||||
[Column(Name = "component")]
|
||||
public string Component { get; private set; } = ""; // 前端组件路径
|
||||
|
||||
[Column(Name = "permission")]
|
||||
public string Permission { get; private set; } = ""; // 权限标识,如 sys:user:list
|
||||
|
||||
public Menu() { }
|
||||
|
||||
public Menu(long id, string name, string iconSvg, MenuType_Enum menuType = MenuType_Enum.默认,
|
||||
string? assemblyName = null, string? typeFullName = null, long parentId = 0, int sortOrder = 0, int parentLevel = 0)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
IconSvg = iconSvg;
|
||||
MenuType = menuType;
|
||||
AssemblyName = assemblyName;
|
||||
TypeFullName = typeFullName;
|
||||
ParentId = parentId;
|
||||
Level = parentId == 0 ? 1 : parentLevel + 1;
|
||||
IsActive = true;
|
||||
CreatedAt = DateTime.Now;
|
||||
SortOrder = sortOrder;
|
||||
AddDomainEvent(new Menu_ChangedDomainEvent(Id));
|
||||
}
|
||||
|
||||
public void GenerateNewCode() => Code = $"menu.{DateTime.Now.Ticks}";
|
||||
|
||||
/// <summary>设置 Web 路由信息(路径/组件/权限码)</summary>
|
||||
public void SetWebInfo(string path, string component, string permission)
|
||||
{
|
||||
Path = path ?? "";
|
||||
Component = component ?? "";
|
||||
Permission = permission ?? "";
|
||||
}
|
||||
|
||||
public IReadOnlySet<Permission_Type_Enum> SupportedPermissionType =>
|
||||
new HashSet<Permission_Type_Enum> { Permission_Type_Enum.Visble };
|
||||
|
||||
public void SoftDelete() => AddDomainEvent(new Menu_ChangedDomainEvent(Id));
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
IsActive = true;
|
||||
AddDomainEvent(new Menu_ChangedDomainEvent(Id));
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
IsActive = false;
|
||||
AddDomainEvent(new Menu_ChangedDomainEvent(Id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using F9WebAiTest.Domain.Enums.SYS.RBAC;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>权限:最小的权限单元,如“查看用户列表”、“导出报表”。</summary>
|
||||
[Table(Name = "sys_rbac_permissions")]
|
||||
public class Permission : AggregateRoot
|
||||
{
|
||||
/// <summary>编号,格式:资源:操作,例如 user:add, report:sales:view</summary>
|
||||
[Column(Name = "code")]
|
||||
public string Code { get; private set; }
|
||||
|
||||
[Column(Name = "permission_type")]
|
||||
public Permission_Type_Enum PermissionType { get; private set; }
|
||||
|
||||
[Column(Name = "resource_type")]
|
||||
public Resource_Type_Enum ResourceType { get; private set; }
|
||||
|
||||
[Column(Name = "resource_id")]
|
||||
public long ResourceId { get; private set; } // 关联资源(菜单、报表等)
|
||||
|
||||
public Permission() { }
|
||||
|
||||
public Permission(long id, Permission_Type_Enum permissionType, Resource_Type_Enum resourceType, string resourceIdentity, long resourceId)
|
||||
{
|
||||
Id = id;
|
||||
PermissionType = permissionType;
|
||||
ResourceType = resourceType;
|
||||
ResourceId = resourceId;
|
||||
CreatedAt = DateTime.Now;
|
||||
Code = $"{GetResorceTypeIdentity}:{resourceIdentity}:{permissionType.ToString().ToLower()}";
|
||||
}
|
||||
|
||||
public string GetResorceTypeIdentity => ResourceType switch
|
||||
{
|
||||
Resource_Type_Enum.菜单 => "menu",
|
||||
Resource_Type_Enum.报表 => "report",
|
||||
Resource_Type_Enum.操作 => "operation",
|
||||
Resource_Type_Enum.部门 => "department",
|
||||
Resource_Type_Enum.消息订阅 => "subscribe",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
/// <summary>自定义权限码(用于消息订阅等业务权限码与 RBAC 权限码保持一致)</summary>
|
||||
public void SetCode(string code) => Code = code;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using F9WebAiTest.Domain.Enums.SYS.RBAC;
|
||||
using F9WebAiTest.Domain.Events.SYS.RBAC;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>角色:一组权限的集合。</summary>
|
||||
[Table(Name = "sys_rbac_roles")]
|
||||
public class Role : AggregateRoot
|
||||
{
|
||||
[Column(Name = "name")]
|
||||
public string Name { get; private set; } // 如 "财务专员", "系统管理员"
|
||||
|
||||
[Column(Name = "code")]
|
||||
public string Code { get; private set; } // 如:role:xxxx
|
||||
|
||||
[Column(Name = "sort_order")]
|
||||
public int SortOrder { get; private set; }
|
||||
|
||||
[Column(Name = "description")]
|
||||
public string Description { get; private set; }
|
||||
|
||||
[Column(Name = "is_active")]
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
private readonly List<long> _permissionIds = [];
|
||||
public IReadOnlyCollection<long> PermissionIds => _permissionIds.AsReadOnly();
|
||||
|
||||
public Role() { }
|
||||
|
||||
public Role(long id, string name, string code, int sortOrder, string description)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Code = code;
|
||||
SortOrder = sortOrder;
|
||||
IsActive = true;
|
||||
Description = description;
|
||||
CreatedAt = DateTime.Now;
|
||||
}
|
||||
|
||||
public void Activate() => IsActive = true;
|
||||
public void Deactivate() => IsActive = false;
|
||||
|
||||
public void AddPermission(long permissionId, Resource_Type_Enum type)
|
||||
{
|
||||
if (!_permissionIds.Contains(permissionId))
|
||||
_permissionIds.Add(permissionId);
|
||||
|
||||
if (type == Resource_Type_Enum.菜单)
|
||||
AddDomainEvent(new RoleMenu_ChangedDomainEvent(Id));
|
||||
else if (type == Resource_Type_Enum.部门)
|
||||
AddDomainEvent(new RoleDepartment_ChangedDomainEvent(Id));
|
||||
}
|
||||
|
||||
public void RemovePermission(long permissionId, Resource_Type_Enum type)
|
||||
{
|
||||
_permissionIds.Remove(permissionId);
|
||||
|
||||
if (type == Resource_Type_Enum.菜单)
|
||||
AddDomainEvent(new RoleMenu_ChangedDomainEvent(Id));
|
||||
else if (type == Resource_Type_Enum.部门)
|
||||
AddDomainEvent(new RoleDepartment_ChangedDomainEvent(Id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>角色权限关联:角色与权限的多对多关系。</summary>
|
||||
[Table(Name = "sys_rbac_role_permissions")]
|
||||
public class RolePermission : BusinessEntity
|
||||
{
|
||||
[Column(Name = "role_id")]
|
||||
public long RoleId { get; private set; }
|
||||
|
||||
[Column(Name = "permission_id")]
|
||||
public long PermissionId { get; private set; }
|
||||
|
||||
public RolePermission() { }
|
||||
|
||||
public RolePermission(long id, long roleId, long permissionId)
|
||||
{
|
||||
Id = id;
|
||||
RoleId = roleId;
|
||||
PermissionId = permissionId;
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using F9WebAiTest.Domain.Events.SYS.RBAC;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>用户:可以拥有多个角色。</summary>
|
||||
[Table(Name = "sys_rbac_users")]
|
||||
public class User : AggregateRoot
|
||||
{
|
||||
[Column(Name = "department_id")]
|
||||
public long DepartmentId { get; private set; }
|
||||
|
||||
[Column(Name = "user_name")]
|
||||
public string UserName { get; private set; }
|
||||
|
||||
[Column(Name = "phone_number")]
|
||||
public string PhoneNumber { get; private set; }
|
||||
|
||||
[Column(Name = "login_name")]
|
||||
public string LoginName { get; private set; }
|
||||
|
||||
[Column(Name = "password_hash")]
|
||||
public string PasswordHash { get; private set; }
|
||||
|
||||
[Column(Name = "is_active")]
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
[Column(Name = "sort_order")]
|
||||
public int SortOrder { get; private set; }
|
||||
|
||||
[Column(Name = "lastlogin_at")]
|
||||
public DateTime? LastLoginAt { get; private set; }
|
||||
|
||||
[Column(Name = "nickname")]
|
||||
public string Nickname { get; private set; } = "";
|
||||
|
||||
[Column(Name = "avatar")]
|
||||
public string Avatar { get; private set; } = "";
|
||||
|
||||
[Column(Name = "email")]
|
||||
public string Email { get; private set; } = "";
|
||||
|
||||
[Column(Name = "gender")]
|
||||
public string Gender { get; private set; } = "男";
|
||||
|
||||
public User() { }
|
||||
|
||||
public User(long id, string userName, string phoneNumber, string loginName, long departmentId, int sortOrder)
|
||||
{
|
||||
Id = id;
|
||||
UserName = userName;
|
||||
PhoneNumber = phoneNumber;
|
||||
LoginName = loginName;
|
||||
DepartmentId = departmentId;
|
||||
IsActive = true;
|
||||
SortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public void Update(string userName, string phoneNumber, string loginName, long departmentId, int sortOrder)
|
||||
{
|
||||
UserName = userName;
|
||||
PhoneNumber = phoneNumber;
|
||||
LoginName = loginName;
|
||||
DepartmentId = departmentId;
|
||||
IsActive = true;
|
||||
SortOrder = sortOrder;
|
||||
}
|
||||
|
||||
public void Activate() => IsActive = true;
|
||||
public void Deactivate() => IsActive = false;
|
||||
|
||||
/// <summary>获取默认密码明文</summary>
|
||||
public string GetDefaultPasswordText() => "123456";
|
||||
|
||||
/// <summary>设置密码(哈希后的密文)</summary>
|
||||
public void SetPassword(string password) => PasswordHash = password;
|
||||
|
||||
/// <summary>更新个人资料(昵称/头像/邮箱/手机号/性别)</summary>
|
||||
public void UpdateProfile(string nickname, string avatar, string email, string phoneNumber, string gender)
|
||||
{
|
||||
Nickname = nickname ?? Nickname;
|
||||
Avatar = avatar ?? Avatar;
|
||||
Email = email ?? Email;
|
||||
PhoneNumber = phoneNumber ?? PhoneNumber;
|
||||
Gender = gender ?? Gender;
|
||||
}
|
||||
|
||||
/// <summary>登录成功,记录登录时间并发布登录事件</summary>
|
||||
public void LoginSuccess(string deviceId, string account, bool success, long userId, string userName)
|
||||
{
|
||||
LastLoginAt = DateTime.Now;
|
||||
AddDomainEvent(new UserLoginDomainEvent(deviceId, account, success, userId, userName));
|
||||
}
|
||||
|
||||
public void AddRole(long roleId) => AddDomainEvent(new UserRole_ChangedDomainEvent(Id));
|
||||
|
||||
public void RemoveRole(long roleId) => AddDomainEvent(new UserRole_ChangedDomainEvent(Id));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
|
||||
namespace F9WebAiTest.Domain.Entities.SYS.RBAC;
|
||||
|
||||
/// <summary>
|
||||
/// 用户角色关联:用户与角色的多对多关系。
|
||||
/// DDD 中作为独立关联实体,应用层直接操作其仓储(不通过 User 聚合)。
|
||||
/// </summary>
|
||||
[Table(Name = "sys_rbac_user_roles")]
|
||||
public class UserRole : BusinessEntity
|
||||
{
|
||||
[Column(Name = "user_id")]
|
||||
public long UserId { get; private set; }
|
||||
|
||||
[Column(Name = "role_id")]
|
||||
public long RoleId { get; private set; }
|
||||
|
||||
public UserRole() { }
|
||||
|
||||
public UserRole(long id, long userId, long roleId)
|
||||
{
|
||||
Id = id;
|
||||
UserId = userId;
|
||||
RoleId = roleId;
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user