一、权限业务介绍
本业务为个人试用期的时候的真实企业级业务,进行了简单的替换词和业务内容模糊,但是业务逻辑没有变化,值得学习,代码部分可能因为替换词有部分误解,发现问题请评论区提醒我。
这个业务教会了我,代码应当复用率高,操作应闭环简化,利用算法的思想,设计任务处理队列,进行批处理,一次性批处理,数据库应交互次数少,巧妙的利用LINQ语句,简化代码难度。
坚持看完,一定对你有所帮助,开头业务描述可能会有点枯燥,但是一定要看完
1. 业务字段介绍
权限数据库字段是这样的,权限种类有四种,决定一级权限的归属
权限种类: 2
一级权限: “R1”
二级权限: “String1,String2”
指的是一个人有2权限的R1中的Sstring1和2的权限
权限种类: 1
一级权限: " * "
二级权限: " * "
指的是一个人有1权限的全权限的权限
权限种类: 1
一级权限: " R1 "
二级权限: “String1,String2”
指的是一个人有1权限的全权限的权限
权限种类: 1
一级权限: " R2 "
二级权限: “String3”
指的是一个人有1权限的R1中的Sstring1和2,和R2的String3 的权限
2. 业务需求分析
2.1 保存接口
需要实现对用户的新增权限、修改(覆盖)权限、取消权限的综合性接口。
图示权限选择:
权限种类: 1(A)
一级权限: " R1 "
二级权限: “String3”
指的是一个人有1权限的全权限的权限
权限种类: 1(A)
一级权限: " R2 "
二级权限: “String1,String2”
指的是一个人有1权限的R1中的Sstring1和2,和R2的String3 的权限
业务问题
-
用户本身有权限,要考虑是不是得软删除原有的权限,新增新权限进行覆盖。
-
从单独权限到全权限(全部勾选),前端发送数据直接改成
*
,删除原有种类下所有的所有权限,新增一条*
权限。
-
可能会出现新增、修改、删除三种操作同时出现的情况。
二、权限业务解析
1. 常规解析
根据业务逻辑一步一步思考
2. 企业级闭环高效解析
代码复用率高,操作闭环简化,利用交并集的思想,设计任务处理队列,进行批处理,一次性批处理,数据库交互次数少,巧妙的利用LINQ语句,简化代码难度。
三、代码实现
1. BLL
1.1 获取用户存储的全部非删除权限
/// <summary>
/// 获取用户存储的全部权限(不包含删除)
/// </summary>
/// <param name="RoleType">权限类型1:A权限,2:D权限,3:M权限,4: E报表权限,*->5:所有权限</param>
/// <param name="UserAccount">用户账号</param>
/// <returns></returns>
public List<UserRoleEntity> GetAllUserRole(int RoleType, string UserAccount)
{
// 获取符合条件的权限记录
List<UserRoleEntity>? allPower = _roleDB.AsQueryable()
.Where(a => a.UserAccount == UserAccount&&!a.IsDelete) // 过滤条件:指定用户账号&&存在
.WhereIF(RoleType != 5, w => w.RoleType == Convert.ToByte(RoleType)) // 过滤条件:指定权限类型,若为 5 则不过滤
.ToList();
return allPower;
}
1.2 删除用户权限
/// <summary>
/// 删除用户权限
/// </summary>
/// <param name="RoleType">权限类型</param>
/// <param name="UserAccount">用户账号</param>
/// <param name="RoleName">权限组名称(可选)</param>
/// <returns></returns>
public async Task<dynamic> DeleteUserRole(int RoleType, string UserAccount, string? RoleName = null)
{
_logger.LogInformation("开始软删除角色,用户账号: {UserAccount}, 权限类型: {RoleType}, 角色名称: {RoleName}", UserAccount, RoleType, RoleName);
if (string.IsNullOrEmpty(UserAccount))
{
_logger.LogWarning("用户账号不能为空。");
return HttpMsgResult.FailureResult(msg: "用户账号不能为空。");
}
var query = _roleDB.AsQueryable()
.Where(r => r.RoleType == RoleType && r.UserAccount == UserAccount);
if (!string.IsNullOrEmpty(RoleName))
{
query = query.Where(r => r.RoleName == RoleName);
}
var existingRoles = await query.ToListAsync();
if (existingRoles == null || existingRoles.Count == 0)
{
_logger.LogWarning("未找到对应的角色,无法删除,用户账号: {UserAccount}, 权限类型: {RoleType}, 角色名称: {RoleName}", UserAccount, RoleType, RoleName);
return HttpMsgResult.FailureResult(msg: "未找到对应的角色,无法删除。");
}
try
{
var affectedRows = _roleDB.FakeDeleteRange(existingRoles);
if (affectedRows > 0)
{
_logger.LogInformation("成功软删除 {Count} 条角色记录,用户账号: {UserAccount}", affectedRows, UserAccount);
return HttpMsgResult.SuccessResult(msg: $"用户权限已被软删除,共删除 {affectedRows} 条记录。");
}
else
{
_logger.LogWarning("未能软删除角色记录,用户账号: {UserAccount}", UserAccount);
return HttpMsgResult.FailureResult(msg: "未能删除用户权限。");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "软删除角色时发生错误,用户账号: {UserAccount}, 权限类型: {RoleType}, 角色名称: {RoleName}", UserAccount, RoleType, RoleName);
return HttpMsgResult.FailureResult(msg: "删除用户权限时发生错误:" + ex.Message);
}
}
1.3 数据传输对象解析
/// <summary>
/// 将综合的用户角色数据传输对象解析为多个 UserRoleEntity 对象。
/// </summary>
/// <param name="userRoleJsonDto">用户角色数据传输对象综合列表。</param>
/// <returns>解析后的 UserRoleEntity 对象列表。</returns>
public List<UserRoleEntity> ParseJsonDtoToUserRoleDtos(UserRoleJsonDto userRoleJsonDto)
{
List<UserRoleEntity>? userRoleDtos = new List<UserRoleEntity>();
foreach (RoleDetailDto role in userRoleJsonDto.Roles)
{
UserRoleEntity? userRoleDto = new UserRoleEntity
{
UserAccount = userRoleJsonDto.UserAccount, // 将用户账号赋值给每个 UserRoleDto
UserRealName = userRoleJsonDto.UserRealName, // 将用户真实姓名赋值给每个 UserRoleDto
RoleType = (byte?)role.RoleType, // 赋值权限类型
RoleName = role.RoleName, // 赋值角色名称
SubRole = string.Join(",", role.SubRoles ?? Array.Empty<string>()), // 赋值子类Code数组
IsDelete = userRoleJsonDto.IsDelete == 1 // 继承综合对象的删除状态
};
userRoleDtos.Add(userRoleDto);
}
return userRoleDtos;
}
2. Dto
2.1 userRoleJsonDto
namespace OPC.PR.Application.Objects
{
/// <summary>
/// 角色详细信息数据传输对象
/// </summary>
public class RoleDetailDto
{
/// <summary>
/// 所属权限组的类型 权限类型1:A权限,2:D权限,3:M权限,4: E报表权限,*->5:所有权限</param>
/// </summary>
public int RoleType { get; set; }
/// <summary>
/// 所属权限组的名称(全部时为*)
/// </summary>
public string? RoleName { get; set; }
/// <summary>
/// 所属权限大类下得子类Code
/// </summary>
public string[]? SubRoles { get; set; }
}
/// <summary>
/// 角色数据传输对象,用于接收复杂结构的 JSON 数据
/// </summary>
public class UserRoleJsonDto
{
/// <summary>
/// 用户账号
/// </summary>
public string UserAccount { get; set; }
/// <summary>
/// 用户真实姓名
/// </summary>
public string? UserRealName { get; set; }
/// <summary>
/// 冻结标识
/// </summary>
public int IsDelete { get; set; } = 0;
/// <summary>
/// 权限详细信息列表
/// </summary>
public List<RoleDetailDto> Roles { get; set; }
}
}
2.2 UserRoleDto
namespace OPC.PR.Application.Objects
{
/// <summary>
/// 角色数据传输对象
/// </summary>
public class UserRoleDto
{
/// <summary>
/// 用户账号
/// </summary>
public string UserAccount { get; set; }
/// <summary>
/// 用户真实姓名
/// </summary>
public string? UserRealName { get; set; }
/// <summary>
/// 所属权限组的名称(全部时为*)
/// </summary>
public string? RoleName { get; set; }
/// <summary>
/// 所属权限组的类型
/// </summary>
public int RoleType { get; set; }
/// <summary>
/// 所属权限大类下得子类Code
/// </summary>
public string[]? SubRoles { get; set; }
/// <summary>
/// 冻结标识
/// </summary>
public int IsDelete { get; set; } = 0;
}
}
2.3 UserRoleEntity
namespace OPC.PR.Application.Entity
{
[SugarTable("b_user_role", "用户权限配置表")]
[Tenant(DBConfigIds.PR)]
public class UserRoleEntity : EntityBase
{
/// <summary>
/// 用户账号
/// </summary>
public string? UserAccount { get; set; }
/// <summary>
/// 用户姓名
/// </summary>
public string? UserRealName { get; set; }
/// <summary>
/// 所属权限组的名称(全部时为*)
/// </summary>
public string? RoleName { get; set; }
/// <summary>
/// 所属权限组的类型
/// </summary>
public byte? RoleType { get; set; }
/// <summary>
/// 所属权限大类下得子类Code,多个时以逗号分隔
/// </summary>
public string? SubRole { get; set; }
}
}
3. Service
3.1 展示角色全部权限
/// <summary>
/// 展示角色全部权限
/// </summary>
/// <param name="RoleType"></param>
/// <param name="UserAccount"></param>
/// <returns></returns>
[DisplayName("展示角色全部权限"), ActionName("GetRole")]
[HttpPost]
[NonUnify]
public dynamic GetRole(string RoleType, string UserAccount)
{
_logger.LogInformation("开始调用 GetRole 方法,权限类型: {RoleType}, 用户账号: {UserAccount}", RoleType, UserAccount);
// 转化成全部情况
if (RoleType == "*") RoleType = "5";
// 获取全部权限
List<UserRoleEntity>? getResult;
try
{
getResult = _bllrole.GetAllUserRole(RoleType: int.Parse(RoleType), UserAccount);
// 将数据库查询结果映射到 UserRoleDto 列表
var qresult = getResult.Select(x => new UserRoleDto
{
UserAccount = x.UserAccount, // 映射用户账号
UserRealName = x.UserRealName, // 映射用户真实姓名
RoleName = x.RoleName, // 映射角色名称
RoleType = x.RoleType.HasValue ? (int)x.RoleType : 0, // 映射角色类型,若为空则设为 0
SubRoles = x.SubRole != null ? x.SubRole.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) : new string[] { }, // 映射子权限,将其分割为数组
IsDelete = x.IsDelete ? 1 : 0 // 映射删除状态,已删除标识为 1,未删除为 0
}).ToList();
_logger.LogInformation("开始调用 GetRole 方法,权限类型: {RoleType}, 用户账号: {UserAccount}", RoleType, UserAccount);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用户权限时发生错误,用户账号: {UserAccount}, 权限类型: {RoleType}", UserAccount, RoleType);
return HttpMsgResult.FailureResult(msg: "获取用户权限时发生错误.");
}
// 过滤掉已软删除的记录
var activeRoles = getResult.Where(r => !r.IsDelete).ToList();
_logger.LogInformation("找到 {Count} 条有效权限记录,用户账号: {UserAccount}", activeRoles.Count, UserAccount);
// 构造固定字段名称的数据
var data = activeRoles.Select(role =>
{
// 调用判断器获取字段名
(string fieldName1, string fieldName2) = GetFieldNames((int)role.RoleType);
// 构造字段名和子权限
return new Dictionary<string, object>
{
{ fieldName1, role.RoleName },
{ fieldName2, role.SubRole} // 直接返回子权限列表
};
}).ToList();
_logger.LogInformation("结束调用 GetRole 方法");
return data;
}
/// <summary>
/// 根据RoleType生成字段名称
/// </summary>
/// <param name="roleType">角色类型</param>
/// <returns>字段名称元组</returns>
private (string fieldName1, string fieldName2) GetFieldNames(int roleType)
{
return roleType switch
{
1 => ("A1", "A2"),
2 => ("D", "Dsub"),
3 or 4 => ("Other1", "Other2"),
_ => ("Error1", "Error2"),
};
}
3.2 保存用户权限
/// <summary>
/// 保存用户权限
/// </summary>
/// <param name="userRoleJsonDto"> Body格式的数据,不多传输</param>
[DisplayName("保存用户权限"), ActionName("SetUserRole")]
[HttpPost]
[NonUnify]
public async Task<dynamic> SetUserRole(UserRoleJsonDto userRoleJsonDto)
{
_logger.LogInformation("开始保存用户权限,用户账号: {UserAccount}", userRoleJsonDto.UserAccount);
// 解析 JSON DTO 为多个 UserRoleDto
List<UserRoleEntity>? userRoleDtos = _bllrole.ParseJsonDtoToUserRoleDtos(userRoleJsonDto);
if (userRoleDtos == null || !userRoleDtos.Any())
{
_logger.LogWarning("未找到有效的用户角色数据,用户账号: {UserAccount}", userRoleJsonDto.UserAccount);
return HttpMsgResult.FailureResult(msg: "未找到有效的用户角色数据。");
}
// 查询数据库中的现有权限
List<UserRoleEntity>? allCurrentRoles = _bllrole.GetAllUserRole(5, userRoleJsonDto.UserAccount);
if (userRoleJsonDto.Roles.Any(s => s.RoleName == "*"))
{
// 查询数据库中是否存在RoleName为*的记录
UserRoleEntity? existingStarRole = allCurrentRoles.FirstOrDefault(w => w.RoleName == "*");
if (existingStarRole == null)
{
// 将相同 RoleType 的所有记录加入软删除队列
List<UserRoleEntity>? rolesToDelete = allCurrentRoles.Where(w => userRoleJsonDto.Roles.Any(s => s.RoleType == w.RoleType)).ToList();
_roleDB.FakeDeleteRange(rolesToDelete);
_logger.LogInformation("批量删除完成,删除数量: {Count}", rolesToDelete.Count);
// 构造新增的*权限
var starRoleEntity = new UserRoleEntity
{
UserAccount = userRoleJsonDto.UserAccount,
UserRealName = userRoleJsonDto.UserRealName, // 从 JsonDto 获取的真实用户姓名
RoleType = Convert.ToByte(userRoleJsonDto.Roles.FirstOrDefault(r => r.RoleName == "*")?.RoleType),
RoleName = "*",
SubRole = string.Join(",", userRoleJsonDto.Roles.FirstOrDefault(r => r.RoleName == "*")?.SubRoles ?? Array.Empty<string>()),
IsDelete = false
};
_roleDB.Insert(starRoleEntity);
_logger.LogInformation("新增角色: *, 类型: {RoleType}, 用户账号: {UserAccount}", starRoleEntity.RoleType, starRoleEntity.UserAccount);
return HttpMsgResult.SuccessResult(msg: "新增角色全权限。");
}
else
{
_logger.LogError("已经是全权限");
return HttpMsgResult.FailureResult(msg: "已经是全权限。");
}
}
// 删除队列
var DeleteRoles = allCurrentRoles.Where(w => userRoleJsonDto.Roles.Any(s => s.RoleType == w.RoleType) && !userRoleJsonDto.Roles.Any(s => s.RoleType == w.RoleType && s.RoleName == w.RoleName)).ToList();
// 更新队列 - 保留从数据库中获取的原始记录,但更新 DTO 中传入的新值
var updateRoles = userRoleDtos.Where(r => allCurrentRoles.Any(existingRole => existingRole.RoleType == r.RoleType && existingRole.RoleName == r.RoleName)) .Select(r =>{var originalEntity = allCurrentRoles.FirstOrDefault(existingRole => existingRole.RoleType == r.RoleType &&existingRole.RoleName == r.RoleName);if (originalEntity != null){originalEntity.UserRealName = r.UserRealName;originalEntity.SubRole = r.SubRole;
originalEntity.IsDelete = r.IsDelete;}return originalEntity;}) .ToList();
// 增加队列 - 构建新的实体,保持从 DTO 传入的数据
var addRoles = userRoleDtos.Where(r => !allCurrentRoles.Any(existingRole => existingRole.RoleType == r.RoleType &&
existingRole.RoleName == r.RoleName)).Select(r => new UserRoleEntity{UserAccount = r.UserAccount,UserRealName = r.UserRealName, RoleType = r.RoleType,
RoleName = r.RoleName,SubRole = r.SubRole,IsDelete = r.IsDelete}) .ToList();
try
{
// 批量执行删除操作
if (DeleteRoles.Any())
{
_roleDB.FakeDeleteRange(DeleteRoles);
_logger.LogInformation("批量删除完成,删除数量: {Count}", DeleteRoles.Count);
}
// 批量执行更新操作
if (updateRoles.Any())
{
_roleDB.UpdateRange(updateRoles);
_logger.LogInformation("批量更新完成,更新数量: {Count}", updateRoles.Count);
}
// 批量执行新增操作
if (addRoles.Any())
{
_roleDB.InsertRange(addRoles);
_logger.LogInformation("批量新增完成,新增数量: {Count}", addRoles.Count);
}
_logger.LogInformation("用户权限保存完成,用户账号: {UserAccount}", userRoleJsonDto.UserAccount);
return HttpMsgResult.SuccessResult(msg: "用户操作已完成。");
}
catch (Exception ex)
{
_logger.LogError(ex, "批量操作时发生错误,用户账号: {UserAccount}", userRoleJsonDto.UserAccount);
return HttpMsgResult.FailureResult(msg: "用户操作失败。");
}
finally
{
_logger.LogInformation("保存用户权限操作结束,用户账号: {UserAccount}", userRoleJsonDto.UserAccount);
}
}
3.3 软删除用户权限
/// <summary>
/// 软删除用户权限
/// </summary>
/// <param name="RoleType">权限类型</param>
/// <param="UserAccount">用户账号</param>
/// <param="RoleName">权限组名称(可选)</param>
/// <returns></returns>
public async Task<dynamic> DeleteUserRole(int RoleType, string UserAccount)
{
_logger.LogInformation("开始软删除角色,用户账号: {UserAccount}, 权限类型: {RoleType}", UserAccount, RoleType);
if (string.IsNullOrEmpty(UserAccount))
{
_logger.LogWarning("用户账号不能为空。");
return HttpMsgResult.FailureResult(msg: "用户账号不能为空。");
}
try
{
// 调用 BLL 的 DeleteUserRole 方法
var result = await _bllrole.DeleteUserRole(RoleType, UserAccount, null);
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "软删除角色时发生错误,用户账号: {UserAccount}, 权限类型: {RoleType},", UserAccount, RoleType);
return HttpMsgResult.FailureResult(msg: "删除用户权限时发生错误:" + ex.Message);
}
}