This commit is contained in:
2026-07-24 22:18:32 +08:00 Unverified
parent d67a07f23e
commit 27c3944c28
12 changed files with 781 additions and 14 deletions
@@ -15,7 +15,8 @@ namespace Jiaowu.Api.Controllers;
[Route("api/personnel")]
public sealed class PersonnelController(
AppDbContext db,
ICurrentUserDataScope currentUserDataScope) : ControllerBase
ICurrentUserDataScope currentUserDataScope,
PersonnelAccountService personnelAccountService) : ControllerBase
{
private const string ReadRoles =
SystemRoles.SuperAdmin + "," +
@@ -103,7 +104,14 @@ public sealed class PersonnelController(
Notes = Normalize(request.Notes)
};
db.Teachers.Add(entity);
return await SaveCreatedAsync(entity.Id, cancellationToken);
return await CreateWithAccountAsync(
entity.Id,
request.InitialPassword,
() => personnelAccountService.EnsureTeacherAccountAsync(
entity,
request.InitialPassword,
cancellationToken),
cancellationToken);
}
[HttpPut("teachers/{id:guid}")]
@@ -130,6 +138,18 @@ public sealed class PersonnelController(
entity.Phone = Normalize(request.Phone);
entity.Email = Normalize(request.Email);
entity.Notes = Normalize(request.Notes);
if (!entity.UserId.HasValue &&
(string.IsNullOrWhiteSpace(request.InitialPassword) ||
request.InitialPassword.Length < 8))
return ValidationProblem("该教师档案尚未开通账号,请填写至少 8 位初始密码。");
if (entity.UserId.HasValue || !string.IsNullOrWhiteSpace(request.InitialPassword))
{
var account = await personnelAccountService.EnsureTeacherAccountAsync(
entity,
request.InitialPassword,
cancellationToken);
if (!account.Success) return AccountProblem(account.Error!);
}
return await SaveNoContentAsync(cancellationToken);
}
@@ -239,7 +259,14 @@ public sealed class PersonnelController(
Notes = Normalize(request.Notes)
};
db.Students.Add(entity);
return await SaveCreatedAsync(entity.Id, cancellationToken);
return await CreateWithAccountAsync(
entity.Id,
request.InitialPassword,
() => personnelAccountService.EnsureStudentAccountAsync(
entity,
request.InitialPassword,
cancellationToken),
cancellationToken);
}
[HttpPut("students/{id:guid}")]
@@ -276,6 +303,18 @@ public sealed class PersonnelController(
entity.Phone = Normalize(request.Phone);
entity.Email = Normalize(request.Email);
entity.Notes = Normalize(request.Notes);
if (!entity.UserId.HasValue &&
(string.IsNullOrWhiteSpace(request.InitialPassword) ||
request.InitialPassword.Length < 8))
return ValidationProblem("该学生档案尚未开通账号,请填写至少 8 位初始密码。");
if (entity.UserId.HasValue || !string.IsNullOrWhiteSpace(request.InitialPassword))
{
var account = await personnelAccountService.EnsureStudentAccountAsync(
entity,
request.InitialPassword,
cancellationToken);
if (!account.Success) return AccountProblem(account.Error!);
}
return await SaveNoContentAsync(cancellationToken);
}
@@ -372,6 +411,39 @@ public sealed class PersonnelController(
}
}
private async Task<ActionResult> CreateWithAccountAsync(
Guid id,
string? initialPassword,
Func<Task<PersonnelAccountResult>> createAccount,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(initialPassword) || initialPassword.Length < 8)
return ValidationProblem("新增人员时必须填写至少 8 位初始密码。");
await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
try
{
var account = await createAccount();
if (!account.Success)
{
await transaction.RollbackAsync(cancellationToken);
return AccountProblem(account.Error!);
}
await transaction.CommitAsync(cancellationToken);
return Created(string.Empty, new
{
id,
account.UserId,
account.UserName
});
}
catch (DbUpdateException)
{
await transaction.RollbackAsync(cancellationToken);
return ConflictProblem("编号已存在,或关联数据无效。");
}
}
private async Task<ActionResult> SaveNoContentAsync(CancellationToken cancellationToken)
{
try
@@ -393,6 +465,14 @@ public sealed class PersonnelController(
Status = StatusCodes.Status409Conflict
});
private ActionResult AccountProblem(string detail) =>
Conflict(new ProblemDetails
{
Title = "登录账号创建失败",
Detail = detail,
Status = StatusCodes.Status409Conflict
});
private static string? Normalize(string? value) =>
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
@@ -422,7 +502,8 @@ public sealed record TeacherRequest(
bool IsExternal,
[MaxLength(30)] string? Phone,
[EmailAddress, MaxLength(100)] string? Email,
[MaxLength(500)] string? Notes);
[MaxLength(500)] string? Notes,
[MinLength(8), MaxLength(100)] string? InitialPassword = null);
public sealed record StudentRequest(
[Required, MaxLength(30)] string StudentNumber,
@@ -435,4 +516,5 @@ public sealed record StudentRequest(
DateOnly? DateOfBirth,
[MaxLength(30)] string? Phone,
[EmailAddress, MaxLength(100)] string? Email,
[MaxLength(500)] string? Notes);
[MaxLength(500)] string? Notes,
[MinLength(8), MaxLength(100)] string? InitialPassword = null);