Files
EIS-dotnet/src/Eis.Web/Candidate/NativeCandidateEndpoints.cs
T
biss 4417d6d674 原生成绩查询、科目/总分排名、达线判断、等级计算及成绩单防伪码:[CandidateService.Results.cs (line 11)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Candidate/CandidateService.Results.cs:11)
原生成绩复议提交,工作流、分配人与审计日志同事务写入。
原生准考证下载窗口校验及 HTML 文书生成:[CandidateAdmitCardRenderer.cs (line 9)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Infrastructure/Candidate/CandidateAdmitCardRenderer.cs:9)
三个路由已切换到 ASP.NET Core:[NativeCandidateEndpoints.cs (line 61)](C:/Users/BI/Documents/EIS-dotnet/src/Eis.Web/Candidate/NativeCandidateEndpoints.cs:61)
更新迁移说明:[MIGRATION.md (line 50)](C:/Users/BI/Documents/EIS-dotnet/MIGRATION.md:50)
2026-07-22 20:08:08 +08:00

125 lines
5.5 KiB
C#

using Eis.Application.Candidate;
using Eis.Infrastructure.Candidate;
namespace Eis.Web.Candidate;
public static class NativeCandidateEndpoints
{
public static IEndpointRouteBuilder MapNativeCandidateEndpoints(
this IEndpointRouteBuilder endpoints,
CandidateMigrationOptions options)
{
if (!options.NativeEnabled)
{
return endpoints;
}
endpoints.MapGet("/api/candidate/dashboard", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetDashboardAsync(SessionToken(context), cancellationToken)));
endpoints.MapGet("/api/candidate/notices", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetNoticesAsync(SessionToken(context), cancellationToken)));
endpoints.MapGet("/api/candidate/profile", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetProfileAsync(SessionToken(context), cancellationToken)));
endpoints.MapPut("/api/candidate/profile", async (
HttpContext context,
System.Text.Json.Nodes.JsonObject request,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.UpdateProfileAsync(SessionToken(context), request, cancellationToken)));
endpoints.MapGet("/api/candidate/exams", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetExamsAsync(SessionToken(context), cancellationToken)));
endpoints.MapGet("/api/candidate/registrations", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetRegistrationsAsync(SessionToken(context), cancellationToken)));
endpoints.MapPost("/api/candidate/registrations", async (
HttpContext context,
System.Text.Json.Nodes.JsonObject request,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.CreateRegistrationAsync(SessionToken(context), request, cancellationToken)));
endpoints.MapGet("/api/candidate/results", async (
HttpContext context,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.GetResultsAsync(
SessionToken(context),
VerificationBaseUrl(context),
cancellationToken)));
endpoints.MapPost("/api/candidate/results/{resultId}/appeals", async (
HttpContext context,
string resultId,
System.Text.Json.Nodes.JsonObject request,
ICandidateService service,
CancellationToken cancellationToken) => ToResult(
context,
await service.CreateScoreAppealAsync(
SessionToken(context),
resultId,
request,
cancellationToken)));
endpoints.MapGet("/api/candidate/registrations/{registrationId}/admit-card", async (
HttpContext context,
string registrationId,
ICandidateService service,
CancellationToken cancellationToken) => ToDocumentResult(
context,
await service.GetAdmitCardAsync(SessionToken(context), registrationId, cancellationToken)));
return endpoints;
}
private static string SessionToken(HttpContext context) =>
context.Request.Cookies.TryGetValue("hz_session", out var token) ? token : string.Empty;
private static string VerificationBaseUrl(HttpContext context)
{
var forwarded = context.Request.Headers["X-Forwarded-Proto"].ToString();
var protocol = forwarded.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()
?? context.Request.Scheme;
return $"{protocol}://{context.Request.Host.Value}";
}
private static IResult ToResult(HttpContext context, CandidateEndpointResult result)
{
context.Response.Headers.CacheControl = "no-store";
context.Response.Headers["X-EIS-Implementation"] = "aspnet-core";
return Results.Json(result.Body, statusCode: result.StatusCode);
}
private static IResult ToDocumentResult(HttpContext context, CandidateDocumentResult result)
{
context.Response.Headers.CacheControl = "no-store";
context.Response.Headers["X-EIS-Implementation"] = "aspnet-core";
if (result.Error is not null)
{
return Results.Json(result.Error, statusCode: result.StatusCode);
}
context.Response.Headers.ContentDisposition =
$"attachment; filename*=UTF-8''{Uri.EscapeDataString(result.FileName ?? "admit-card.html")}";
return Results.Content(result.Content ?? string.Empty, "text/html; charset=utf-8", statusCode: result.StatusCode);
}
}