first commit

This commit is contained in:
yanpeng200212
2026-10-08 10:43:59 +08:00
commit 8430ba0452
288 changed files with 29595 additions and 0 deletions
@@ -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;
}
}