feat(阶段3): 补齐用户侧依赖的三个 admin 端点

重判、提交统计、流程图统计这三条挂在旧后端的 admin 路由下,权限也确实是
teacher/super admin,但入口在用户侧页面里(提交列表页的重判按钮、两个统计面板)。
不做完,阶段 3 的出口标准「用户侧全部功能跑在新后端上」就不成立 —— 按 URL
前缀切阶段会漏掉它们。

- POST submissions/:id/rejudge     ← GET admin/submission/rejudge
- GET  submissions/statistics      ← GET admin/submission/statistics
- GET  flowcharts/statistics       ← GET admin/flowchart/statistics

几处对齐旧后端的细节:
- AST_CHECK_FAILED(10) 与 ACCEPTED(0) 同算通过
- 完成度先用原始花名册人数算、再修正 person_count,顺序照搬,兜住「学生已删号
  但提交记录还在」
- 有提交但零通过的学生,两个名单里都不出现(旧后端同样口径)
- 词云用 @node-rs/jieba,STOPWORDS 与 38 个自定义词逐词照搬;jieba@2 没有
  insertWord,改用 loadDict 加载用户词典
- avgScore 分母是有分数的条数,对齐 Django Avg() 跳过 NULL

rejudge 的 jobId 带时间戳。队列保留最近 100 个已完成任务,沿用 submissionId
做 jobId 的话 BullMQ 会认为任务已存在,重判会静默变成空操作。

correctRate 改成数值不带 %,展示格式化交给前端。stripClassPrefix 用
startsWith+slice 而不是 replace,前缀对不上时不会从中间截出乱码;site.ts
原有的 replace 写法一并改掉。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 06:48:05 -06:00
parent cb6d42363b
commit 836d97847e
12 changed files with 787 additions and 233 deletions

View File

@@ -53,6 +53,25 @@ export const createFlowchartResponseSchema = z.object({ submissionId: z.string()
export const flowchartCurrentSchema = z.object({ count: z.number().int(), score: z.number(), grade: z.string() })
export const flowchartDetailSchema = z.object({ submission: flowchartSubmissionSchema.nullable(), count: z.number().int() })
export const flowchartStatisticsSchema = z.object({
totalCount: z.number().int(),
avgScore: z.number(),
gradeDistribution: z.record(z.string(), z.number().int()),
criteriaAverages: z.record(
z.string(),
z.object({ avg: z.number(), max: z.number() }),
),
personCount: z.number().int(),
completedCount: z.number().int(),
wordFrequencies: z.array(
z.object({ word: z.string(), count: z.number().int() }),
),
// 与提交统计共用「未完成学生」的形状,见 submission.ts 的 unacceptedStudentSchema
dataUnaccepted: z.array(
z.object({ username: z.string(), realName: z.string() }),
),
})
export const flowchartUpdateSchema = z.object({
type: z.enum([
"flowchart_evaluation_completed",
@@ -69,3 +88,4 @@ export const flowchartUpdateSchema = z.object({
})
export type FlowchartUpdate = z.infer<typeof flowchartUpdateSchema>
export type FlowchartStatistics = z.infer<typeof flowchartStatisticsSchema>