fix(admin): CSV 表头「Word分」改为「大题分」+ 移除 getExamSubmissions 重复 examScore 键

改动(3 处):
  ① getExamSubmissions CSV 表头(L631):
       「...,客观题分,Word分,总分」→「...,客观题分,大题分,总分」
  ② 移除 getExamSubmissions 返回对象中重复定义的 examScore 键(原 L445):
       该键与 L456 的 `examScore: autoScore` 重名,对象字面量重复键「后者静默胜出」,
       L445 实为死代码。当前因 updateScores 会同步写 contestants.exam_score
       而「结果碰巧一致」,属隐患,故删除并加注释说明。
  ③ 同步两处注释口径:Word 阅卷分 → 综合大题阅卷分(getScores isExam 分支)。

不改动(保持契约):updateScores 入参名 wordScore、路由
  /api/admin/submissions/:group/:id/word、contestants.word_score 列名。
  (列名为历史沿用,语义已是「综合大题得分」,仅文案口径调整。)

影响面:仅中职/高职(isExam)分支;本科/教师组 CSV 与成绩口径不变。

验证:CSV 表头端到端实测 = 选手ID,身份证号,姓名,手机号,是否提交,客观题分,大题分,总分;
     verify_scoring_e2e.py 17/0;verify_big_question.py --cleanup 52/0;零回归。
This commit is contained in:
2026-09-22 13:05:35 +08:00
parent 23604f2718
commit e7af00beb9

View File

@@ -442,9 +442,8 @@ class AdminService extends Service {
answeredCount, answeredCount,
totalQuestions: answeredCount, totalQuestions: answeredCount,
autoScore, autoScore,
examScore: c.exam_score ?? 0,
wordScore: c.word_score ?? 0, wordScore: c.word_score ?? 0,
// 总分 = 客观题自动评分合计 + Word 阅卷分(与卷面分/Word 分口径一致); // 总分 = 客观题自动评分合计 + 综合大题阅卷分(与「卷面分 / 大题分」口径一致);
// 不读 contestants.score(未人工评分时恒为 0,会导致"客观题有分但总分=0")。 // 不读 contestants.score(未人工评分时恒为 0,会导致"客观题有分但总分=0")。
totalScore: autoScore + (c.word_score ?? 0), totalScore: autoScore + (c.word_score ?? 0),
hasWordFile: hasWord, hasWordFile: hasWord,
@@ -452,7 +451,9 @@ class AdminService extends Service {
wordFileName: (wordSub && wordSub.word_file_name) || null, wordFileName: (wordSub && wordSub.word_file_name) || null,
submitted: !!formalSubmitTime || answeredCount > 0, submitted: !!formalSubmitTime || answeredCount > 0,
submitTime: formalSubmitTime || (subs.length > 0 ? subs[0].created_at : null), submitTime: formalSubmitTime || (subs.length > 0 ? subs[0].created_at : null),
// 卷面分(客观分)统一取客观题自动评分合计,与成绩管理表口径一致 // 卷面分(客观分)统一取客观题自动评分合计,与成绩管理表口径一致。
// ⚠️ 此前本行与上方 `examScore: c.exam_score ?? 0` 重复定义(对象字面量重复键,后者静默胜出);
// 虽因 updateScores 会同步写 exam_score 而「结果碰巧一致」,但属隐患,故删除上方那条只留本条。
examScore: autoScore, examScore: autoScore,
}; };
}); });
@@ -629,8 +630,10 @@ class AdminService extends Service {
let csvContent = ''; let csvContent = '';
if (isExam) { if (isExam) {
// 中职/高职组:客观题(系统) + Word(人工) // 中职/高职组:客观题(系统自动评分) + 综合大题(人工阅卷)
csvContent = '选手ID,身份证号,姓名,手机号,是否提交,客观题分,Word分,总分\n'; // 说明:大题分落库列名为 contestants.word_score(历史沿用,语义已变为「综合大题得分」),
// 故此处取 item.wordScore,仅表头文案按现行口径显示为「大题分」。
csvContent = '选手ID,身份证号,姓名,手机号,是否提交,客观题分,大题分,总分\n';
for (const item of submissions) { for (const item of submissions) {
csvContent += [ csvContent += [
item.contestantId, item.contestantId,