using System.Text.Json; using Microsoft.EntityFrameworkCore; using MilitaryTrainingManagement.Data; using MilitaryTrainingManagement.Models.Entities; using MilitaryTrainingManagement.Models.Enums; using MilitaryTrainingManagement.Services.Interfaces; namespace MilitaryTrainingManagement.Services.Implementations; /// /// 人员管理服务实现 /// public class PersonnelService : IPersonnelService { private readonly ApplicationDbContext _context; private readonly IOrganizationService _organizationService; private readonly IFileUploadService _fileUploadService; private readonly IWorkflowService _workflowService; private readonly ILogger _logger; public PersonnelService( ApplicationDbContext context, IOrganizationService organizationService, IFileUploadService fileUploadService, IWorkflowService workflowService, ILogger logger) { _context = context; _organizationService = organizationService; _fileUploadService = fileUploadService; _workflowService = workflowService; _logger = logger; } public async Task GetByIdAsync(int id) { return await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .FirstOrDefaultAsync(p => p.Id == id); } public async Task> GetByUnitAsync(int unitId, bool includeSubordinates = false) { if (includeSubordinates) { var subordinates = await _organizationService.GetSubordinatesAsync(unitId); var unitIds = subordinates.Select(s => s.Id).ToList(); unitIds.Add(unitId); return await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .Where(p => unitIds.Contains(p.SubmittedByUnitId)) .OrderByDescending(p => p.SubmittedAt) .ToListAsync(); } return await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .Where(p => p.SubmittedByUnitId == unitId) .OrderByDescending(p => p.SubmittedAt) .ToListAsync(); } public async Task CreateAsync(Personnel personnel) { personnel.Status = PersonnelStatus.Pending; personnel.SubmittedAt = DateTime.UtcNow; _context.Personnel.Add(personnel); await _context.SaveChangesAsync(); return personnel; } public async Task UpdateAsync(Personnel personnel) { _context.Personnel.Update(personnel); await _context.SaveChangesAsync(); return personnel; } public async Task ApproveAsync(int personnelId, int approvedByUnitId, PersonnelLevel level) { var personnel = await _context.Personnel.FindAsync(personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId); if (approvedByUnit == null) throw new ArgumentException("审批单位不存在"); // 验证审批单位层级必须高于或等于人员等级(数值越小层级越高) var unitLevelValue = (int)approvedByUnit.Level; var personnelLevelValue = (int)level; if (unitLevelValue > personnelLevelValue) throw new ArgumentException("审批单位层级不足以审批该等级人才"); var previousStatus = personnel.Status; var previousLevel = personnel.ApprovedLevel; personnel.Status = PersonnelStatus.Approved; personnel.ApprovedByUnitId = approvedByUnitId; personnel.ApprovedLevel = level; personnel.ApprovedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); // 记录审批历史 var userId = await GetUserIdByUnitAsync(approvedByUnitId); await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Approved, previousStatus, PersonnelStatus.Approved, previousLevel, level, userId, approvedByUnitId, "审批通过"); _logger.LogInformation("人员 {PersonnelId} 已被单位 {UnitId} 审批通过,等级:{Level}", personnelId, approvedByUnitId, level); return personnel; } public async Task RejectAsync(int personnelId, int reviewedByUserId) { var personnel = await _context.Personnel.FindAsync(personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); var previousStatus = personnel.Status; personnel.Status = PersonnelStatus.Rejected; await _context.SaveChangesAsync(); // 记录审批历史 await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Rejected, previousStatus, PersonnelStatus.Rejected, null, null, reviewedByUserId, null, "审批拒绝"); _logger.LogInformation("人员 {PersonnelId} 已被用户 {UserId} 拒绝", personnelId, reviewedByUserId); return personnel; } public async Task DeleteAsync(int id) { var personnel = await _context.Personnel.FindAsync(id); if (personnel == null) throw new ArgumentException("人员记录不存在"); // 删除关联的文件 if (!string.IsNullOrEmpty(personnel.PhotoPath)) { await _fileUploadService.DeleteFileAsync(personnel.PhotoPath); } if (!string.IsNullOrEmpty(personnel.SupportingDocuments)) { await _fileUploadService.DeleteFileAsync(personnel.SupportingDocuments); } _context.Personnel.Remove(personnel); await _context.SaveChangesAsync(); _logger.LogInformation("人员记录 {PersonnelId} 已删除", id); } public async Task SubmitPersonnelAsync(Personnel personnel, IFormFile? photo, IFormFile? supportingDocument) { // 验证人员数据完整性 var validation = await ValidatePersonnelDataAsync(personnel); if (!validation.IsValid) { throw new ArgumentException($"人员数据验证失败:{string.Join(", ", validation.Errors)}"); } // 处理照片上传 if (photo != null) { try { personnel.PhotoPath = await _fileUploadService.UploadPhotoAsync(photo); _logger.LogInformation("人员照片上传成功:{PhotoPath}", personnel.PhotoPath); } catch (Exception ex) { _logger.LogError(ex, "人员照片上传失败"); throw new InvalidOperationException($"照片上传失败:{ex.Message}"); } } // 处理支持文档上传 if (supportingDocument != null) { try { personnel.SupportingDocuments = await _fileUploadService.UploadDocumentAsync(supportingDocument); _logger.LogInformation("支持文档上传成功:{DocumentPath}", personnel.SupportingDocuments); } catch (Exception ex) { _logger.LogError(ex, "支持文档上传失败"); throw new InvalidOperationException($"支持文档上传失败:{ex.Message}"); } } // 设置提交状态和时间 personnel.Status = PersonnelStatus.Pending; personnel.SubmittedAt = DateTime.UtcNow; _context.Personnel.Add(personnel); await _context.SaveChangesAsync(); _logger.LogInformation("人员数据提交成功,ID:{PersonnelId},提交单位:{UnitId}", personnel.Id, personnel.SubmittedByUnitId); return personnel; } public async Task ValidatePersonnelDataAsync(Personnel personnel) { var errors = new List(); // 验证必填字段 if (string.IsNullOrWhiteSpace(personnel.Name)) errors.Add("姓名不能为空"); if (string.IsNullOrWhiteSpace(personnel.Position)) errors.Add("职位不能为空"); if (string.IsNullOrWhiteSpace(personnel.Rank)) errors.Add("军衔不能为空"); if (string.IsNullOrWhiteSpace(personnel.Gender)) errors.Add("性别不能为空"); if (string.IsNullOrWhiteSpace(personnel.IdNumber)) errors.Add("身份证号不能为空"); if (personnel.Age <= 0 || personnel.Age > 100) errors.Add("年龄必须在1-100之间"); if (personnel.SubmittedByUnitId <= 0) errors.Add("提交单位不能为空"); // 验证身份证号格式(简单验证) if (!string.IsNullOrWhiteSpace(personnel.IdNumber)) { if (personnel.IdNumber.Length != 18) errors.Add("身份证号必须为18位"); } // 验证身份证号唯一性 if (!string.IsNullOrWhiteSpace(personnel.IdNumber)) { var existingPersonnel = await _context.Personnel .FirstOrDefaultAsync(p => p.IdNumber == personnel.IdNumber && p.Id != personnel.Id); if (existingPersonnel != null) errors.Add("身份证号已存在"); } // 验证提交单位是否存在 if (personnel.SubmittedByUnitId > 0) { var unit = await _context.OrganizationalUnits.FindAsync(personnel.SubmittedByUnitId); if (unit == null) errors.Add("提交单位不存在"); } return errors.Any() ? PersonnelValidationResult.Failure(errors.ToArray()) : PersonnelValidationResult.Success(); } public async Task GetApprovalTargetUnitAsync(int submittingUnitId) { var submittingUnit = await _context.OrganizationalUnits .Include(u => u.Parent) .FirstOrDefaultAsync(u => u.Id == submittingUnitId); if (submittingUnit == null) throw new ArgumentException("提交单位不存在"); // 审批路由逻辑:提交给上级单位审批 if (submittingUnit.Parent != null) { return submittingUnit.Parent; } // 如果是师团级别,则自己审批 if (submittingUnit.Level == OrganizationalLevel.Division) { return submittingUnit; } throw new InvalidOperationException("无法确定审批目标单位"); } public async Task CanModifyPersonnelAsync(int personnelId) { var personnel = await _context.Personnel.FindAsync(personnelId); if (personnel == null) return false; // 只有待审批状态的人员可以直接修改 if (personnel.Status == PersonnelStatus.Pending) return true; // 已审批的人员需要通过工作流修改 return false; } public async Task RequestPersonnelModificationAsync(int personnelId, int requestedByUserId, string reason, Personnel modifiedPersonnel) { var originalPersonnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (originalPersonnel == null) throw new ArgumentException("人员记录不存在"); if (originalPersonnel.Status != PersonnelStatus.Approved) throw new InvalidOperationException("只能修改已审批的人员记录"); var user = await _context.UserAccounts .Include(u => u.OrganizationalUnit) .FirstOrDefaultAsync(u => u.Id == requestedByUserId); if (user == null) throw new ArgumentException("请求用户不存在"); // 序列化原始数据和修改数据 var originalData = JsonSerializer.Serialize(new { originalPersonnel.Name, originalPersonnel.Position, originalPersonnel.Rank, originalPersonnel.Gender, originalPersonnel.IdNumber, originalPersonnel.ProfessionalTitle, originalPersonnel.EducationLevel, originalPersonnel.Age, originalPersonnel.Height, originalPersonnel.ContactInfo, originalPersonnel.Hometown, originalPersonnel.TrainingParticipation, originalPersonnel.Achievements }); var requestedChanges = JsonSerializer.Serialize(new { modifiedPersonnel.Name, modifiedPersonnel.Position, modifiedPersonnel.Rank, modifiedPersonnel.Gender, modifiedPersonnel.IdNumber, modifiedPersonnel.ProfessionalTitle, modifiedPersonnel.EducationLevel, modifiedPersonnel.Age, modifiedPersonnel.Height, modifiedPersonnel.ContactInfo, modifiedPersonnel.Hometown, modifiedPersonnel.TrainingParticipation, modifiedPersonnel.Achievements }); var request = await _workflowService.CreateModificationRequestAsync( ApprovalRequestType.PersonnelModification, personnelId, requestedByUserId, user.OrganizationalUnitId, reason, originalData, requestedChanges); _logger.LogInformation("人员修改请求已创建,ID:{RequestId},人员ID:{PersonnelId}", request.Id, personnelId); return request; } public async Task> GetVisiblePersonnelAsync(int unitId, OrganizationalLevel userLevel) { // 根据组织层级获取可见的人员 // 用户只能查看当前和下级组织单位的人员 var subordinates = await _organizationService.GetSubordinatesAsync(unitId); var visibleUnitIds = subordinates.Select(s => s.Id).ToList(); visibleUnitIds.Add(unitId); var query = _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .Where(p => visibleUnitIds.Contains(p.SubmittedByUnitId)); // 根据人员等级进一步过滤 // 用户只能查看等级不高于自己组织层级的人员 var maxPersonnelLevel = (PersonnelLevel)(int)userLevel; query = query.Where(p => p.ApprovedLevel == null || p.ApprovedLevel >= maxPersonnelLevel); return await query.OrderByDescending(p => p.SubmittedAt).ToListAsync(); } public async Task TransferPersonnelAsync(int personnelId, int targetUnitId, int approvedByUnitId) { var personnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); if (personnel.Status != PersonnelStatus.Approved) throw new InvalidOperationException("只能转移已审批的人员"); var targetUnit = await _context.OrganizationalUnits.FindAsync(targetUnitId); if (targetUnit == null) throw new ArgumentException("目标单位不存在"); var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId); if (approvedByUnit == null) throw new ArgumentException("审批单位不存在"); // 验证审批单位有权限进行跨层级转移 // 审批单位层级必须高于或等于目标单位层级 if ((int)approvedByUnit.Level > (int)targetUnit.Level) throw new UnauthorizedAccessException("审批单位层级不足以进行此转移"); // 更新人员所属单位 personnel.SubmittedByUnitId = targetUnitId; // 根据新的审批单位重新设置人员等级 var newLevel = (PersonnelLevel)(int)approvedByUnit.Level; personnel.ApprovedLevel = newLevel; personnel.ApprovedByUnitId = approvedByUnitId; personnel.ApprovedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); _logger.LogInformation("人员 {PersonnelId} 已从单位 {FromUnitId} 转移到单位 {ToUnitId},审批单位:{ApprovedByUnitId}", personnelId, personnel.SubmittedByUnit.Id, targetUnitId, approvedByUnitId); return personnel; } public async Task> GetPendingApprovalPersonnelAsync(int unitId) { // 获取需要当前单位审批的人员(来自下级单位的提交) var subordinates = await _organizationService.GetSubordinatesAsync(unitId); var subordinateIds = subordinates.Select(s => s.Id).ToList(); return await _context.Personnel .Include(p => p.SubmittedByUnit) .Where(p => subordinateIds.Contains(p.SubmittedByUnitId) && p.Status == PersonnelStatus.Pending) .OrderBy(p => p.SubmittedAt) .ToListAsync(); } public async Task> BatchApprovePersonnelAsync(int[] personnelIds, int approvedByUnitId, PersonnelLevel level) { var approvedPersonnel = new List(); foreach (var personnelId in personnelIds) { try { var personnel = await ApproveAsync(personnelId, approvedByUnitId, level); approvedPersonnel.Add(personnel); // 记录审批历史 await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Approved, PersonnelStatus.Pending, PersonnelStatus.Approved, null, level, await GetUserIdByUnitAsync(approvedByUnitId), approvedByUnitId, "批量审批通过"); } catch (Exception ex) { _logger.LogError(ex, "批量审批人员 {PersonnelId} 失败", personnelId); // 继续处理其他人员,不中断整个批量操作 } } return approvedPersonnel; } public async Task> BatchRejectPersonnelAsync(int[] personnelIds, int reviewedByUserId, string reason) { var rejectedPersonnel = new List(); foreach (var personnelId in personnelIds) { try { var personnel = await RejectAsync(personnelId, reviewedByUserId); rejectedPersonnel.Add(personnel); // 记录审批历史 await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Rejected, PersonnelStatus.Pending, PersonnelStatus.Rejected, null, null, reviewedByUserId, null, reason); } catch (Exception ex) { _logger.LogError(ex, "批量拒绝人员 {PersonnelId} 失败", personnelId); // 继续处理其他人员,不中断整个批量操作 } } return rejectedPersonnel; } public async Task> GetPersonnelApprovalHistoryAsync(int personnelId) { return await _context.PersonnelApprovalHistories .Include(h => h.ReviewedByUser) .Include(h => h.ReviewedByUnit) .Where(h => h.PersonnelId == personnelId) .OrderByDescending(h => h.ReviewedAt) .ToListAsync(); } public async Task CanApprovePersonnelAsync(int userId, int personnelId) { var user = await _context.UserAccounts .Include(u => u.OrganizationalUnit) .FirstOrDefaultAsync(u => u.Id == userId); if (user == null) return false; var personnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null || personnel.Status != PersonnelStatus.Pending) return false; // 同一单位可以审批自己提交的人员 if (user.OrganizationalUnitId == personnel.SubmittedByUnitId) return true; // 检查用户的组织单位是否是提交单位的上级 var isParent = await _organizationService.IsParentUnitAsync(user.OrganizationalUnitId, personnel.SubmittedByUnitId); return isParent; } /// /// 记录人员审批历史 /// private async Task RecordApprovalHistoryAsync(int personnelId, PersonnelApprovalAction action, PersonnelStatus? previousStatus, PersonnelStatus newStatus, PersonnelLevel? previousLevel, PersonnelLevel? newLevel, int reviewedByUserId, int? reviewedByUnitId, string? comments) { var history = new PersonnelApprovalHistory { PersonnelId = personnelId, Action = action, PreviousStatus = previousStatus, NewStatus = newStatus, PreviousLevel = previousLevel, NewLevel = newLevel, ReviewedByUserId = reviewedByUserId, ReviewedByUnitId = reviewedByUnitId, Comments = comments, ReviewedAt = DateTime.UtcNow }; _context.PersonnelApprovalHistories.Add(history); await _context.SaveChangesAsync(); } /// /// 根据单位ID获取用户ID(用于审批历史记录) /// private async Task GetUserIdByUnitAsync(int unitId) { var user = await _context.UserAccounts .FirstOrDefaultAsync(u => u.OrganizationalUnitId == unitId); return user?.Id ?? 0; // 如果找不到用户,返回0作为系统操作 } }