317 lines
11 KiB
C#
317 lines
11 KiB
C#
using MiAssessment.Admin.Data;
|
|
using MiAssessment.Admin.Entities;
|
|
using MiAssessment.Admin.Models.AdminUser;
|
|
using MiAssessment.Admin.Models.Common;
|
|
using MiAssessment.Admin.Models.Department;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MiAssessment.Admin.Services;
|
|
|
|
/// <summary>
|
|
/// 部门服务实现
|
|
/// </summary>
|
|
public class DepartmentService : IDepartmentService
|
|
{
|
|
private readonly AdminDbContext _dbContext;
|
|
private readonly ILogger<DepartmentService> _logger;
|
|
|
|
public DepartmentService(AdminDbContext dbContext, ILogger<DepartmentService> logger)
|
|
{
|
|
_dbContext = dbContext;
|
|
_logger = logger;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<List<DepartmentTreeDto>> GetDepartmentTreeAsync()
|
|
{
|
|
var departments = await _dbContext.Departments
|
|
.Include(d => d.AdminUsers)
|
|
.OrderBy(d => d.SortOrder)
|
|
.ThenBy(d => d.Id)
|
|
.ToListAsync();
|
|
|
|
return BuildDepartmentTree(departments, 0);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<DepartmentDto> GetByIdAsync(long id)
|
|
{
|
|
var department = await _dbContext.Departments
|
|
.Include(d => d.DepartmentMenus)
|
|
.FirstOrDefaultAsync(d => d.Id == id);
|
|
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
return new DepartmentDto
|
|
{
|
|
Id = department.Id,
|
|
ParentId = department.ParentId,
|
|
Name = department.Name,
|
|
Code = department.Code,
|
|
Description = department.Description,
|
|
SortOrder = department.SortOrder,
|
|
Status = department.Status,
|
|
CreatedAt = department.CreatedAt,
|
|
UpdatedAt = department.UpdatedAt,
|
|
MenuIds = department.DepartmentMenus.Select(dm => dm.MenuId).ToList()
|
|
};
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<long> CreateAsync(CreateDepartmentRequest request)
|
|
{
|
|
// 验证父部门是否存在
|
|
if (request.ParentId > 0)
|
|
{
|
|
var parentExists = await _dbContext.Departments.AnyAsync(d => d.Id == request.ParentId);
|
|
if (!parentExists)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "父部门不存在");
|
|
}
|
|
}
|
|
|
|
// 检查编码是否重复
|
|
if (!string.IsNullOrWhiteSpace(request.Code))
|
|
{
|
|
var codeExists = await _dbContext.Departments.AnyAsync(d => d.Code == request.Code);
|
|
if (codeExists)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DuplicateDepartmentCode, "部门编码已存在");
|
|
}
|
|
}
|
|
|
|
var department = new Entities.Department
|
|
{
|
|
ParentId = request.ParentId,
|
|
Name = request.Name,
|
|
Code = request.Code,
|
|
Description = request.Description,
|
|
SortOrder = request.SortOrder,
|
|
Status = request.Status,
|
|
CreatedAt = DateTime.Now
|
|
};
|
|
|
|
_dbContext.Departments.Add(department);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
_logger.LogInformation("创建部门成功: {DepartmentId} - {DepartmentName}", department.Id, department.Name);
|
|
return department.Id;
|
|
}
|
|
|
|
|
|
/// <inheritdoc />
|
|
public async Task UpdateAsync(long id, UpdateDepartmentRequest request)
|
|
{
|
|
var department = await _dbContext.Departments.FindAsync(id);
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
// 验证父部门是否存在
|
|
if (request.ParentId > 0)
|
|
{
|
|
// 不能将自己设为父部门
|
|
if (request.ParentId == id)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DepartmentCircularReference, "不能将部门设为自己的子部门");
|
|
}
|
|
|
|
var parentExists = await _dbContext.Departments.AnyAsync(d => d.Id == request.ParentId);
|
|
if (!parentExists)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "父部门不存在");
|
|
}
|
|
|
|
// 检查是否会形成循环引用(不能将部门设为其子孙部门的子部门)
|
|
if (await IsDescendantAsync(request.ParentId, id))
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DepartmentCircularReference, "不能将部门设为其子部门的子部门");
|
|
}
|
|
}
|
|
|
|
// 检查编码是否重复(排除自己)
|
|
if (!string.IsNullOrWhiteSpace(request.Code))
|
|
{
|
|
var codeExists = await _dbContext.Departments.AnyAsync(d => d.Code == request.Code && d.Id != id);
|
|
if (codeExists)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DuplicateDepartmentCode, "部门编码已存在");
|
|
}
|
|
}
|
|
|
|
department.ParentId = request.ParentId;
|
|
department.Name = request.Name;
|
|
department.Code = request.Code;
|
|
department.Description = request.Description;
|
|
department.SortOrder = request.SortOrder;
|
|
department.Status = request.Status;
|
|
department.UpdatedAt = DateTime.Now;
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
_logger.LogInformation("更新部门成功: {DepartmentId} - {DepartmentName}", department.Id, department.Name);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task DeleteAsync(long id)
|
|
{
|
|
var department = await _dbContext.Departments.FindAsync(id);
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
// 检查是否有子部门
|
|
var hasChildren = await _dbContext.Departments.AnyAsync(d => d.ParentId == id);
|
|
if (hasChildren)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DepartmentHasChildren, "该部门下有子部门,无法删除");
|
|
}
|
|
|
|
// 检查是否有用户
|
|
var hasUsers = await _dbContext.AdminUsers.AnyAsync(u => u.DepartmentId == id);
|
|
if (hasUsers)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.DepartmentHasUsers, "该部门下有用户,无法删除");
|
|
}
|
|
|
|
// 删除关联数据
|
|
var departmentMenus = await _dbContext.DepartmentMenus.Where(dm => dm.DepartmentId == id).ToListAsync();
|
|
_dbContext.DepartmentMenus.RemoveRange(departmentMenus);
|
|
|
|
_dbContext.Departments.Remove(department);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
_logger.LogInformation("删除部门成功: {DepartmentId} - {DepartmentName}", id, department.Name);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<List<long>> GetMenuIdsAsync(long departmentId)
|
|
{
|
|
var department = await _dbContext.Departments.FindAsync(departmentId);
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
return await _dbContext.DepartmentMenus
|
|
.Where(dm => dm.DepartmentId == departmentId)
|
|
.Select(dm => dm.MenuId)
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task AssignMenusAsync(long departmentId, List<long> menuIds)
|
|
{
|
|
var department = await _dbContext.Departments.FindAsync(departmentId);
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
// 删除现有关联
|
|
var existingMenus = await _dbContext.DepartmentMenus.Where(dm => dm.DepartmentId == departmentId).ToListAsync();
|
|
_dbContext.DepartmentMenus.RemoveRange(existingMenus);
|
|
|
|
// 添加新关联
|
|
if (menuIds.Any())
|
|
{
|
|
var newMenus = menuIds.Distinct().Select(menuId => new DepartmentMenu
|
|
{
|
|
DepartmentId = departmentId,
|
|
MenuId = menuId
|
|
});
|
|
_dbContext.DepartmentMenus.AddRange(newMenus);
|
|
}
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
_logger.LogInformation("部门 {DepartmentId} 分配菜单成功,菜单数量: {Count}", departmentId, menuIds.Count);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<List<AdminUserDto>> GetDepartmentUsersAsync(long departmentId)
|
|
{
|
|
var department = await _dbContext.Departments.FindAsync(departmentId);
|
|
if (department == null)
|
|
{
|
|
throw new AdminException(AdminErrorCodes.InvalidParameter, "部门不存在");
|
|
}
|
|
|
|
return await _dbContext.AdminUsers
|
|
.Where(u => u.DepartmentId == departmentId)
|
|
.Include(u => u.AdminUserRoles)
|
|
.ThenInclude(ur => ur.Role)
|
|
.Select(u => new AdminUserDto
|
|
{
|
|
Id = u.Id,
|
|
Username = u.Username,
|
|
RealName = u.RealName,
|
|
Avatar = u.Avatar,
|
|
Email = u.Email,
|
|
Phone = u.Phone,
|
|
DepartmentId = u.DepartmentId,
|
|
DepartmentName = department.Name,
|
|
Status = u.Status,
|
|
LastLoginTime = u.LastLoginTime,
|
|
LastLoginIp = u.LastLoginIp,
|
|
CreatedAt = u.CreatedAt,
|
|
UpdatedAt = u.UpdatedAt,
|
|
Remark = u.Remark,
|
|
RoleIds = u.AdminUserRoles.Select(ur => ur.RoleId).ToList(),
|
|
RoleNames = u.AdminUserRoles.Select(ur => ur.Role.Name).ToList()
|
|
})
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 构建部门树
|
|
/// </summary>
|
|
private List<DepartmentTreeDto> BuildDepartmentTree(List<Entities.Department> departments, long parentId)
|
|
{
|
|
return departments
|
|
.Where(d => d.ParentId == parentId)
|
|
.Select(d => new DepartmentTreeDto
|
|
{
|
|
Id = d.Id,
|
|
ParentId = d.ParentId,
|
|
Name = d.Name,
|
|
Code = d.Code,
|
|
SortOrder = d.SortOrder,
|
|
Status = d.Status,
|
|
UserCount = d.AdminUsers.Count,
|
|
Children = BuildDepartmentTree(departments, d.Id)
|
|
})
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 检查 targetId 是否是 departmentId 的子孙部门
|
|
/// </summary>
|
|
private async Task<bool> IsDescendantAsync(long targetId, long departmentId)
|
|
{
|
|
var children = await _dbContext.Departments
|
|
.Where(d => d.ParentId == departmentId)
|
|
.Select(d => d.Id)
|
|
.ToListAsync();
|
|
|
|
if (children.Contains(targetId))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
foreach (var childId in children)
|
|
{
|
|
if (await IsDescendantAsync(targetId, childId))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|