From 1a173f75d78d6d3155916b6e9e0b4a091bfb9ea9 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Mon, 26 Oct 2026 08:52:50 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8C=91=E6=88=98):=20=E8=BF=99=E8=8A=82?= =?UTF-8?q?=E8=AF=BE=E5=81=9A=E5=AE=8C=E4=BA=86=E7=BB=99=E3=80=8C=E8=BF=98?= =?UTF-8?q?=E8=83=BD=E6=8C=91=E6=88=98=E3=80=8D=EF=BC=8C=E6=8C=91=E6=88=98?= =?UTF-8?q?=E4=B8=AD=E7=BC=96=E8=BE=91=E5=99=A8=E9=A1=B6=E4=B8=8A=E4=B8=80?= =?UTF-8?q?=E6=9D=A1=E7=B4=AB=E8=89=B2=E7=9A=84=EF=BC=8C=E8=80=81=E5=B8=88?= =?UTF-8?q?=E7=9C=8B=E6=9D=BF=E4=B8=8A=E7=9C=8B=E5=BE=97=E5=87=BA=E8=B0=81?= =?UTF-8?q?=E5=9C=A8=E6=8C=91=E6=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 做完这节课(或题库里自己做对)之后列出还能挑战的题;去挑战后编辑器顶上写着要求, 没做到标出是哪几行,做到了写本班第几个、全站第几个。课堂看板做到的格子贴一枚紫色筹码、 在挑战的加一圈紫边,题卡片写挑战成功几人。出题页多一块「挑战」,能从做对的代码里找候选。 Co-Authored-By: Claude Opus 5.5 --- apps/web/src/admin/api.ts | 11 + .../problem/components/AstRulesEditor.vue | 32 ++- .../problem/components/ChallengeEditor.vue | 265 ++++++++++++++++++ apps/web/src/admin/problem/detail.vue | 52 +++- apps/web/src/oj/api.ts | 10 + apps/web/src/oj/classroom/board.vue | 57 +++- apps/web/src/oj/classroom/boardCells.ts | 5 +- .../oj/problem/components/ChallengeBar.vue | 127 +++++++++ .../oj/problem/components/ChallengeIcon.vue | 20 ++ .../oj/problem/components/ChallengeList.vue | 201 +++++++++++++ .../problem/components/ChallengeOutcome.vue | 194 +++++++++++++ .../src/oj/problem/components/LessonNext.vue | 32 ++- .../oj/problem/components/ProblemEditor.vue | 10 +- .../problem/components/SubmissionResult.vue | 87 +++++- .../oj/problem/composables/challengeTone.ts | 24 ++ .../problem/composables/problemPageContext.ts | 8 + apps/web/src/oj/problem/utils/errorMark.ts | 40 ++- apps/web/src/oj/store/challenge.ts | 87 ++++++ apps/web/src/utils/types.ts | 5 +- 19 files changed, 1243 insertions(+), 24 deletions(-) create mode 100644 apps/web/src/admin/problem/components/ChallengeEditor.vue create mode 100644 apps/web/src/oj/problem/components/ChallengeBar.vue create mode 100644 apps/web/src/oj/problem/components/ChallengeIcon.vue create mode 100644 apps/web/src/oj/problem/components/ChallengeList.vue create mode 100644 apps/web/src/oj/problem/components/ChallengeOutcome.vue create mode 100644 apps/web/src/oj/problem/composables/challengeTone.ts create mode 100644 apps/web/src/oj/store/challenge.ts diff --git a/apps/web/src/admin/api.ts b/apps/web/src/admin/api.ts index 96556ea..43b00cc 100644 --- a/apps/web/src/admin/api.ts +++ b/apps/web/src/admin/api.ts @@ -1,6 +1,7 @@ import { toAdminType, toProblemPermission } from "@oj2/contract" import type { AddContestProblemRequest, + ChallengeSuggestionsResponse, AddProblemsToSetRequest, BatchProblemTagRequest, BatchProblemVisibleRequest, @@ -353,6 +354,16 @@ export function checkAstRules(data: AstCheckRequest) { return api.post("admin/ast-check", data satisfies AstCheckRequest) } +// 出题页「挑战」的候选:拿这道题历史上做对的代码挖 +export function getChallengeSuggestions(problemId: number, language: string) { + return api.post( + `admin/problems/${problemId}/challenge-suggestions`, + { + language, + }, + ) +} + // AI 按题面和标准答案想几组测试输入(输出由标准答案跑) export function generateTestInputs(data: GenerateTestInputsRequest) { return api.post( diff --git a/apps/web/src/admin/problem/components/AstRulesEditor.vue b/apps/web/src/admin/problem/components/AstRulesEditor.vue index 54fa8ea..e6ca136 100644 --- a/apps/web/src/admin/problem/components/AstRulesEditor.vue +++ b/apps/web/src/admin/problem/components/AstRulesEditor.vue @@ -15,6 +15,11 @@ interface Props { languages: LANGUAGE[] /** 各语言的标准答案(学生那段代码,不套模板):拿来自测规则 */ answers: Partial> + /** + * 挑战的判定规则(ChallengeEditor 里一条挑战一个)。和语法要求是同一套规则,但口径不同: + * 不满足不算错、说法由挑战自己写、标准答案不这么写是常事(挑战就是另一种写法) + */ + challenge?: boolean } const props = defineProps() @@ -294,8 +299,13 @@ watch(supportedLanguages, (langs) => {