corps/src/MilitaryTrainingManagement/Controllers/PersonnelController.cs
2026-01-17 00:44:32 +08:00

791 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MilitaryTrainingManagement.Authorization;
using MilitaryTrainingManagement.Models.DTOs;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Models.Enums;
using MilitaryTrainingManagement.Services.Interfaces;
namespace MilitaryTrainingManagement.Controllers;
/// <summary>
/// 人员管理控制器
/// </summary>
[Authorize]
public class PersonnelController : BaseApiController
{
private readonly IPersonnelService _personnelService;
private readonly IFileUploadService _fileUploadService;
private readonly IOrganizationalAuthorizationService _authorizationService;
public PersonnelController(
IPersonnelService personnelService,
IFileUploadService fileUploadService,
IOrganizationalAuthorizationService authorizationService)
{
_personnelService = personnelService;
_fileUploadService = fileUploadService;
_authorizationService = authorizationService;
}
/// <summary>
/// 根据出生年月计算年龄
/// </summary>
private int CalculateAge(string? birthDate)
{
if (string.IsNullOrWhiteSpace(birthDate))
return 25; // 如果没有出生年月返回默认值25岁
try
{
// birthDate格式为 "YYYY-MM"
var parts = birthDate.Split('-');
if (parts.Length != 2)
return 25;
if (!int.TryParse(parts[0], out var year) || !int.TryParse(parts[1], out var month))
return 25;
var birthDateTime = new DateTime(year, month, 1);
var today = DateTime.Today;
var age = today.Year - birthDateTime.Year;
// 如果今年的生日还没到年龄减1
if (today.Month < birthDateTime.Month)
age--;
return age > 0 ? age : 25; // 确保年龄为正数
}
catch
{
return 25; // 解析失败返回默认值
}
}
/// <summary>
/// 获取人员列表(基于层级权限控制)
/// </summary>
[HttpGet]
public async Task<IActionResult> GetPersonnel(
[FromQuery] int pageNumber = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string? status = null)
{
var unitId = GetCurrentUnitId();
var userLevel = GetCurrentUnitLevel();
if (unitId == null || userLevel == null)
{
return Unauthorized();
}
var allPersonnel = await _personnelService.GetVisiblePersonnelAsync(unitId.Value, userLevel.Value);
// 状态筛选
if (!string.IsNullOrEmpty(status) && Enum.TryParse<PersonnelStatus>(status, out var statusFilter))
{
allPersonnel = allPersonnel.Where(p => p.Status == statusFilter);
}
var totalCount = allPersonnel.Count();
var items = allPersonnel
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.Select(MapToResponse)
.ToList();
return Ok(new
{
items,
totalCount,
pageNumber,
pageSize,
totalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
});
}
/// <summary>
/// 映射人员实体到响应DTO
/// </summary>
private static PersonnelResponse MapToResponse(Personnel personnel)
{
return new PersonnelResponse
{
Id = personnel.Id,
Name = personnel.Name,
PhotoPath = personnel.PhotoPath,
Position = personnel.Position,
Rank = personnel.Rank,
Gender = personnel.Gender,
IdNumber = personnel.IdNumber,
ProfessionalTitle = personnel.ProfessionalTitle,
EducationLevel = personnel.EducationLevel,
Age = personnel.Age,
Height = personnel.Height,
ContactInfo = personnel.ContactInfo,
Hometown = personnel.Hometown,
TrainingParticipation = personnel.TrainingParticipation,
Achievements = personnel.Achievements,
SupportingDocuments = personnel.SupportingDocuments,
Ethnicity = personnel.Ethnicity,
PoliticalStatus = personnel.PoliticalStatus,
BirthDate = personnel.BirthDate,
EnlistmentDate = personnel.EnlistmentDate,
Specialty = personnel.Specialty,
SubmittedByUnitId = personnel.SubmittedByUnitId,
SubmittedByUnitName = personnel.SubmittedByUnit?.Name,
ApprovedLevel = personnel.ApprovedLevel,
ApprovedByUnitId = personnel.ApprovedByUnitId,
ApprovedByUnitName = personnel.ApprovedByUnit?.Name,
Status = personnel.Status,
SubmittedAt = personnel.SubmittedAt,
ApprovedAt = personnel.ApprovedAt,
PendingUpgradeByUnitId = personnel.PendingUpgradeByUnitId
};
}
/// <summary>
/// 获取待审批的人员列表
/// </summary>
[HttpGet("pending-approval")]
public async Task<IActionResult> GetPendingApproval()
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
var personnel = await _personnelService.GetPendingApprovalPersonnelAsync(unitId.Value);
return Ok(personnel);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound();
}
// 检查访问权限
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
var hasAccess = await _authorizationService.CanAccessUnitAsync(
unitId.Value, personnel.SubmittedByUnitId);
if (!hasAccess)
{
return Forbid();
}
return Ok(MapToResponse(personnel));
}
/// <summary>
/// 提交人员数据(包含文件上传和验证)
/// </summary>
[HttpPost("submit")]
public async Task<IActionResult> SubmitPersonnel([FromForm] SubmitPersonnelRequest request,
IFormFile? photo, IFormFile? supportingDocument)
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
var personnel = new Personnel
{
Name = request.Name,
Unit = request.Unit,
Position = request.Position,
Rank = request.Rank,
Gender = "男", // 默认值
IdNumber = request.IdNumber,
ProfessionalTitle = request.ProfessionalTitle,
EducationLevel = request.EducationLevel,
Age = CalculateAge(request.BirthDate), // 根据出生年月计算年龄
Height = null,
ContactInfo = null,
Hometown = request.Hometown,
TrainingParticipation = request.TrainingParticipation,
Achievements = request.Achievements,
Ethnicity = request.Ethnicity,
PoliticalStatus = request.PoliticalStatus,
BirthDate = request.BirthDate,
EnlistmentDate = request.EnlistmentDate,
Specialty = request.Specialty,
SubmittedByUnitId = unitId.Value
};
try
{
var created = await _personnelService.SubmitPersonnelAsync(personnel, photo, supportingDocument);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost]
public async Task<IActionResult> Create([FromForm] CreatePersonnelRequest request,
IFormFile? photo, IFormFile? supportingDocuments)
{
// 调试:打印接收到的数据
Console.WriteLine($"接收到的数据: Name={request.Name}, Position={request.Position}, Rank={request.Rank}");
// 返回详细的验证错误
if (!ModelState.IsValid)
{
Console.WriteLine("模型验证失败:");
foreach (var key in ModelState.Keys)
{
var modelErrors = ModelState[key]?.Errors;
if (modelErrors != null && modelErrors.Count > 0)
{
Console.WriteLine($" {key}: {string.Join(", ", modelErrors.Select(e => e.ErrorMessage))}");
}
}
var errors = ModelState
.Where(x => x.Value?.Errors.Count > 0)
.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value?.Errors.Select(e => e.ErrorMessage).ToArray()
);
return BadRequest(new { message = "验证失败", errors });
}
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
var personnel = new Personnel
{
Name = request.Name,
Unit = request.Unit,
Position = request.Position,
Rank = request.Rank,
Gender = "男", // 默认值
IdNumber = request.IdNumber,
ProfessionalTitle = request.ProfessionalTitle,
EducationLevel = request.EducationLevel,
Age = CalculateAge(request.BirthDate), // 根据出生年月计算年龄
Height = null,
ContactInfo = null,
Hometown = request.Hometown,
TrainingParticipation = request.TrainingParticipation,
Achievements = request.Achievements,
Ethnicity = request.Ethnicity,
PoliticalStatus = request.PoliticalStatus,
BirthDate = request.BirthDate,
EnlistmentDate = request.EnlistmentDate,
Specialty = request.Specialty,
SubmittedByUnitId = unitId.Value
};
try
{
var created = await _personnelService.SubmitPersonnelAsync(personnel, photo, supportingDocuments);
return CreatedAtAction(nameof(GetById), new { id = created.Id }, created);
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// 更新人员信息(仅限未审批的人员)
/// </summary>
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromForm] UpdatePersonnelRequest request,
IFormFile? photo, IFormFile? supportingDocuments)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound();
}
// 检查是否可以修改
var canModify = await _personnelService.CanModifyPersonnelAsync(id);
if (!canModify)
{
return BadRequest("已审批的人员记录不能直接修改,请使用修改申请功能");
}
// 检查权限
var unitId = GetCurrentUnitId();
if (unitId == null || personnel.SubmittedByUnitId != unitId.Value)
{
return Forbid();
}
// 更新人员信息
personnel.Name = request.Name;
personnel.Position = request.Position;
personnel.Rank = request.Rank;
personnel.Gender = request.Gender;
personnel.ProfessionalTitle = request.ProfessionalTitle;
personnel.EducationLevel = request.EducationLevel;
personnel.Age = request.Age;
personnel.Height = request.Height;
personnel.ContactInfo = request.ContactInfo;
personnel.Hometown = request.Hometown;
personnel.TrainingParticipation = request.TrainingParticipation;
personnel.Achievements = request.Achievements;
// 处理照片上传
if (photo != null)
{
if (!string.IsNullOrEmpty(personnel.PhotoPath))
{
await _fileUploadService.DeleteFileAsync(personnel.PhotoPath);
}
personnel.PhotoPath = await _fileUploadService.UploadPhotoAsync(photo);
}
// 处理文档上传
if (supportingDocuments != null)
{
var documentPath = await _fileUploadService.UploadDocumentAsync(supportingDocuments);
if (string.IsNullOrEmpty(personnel.SupportingDocuments))
{
personnel.SupportingDocuments = documentPath;
}
else
{
personnel.SupportingDocuments += ";" + documentPath;
}
}
var updated = await _personnelService.UpdateAsync(personnel);
return Ok(updated);
}
/// <summary>
/// 请求修改已审批的人员记录
/// </summary>
[HttpPost("{id}/request-modification")]
public async Task<IActionResult> RequestModification(int id, [FromBody] PersonnelModificationRequest request)
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized();
}
try
{
var personnel = new Personnel
{
Name = request.ModifiedPersonnel.Name,
Position = request.ModifiedPersonnel.Position,
Rank = request.ModifiedPersonnel.Rank,
Gender = request.ModifiedPersonnel.Gender,
ProfessionalTitle = request.ModifiedPersonnel.ProfessionalTitle,
EducationLevel = request.ModifiedPersonnel.EducationLevel,
Age = request.ModifiedPersonnel.Age,
Height = request.ModifiedPersonnel.Height,
ContactInfo = request.ModifiedPersonnel.ContactInfo,
Hometown = request.ModifiedPersonnel.Hometown,
TrainingParticipation = request.ModifiedPersonnel.TrainingParticipation,
Achievements = request.ModifiedPersonnel.Achievements
};
var approvalRequest = await _personnelService.RequestPersonnelModificationAsync(
id, userId.Value, request.Reason, personnel);
return Ok(approvalRequest);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 上传人员照片
/// </summary>
[HttpPost("{id}/photo")]
public async Task<IActionResult> UploadPhoto(int id, IFormFile file)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound("人员记录不存在");
}
try
{
// 删除旧照片
if (!string.IsNullOrEmpty(personnel.PhotoPath))
{
await _fileUploadService.DeleteFileAsync(personnel.PhotoPath);
}
var photoPath = await _fileUploadService.UploadPhotoAsync(file);
personnel.PhotoPath = photoPath;
await _personnelService.UpdateAsync(personnel);
return Ok(new { photoPath });
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 上传支持文档
/// </summary>
[HttpPost("{id}/documents")]
public async Task<IActionResult> UploadDocument(int id, IFormFile file)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound("人员记录不存在");
}
try
{
var documentPath = await _fileUploadService.UploadDocumentAsync(file);
// 追加到现有文档列表(用分号分隔)
if (string.IsNullOrEmpty(personnel.SupportingDocuments))
{
personnel.SupportingDocuments = documentPath;
}
else
{
personnel.SupportingDocuments += ";" + documentPath;
}
await _personnelService.UpdateAsync(personnel);
return Ok(new { documentPath });
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 验证照片格式
/// </summary>
[HttpPost("validate-photo")]
public async Task<IActionResult> ValidatePhoto(IFormFile file)
{
var result = await _fileUploadService.ValidatePhotoAsync(file);
if (result.IsValid)
{
return Ok(new { isValid = true, width = result.Width, height = result.Height });
}
return BadRequest(new { isValid = false, error = result.ErrorMessage });
}
/// <summary>
/// 审批人员
/// </summary>
[HttpPost("{id}/approve")]
[Authorize(Policy = "BattalionLevel")] // 营级及以上权限
public async Task<IActionResult> Approve(int id)
{
var unitId = GetCurrentUnitId();
var userId = GetCurrentUserId();
if (unitId == null || userId == null)
{
return Unauthorized();
}
// 检查审批权限
var canApprove = await _personnelService.CanApprovePersonnelAsync(userId.Value, id);
if (!canApprove)
{
return StatusCode(403, new { message = "您没有权限审批此人员" });
}
try
{
// 不传递level参数让服务层根据人员所在单位自动确定等级
var personnel = await _personnelService.ApproveAsync(id, unitId.Value);
return Ok(MapToResponse(personnel));
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// 拒绝人员
/// </summary>
[HttpPost("{id}/reject")]
[Authorize(Policy = "BattalionLevel")] // 营级及以上权限
public async Task<IActionResult> Reject(int id, [FromBody] RejectPersonnelRequest request)
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized();
}
// 检查审批权限
var canApprove = await _personnelService.CanApprovePersonnelAsync(userId.Value, id);
if (!canApprove)
{
return StatusCode(403, new { message = "您没有权限拒绝此人员" });
}
var personnel = await _personnelService.RejectAsync(id, userId.Value);
return Ok(personnel);
}
/// <summary>
/// 批量审批人员
/// </summary>
[HttpPost("batch-approve")]
[Authorize(Policy = "RegimentLevel")] // 团级及以上权限
public async Task<IActionResult> BatchApprove([FromBody] BatchApprovePersonnelRequest request)
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
try
{
var approvedPersonnel = await _personnelService.BatchApprovePersonnelAsync(
request.PersonnelIds, unitId.Value, request.Level);
return Ok(new {
approvedCount = approvedPersonnel.Count(),
approvedPersonnel = approvedPersonnel
});
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 批量拒绝人员
/// </summary>
[HttpPost("batch-reject")]
[Authorize(Policy = "RegimentLevel")] // 团级及以上权限
public async Task<IActionResult> BatchReject([FromBody] BatchRejectPersonnelRequest request)
{
var userId = GetCurrentUserId();
if (userId == null)
{
return Unauthorized();
}
try
{
var rejectedPersonnel = await _personnelService.BatchRejectPersonnelAsync(
request.PersonnelIds, userId.Value, request.Reason);
return Ok(new {
rejectedCount = rejectedPersonnel.Count(),
rejectedPersonnel = rejectedPersonnel
});
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 跨层级人员转移
/// </summary>
[HttpPost("{id}/transfer")]
[Authorize(Policy = "BattalionLevel")] // 营级及以上权限
public async Task<IActionResult> TransferPersonnel(int id, [FromBody] TransferPersonnelRequest request)
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
try
{
var personnel = await _personnelService.TransferPersonnelAsync(
id, request.TargetUnitId, unitId.Value);
return Ok(personnel);
}
catch (ArgumentException ex)
{
return BadRequest(ex.Message);
}
catch (UnauthorizedAccessException ex)
{
return Forbid(ex.Message);
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}
/// <summary>
/// 获取人员审批历史
/// </summary>
[HttpGet("{id}/approval-history")]
public async Task<IActionResult> GetApprovalHistory(int id)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound();
}
// 检查访问权限
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
var hasAccess = await _authorizationService.CanAccessUnitAsync(
unitId.Value, personnel.SubmittedByUnitId);
if (!hasAccess)
{
return Forbid();
}
var history = await _personnelService.GetPersonnelApprovalHistoryAsync(id);
return Ok(history);
}
/// <summary>
/// 删除人员记录
/// </summary>
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var personnel = await _personnelService.GetByIdAsync(id);
if (personnel == null)
{
return NotFound(new { message = "人员记录不存在" });
}
// 检查权限:只有提交单位或上级单位可以删除
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
// 检查是否是提交单位
if (personnel.SubmittedByUnitId != unitId.Value)
{
// 检查是否有上级权限
var hasAccess = await _authorizationService.CanAccessUnitAsync(
unitId.Value, personnel.SubmittedByUnitId);
if (!hasAccess)
{
return Forbid();
}
}
// 只能删除待审批状态的人员
if (personnel.Status != PersonnelStatus.Pending)
{
return BadRequest(new { message = "只能删除待审批状态的人员记录" });
}
try
{
await _personnelService.DeleteAsync(id);
return NoContent();
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// 发起向上申报请求
/// </summary>
[HttpPost("{id}/request-upgrade")]
[Authorize(Policy = "BattalionLevel")] // 营级及以上权限
public async Task<IActionResult> RequestUpgrade(int id)
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
try
{
var personnel = await _personnelService.RequestUpgradeAsync(id, unitId.Value);
return Ok(MapToResponse(personnel));
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// 审批向上申报请求
/// </summary>
[HttpPost("{id}/approve-upgrade")]
[Authorize(Policy = "BattalionLevel")] // 营级及以上权限
public async Task<IActionResult> ApproveUpgrade(int id)
{
var unitId = GetCurrentUnitId();
if (unitId == null)
{
return Unauthorized();
}
try
{
var personnel = await _personnelService.ApproveUpgradeAsync(id, unitId.Value);
return Ok(MapToResponse(personnel));
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
}