contest.ts 两处把「藏起来的难度」表示成空串,而 problemDifficultySchema 是严格的三值枚举,parse 直接抛 ZodError。contestDetailsAllowed 在 「比赛进行中 + 看的人不是管理员」时就是假 —— 也就是正常学生在正常比赛里, 比赛题列表和详情页一开就挂。dev 库 contest 表一直是空的,这条路径没被跑到过。 改成下发 null,契约里给这两个字段单独起了 maskedProblemDifficultySchema。 语义上对齐旧 Django:ProblemSafeSerializer 把 difficulty 放在 exclude 里, 字段整个不下发,而不是给一个假值。 端上顺着 null 补了四处:ProblemInfo 的「难度」项整条不渲染(和旧栈表现一致), 题目列表、题单列表同理,transforms 的 ProblemFiltered.difficulty 也放开为可空。 这几处是 vue-tsc 逐个揪出来的,正是严格枚举该起的作用。 实测(学生 / 超管 × 比赛题 / 普通题 四种组合):学生看比赛题详情与列表 从 500 变 200 且 difficulty 为 null,超管仍拿到真值 Low,普通题不受影响; 页面上「难度」整项消失,统计面板其余内容正常。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016DHxhKNxXfG89JnVzHbvgj
oj.xuyue.cc