1. 教室容量按 1/2 计算
- ExamArrangementService.cs: SelectRooms() 使用 Capacity / 2 选择房间、计算剩余座位和总容量
- MakeupExamArrangementService.cs: 数据库查询用 x.Capacity >= enrolledCount * 2(等价于 Capacity/2 >=
enrolledCount),消息显示有效座位数
2. 教学楼限制多选
- Domain: ExamSession 和 MakeupExamSession 新增 RequiredBuildingIds (JSON string),保留旧 RequiredBuildingId 向后兼容
- Service: RoomGroupKey 改为字符串键确保值相等;GroupKey() 合并新旧字段
- Controller: 请求 DTO 增加 RequiredBuildingIds (Guid 数组),响应包含该字段
- DB: MySQL 迁移 + SQLite migrator 添加新列
- Frontend: <el-select> 改为 multiple,新增 parseBuildingIds() 解析服务器返回的 JSON
3. 导出签名单后台任务
- 新增: ExamSignInExportJob 实体、ExamSignInExportJobProcessor、ExamSignInExportJobStatus 枚举
- BackgroundJobKind: 新增 ExamSignInExport = 5
- RabbitMQ: routing key exam.sign-in-export,队列 jiaowu.background-jobs.exam.sign-in-export
- API: POST /sign-in-export 创建任务返回 202;GET /sign-in-exports/{jobId} 查询状态;GET
/sign-in-exports/{jobId}/download 下载文件
- Frontend: 导出改为异步任务 + 轮询 + 自动下载,显示进度条
- 恢复: OutboxPublisher 启动时恢复未完成的任务,重试超限自动标记失败
This commit is contained in:
@@ -110,6 +110,7 @@ public sealed class MakeupExamsController(
|
||||
item.StartsAt,
|
||||
item.EndsAt,
|
||||
item.RequiredBuildingId,
|
||||
item.RequiredBuildingIds,
|
||||
RequiredBuildingName = item.RequiredBuilding != null
|
||||
? item.RequiredBuilding.Name : null,
|
||||
item.RequiredInvigilatorCount,
|
||||
@@ -220,6 +221,7 @@ public sealed class MakeupExamsController(
|
||||
StartsAt = startsAt,
|
||||
EndsAt = endsAt,
|
||||
RequiredBuildingId = request.RequiredBuildingId,
|
||||
RequiredBuildingIds = SerializeBuildingIds(request.RequiredBuildingIds),
|
||||
RequiredInvigilatorCount = request.RequiredInvigilatorCount,
|
||||
Notes = Normalize(request.Notes),
|
||||
Invigilators = (request.InvigilatorIds ?? []).Distinct().Select(id =>
|
||||
@@ -288,6 +290,7 @@ public sealed class MakeupExamsController(
|
||||
StartsAt = startsAt,
|
||||
EndsAt = endsAt,
|
||||
RequiredBuildingId = request.RequiredBuildingId,
|
||||
RequiredBuildingIds = SerializeBuildingIds(request.RequiredBuildingIds),
|
||||
RequiredInvigilatorCount = request.RequiredInvigilatorCount,
|
||||
Notes = Normalize(request.Notes)
|
||||
}));
|
||||
@@ -339,6 +342,7 @@ public sealed class MakeupExamsController(
|
||||
session.StartsAt = startsAt;
|
||||
session.EndsAt = endsAt;
|
||||
session.RequiredBuildingId = request.RequiredBuildingId;
|
||||
session.RequiredBuildingIds = SerializeBuildingIds(request.RequiredBuildingIds);
|
||||
session.RequiredInvigilatorCount = request.RequiredInvigilatorCount;
|
||||
session.Notes = Normalize(request.Notes);
|
||||
|
||||
@@ -1222,6 +1226,10 @@ public sealed class MakeupExamsController(
|
||||
});
|
||||
private static string? Normalize(string? value) =>
|
||||
string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||||
private static string? SerializeBuildingIds(IReadOnlyCollection<Guid>? ids) =>
|
||||
ids is { Count: > 0 }
|
||||
? System.Text.Json.JsonSerializer.Serialize(ids)
|
||||
: null;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
@@ -1240,6 +1248,7 @@ public sealed record CreateMakeupExamSessionRequest(
|
||||
[Range(1, 30)] int StartPeriod,
|
||||
[Range(1, 6)] int PeriodCount,
|
||||
Guid? RequiredBuildingId,
|
||||
IReadOnlyCollection<Guid>? RequiredBuildingIds,
|
||||
[Range(1, 10)] int RequiredInvigilatorCount,
|
||||
IReadOnlyCollection<Guid>? InvigilatorIds,
|
||||
[MaxLength(500)] string? Notes);
|
||||
@@ -1250,6 +1259,7 @@ public sealed record CreateMakeupExamSessionsBatchRequest(
|
||||
[Range(1, 30)] int StartPeriod,
|
||||
[Range(1, 6)] int PeriodCount,
|
||||
Guid? RequiredBuildingId,
|
||||
IReadOnlyCollection<Guid>? RequiredBuildingIds,
|
||||
[Range(1, 10)] int RequiredInvigilatorCount,
|
||||
[MaxLength(500)] string? Notes);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user