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 = null) { var personnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId); if (approvedByUnit == null) throw new ArgumentException("审批单位不存在"); var previousStatus = personnel.Status; var previousLevel = personnel.ApprovedLevel; PersonnelLevel actualLevel; if (level.HasValue) { actualLevel = level.Value; } else { // 区分首次审批和向上申报两种场景 if (previousStatus == PersonnelStatus.Pending) { // 首次审批:人员等级根据提交单位的层级确定 // 例如:营级单位提交的人才,团级审批后应为"营级人才" actualLevel = (PersonnelLevel)(int)personnel.SubmittedByUnit!.Level; // 验证审批单位层级必须高于提交单位层级(数值越小层级越高) var unitLevelValue = (int)approvedByUnit.Level; var submittedUnitLevelValue = (int)personnel.SubmittedByUnit!.Level; if (unitLevelValue >= submittedUnitLevelValue) throw new ArgumentException("审批单位层级必须高于提交单位层级"); } else if (previousStatus == PersonnelStatus.Approved) { // 向上申报:人员等级升级为上报单位(即之前的审批单位)的层级 // 例如:营级人才由团级向上申报,师级审批后应为"团级人才" if (personnel.ApprovedByUnit == null) throw new ArgumentException("无法确定上报单位"); actualLevel = (PersonnelLevel)(int)personnel.ApprovedByUnit.Level; // 验证审批单位层级必须高于当前审批单位层级(数值越小层级越高) var unitLevelValue = (int)approvedByUnit.Level; var currentApprovedUnitLevelValue = (int)personnel.ApprovedByUnit.Level; if (unitLevelValue >= currentApprovedUnitLevelValue) throw new ArgumentException("审批单位层级必须高于当前审批单位层级"); } else { throw new ArgumentException("该人员状态不允许审批"); } } personnel.Status = PersonnelStatus.Approved; personnel.ApprovedByUnitId = approvedByUnitId; personnel.ApprovedLevel = actualLevel; personnel.ApprovedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); // 记录审批历史 var userId = await GetUserIdByUnitAsync(approvedByUnitId); var actionType = previousStatus == PersonnelStatus.Approved ? PersonnelApprovalAction.LevelUpgraded : PersonnelApprovalAction.Approved; var comments = previousStatus == PersonnelStatus.Approved ? $"向上申报通过,等级从{GetLevelName(previousLevel)}升级为{GetLevelName(actualLevel)}" : "审批通过"; await RecordApprovalHistoryAsync(personnelId, actionType, previousStatus, PersonnelStatus.Approved, previousLevel, actualLevel, userId, approvedByUnitId, comments); _logger.LogInformation("人员 {PersonnelId} 已被单位 {UnitId} 审批通过,等级:{Level}", personnelId, approvedByUnitId, actualLevel); return personnel; } /// /// 获取等级名称 /// private static string GetLevelName(PersonnelLevel? level) { return level switch { PersonnelLevel.Division => "师级人才", PersonnelLevel.Regiment => "团级人才", PersonnelLevel.Battalion => "营级人才", PersonnelLevel.Company => "连级人才", _ => "未定级" }; } 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("军衔不能为空"); // Gender和Age已设置默认值,不需要验证 // IdNumber(士兵证号)是可选的,不需要验证必填 if (personnel.SubmittedByUnitId <= 0) errors.Add("提交单位不能为空"); // 验证士兵证号格式(如果提供了) // 注意:士兵证号不是身份证号,格式可能不同,这里移除18位的限制 // 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) .Include(p => p.ApprovedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null) return false; // 已拒绝的人员不能审批 if (personnel.Status == PersonnelStatus.Rejected) return false; // 本单位不能审批自己提交的人员,必须由上级单位审批 if (user.OrganizationalUnitId == personnel.SubmittedByUnitId) return false; // 如果是已审批的人员(向上申报场景) if (personnel.Status == PersonnelStatus.Approved && personnel.ApprovedByUnitId.HasValue) { // 用户单位层级必须高于已审批单位层级(数值越小层级越高) if ((int)user.OrganizationalUnit!.Level >= (int)personnel.ApprovedByUnit!.Level) return false; // 向上申报场景:检查用户单位是否是当前审批单位的上级 var isParentOfApprovedUnit = await _organizationService.IsParentUnitAsync( user.OrganizationalUnitId, personnel.ApprovedByUnitId.Value); return isParentOfApprovedUnit; } // 首次审批场景:检查用户的组织单位是否是提交单位的上级 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作为系统操作 } /// /// 发起向上申报请求 /// public async Task RequestUpgradeAsync(int personnelId, int requestByUnitId) { var personnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); if (personnel.Status != PersonnelStatus.Approved) throw new ArgumentException("只有已审批的人员才能向上申报"); if (personnel.PendingUpgradeByUnitId.HasValue) throw new ArgumentException("该人员已有待处理的向上申报请求"); var requestByUnit = await _context.OrganizationalUnits.FindAsync(requestByUnitId); if (requestByUnit == null) throw new ArgumentException("申报单位不存在"); // 师级人才不能再向上申报 if (personnel.ApprovedLevel == PersonnelLevel.Division) throw new ArgumentException("师级人才不能再向上申报"); // 特殊情况:师部可以直接升级团级人才为师级 // 此时师部既是申报单位也是审批单位 if (requestByUnit.Level == OrganizationalLevel.Division && personnel.ApprovedLevel == PersonnelLevel.Regiment) { // 师部直接升级团级人才,不需要验证是否是审批单位 // 标记为待向上申报(由师部自己审批) personnel.PendingUpgradeByUnitId = requestByUnitId; await _context.SaveChangesAsync(); _logger.LogInformation("团级人才 {PersonnelId} 已由师部 {UnitId} 发起直接升级请求", personnelId, requestByUnitId); return personnel; } // 验证申报单位必须是当前审批单位 if (personnel.ApprovedByUnitId != requestByUnitId) throw new ArgumentException("只有当前审批单位才能发起向上申报"); // 标记为待向上申报 personnel.PendingUpgradeByUnitId = requestByUnitId; await _context.SaveChangesAsync(); _logger.LogInformation("人员 {PersonnelId} 已由单位 {UnitId} 发起向上申报请求", personnelId, requestByUnitId); return personnel; } /// /// 审批向上申报请求 /// public async Task ApproveUpgradeAsync(int personnelId, int approvedByUnitId) { var personnel = await _context.Personnel .Include(p => p.SubmittedByUnit) .Include(p => p.ApprovedByUnit) .Include(p => p.PendingUpgradeByUnit) .FirstOrDefaultAsync(p => p.Id == personnelId); if (personnel == null) throw new ArgumentException("人员记录不存在"); if (!personnel.PendingUpgradeByUnitId.HasValue) throw new ArgumentException("该人员没有待处理的向上申报请求"); var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId); if (approvedByUnit == null) throw new ArgumentException("审批单位不存在"); _logger.LogInformation("ApproveUpgrade: personnelId={PersonnelId}, approvedByUnitId={ApprovedByUnitId}, pendingUpgradeByUnitId={PendingUpgradeByUnitId}, approvedByUnitLevel={Level}, personnelApprovedLevel={PersonnelLevel}", personnelId, approvedByUnitId, personnel.PendingUpgradeByUnitId.Value, approvedByUnit.Level, personnel.ApprovedLevel); var previousLevel = personnel.ApprovedLevel; PersonnelLevel newLevel; // 特殊情况:师部直接升级团级人才为师级 var isDivisionUnit = approvedByUnit.Level == OrganizationalLevel.Division; var isRegimentPersonnel = personnel.ApprovedLevel == PersonnelLevel.Regiment; _logger.LogInformation("检查条件: isDivisionUnit={IsDivision}, isRegimentPersonnel={IsRegiment}", isDivisionUnit, isRegimentPersonnel); if (isDivisionUnit && isRegimentPersonnel) { // 师部直接升级团级人才为师级 newLevel = PersonnelLevel.Division; _logger.LogInformation("师部直接升级团级人才为师级"); } else { // 验证审批单位必须是申报单位的上级 var isParent = await _organizationService.IsParentUnitAsync(approvedByUnitId, personnel.PendingUpgradeByUnitId.Value); _logger.LogInformation("检查上级关系: isParent={IsParent}", isParent); if (!isParent) throw new ArgumentException("审批单位必须是申报单位的上级"); // 人才等级升级为申报单位的等级 newLevel = (PersonnelLevel)(int)personnel.PendingUpgradeByUnit!.Level; } personnel.ApprovedLevel = newLevel; personnel.ApprovedByUnitId = approvedByUnitId; personnel.ApprovedAt = DateTime.UtcNow; personnel.PendingUpgradeByUnitId = null; // 清除待申报标记 await _context.SaveChangesAsync(); // 记录审批历史 var userId = await GetUserIdByUnitAsync(approvedByUnitId); await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.LevelUpgraded, PersonnelStatus.Approved, PersonnelStatus.Approved, previousLevel, newLevel, userId, approvedByUnitId, $"向上申报通过,等级从{GetLevelName(previousLevel)}升级为{GetLevelName(newLevel)}"); _logger.LogInformation("人员 {PersonnelId} 向上申报已被单位 {UnitId} 审批通过,等级升级为 {Level}", personnelId, approvedByUnitId, newLevel); return personnel; } }