feat(题目): 结果标题说清楚错在哪——「在例子 1 上就错了」「所有测试点都对了」,答错时附上题目对输出的原话
- 在公开例子上就错了的:标题写「答案错误 · 在例子 N 上就错了」,不再挂「通过 x/y 个测试点」 和进度条 —— 那时候那个数字没意义,先把例子跑对 - 做对了:「答案正确 · 所有测试点都对了」 - 答案错误的说明末尾摆出题目「输出」那一节的原话:格式不对、漏了一行这类错,对着原话一看就明白 - 例子都对、错在隐藏测试点的,给「去自己输入试试」(SQL 题不给,跑不了) - 提交详情页的标题不变 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b4afcbd47f
commit
8f0d39bb5a
2 files changed
+110
-10
No files matched your search
@@ -145,6 +145,41 @@ const msg = computed(() => {
|
||||
// 这是学生这边唯一能看出「比上次多过了几个点」的地方。
|
||||
const partialCases = computed(() => submissionPartialCases(props.submission))
|
||||
|
||||
/** 在公开的例子上就错了:这时候「通过 x/y 个测试点」没意义,先说是哪个例子 */
|
||||
const failedOnSample = computed(() =>
|
||||
sampleCheck.value && !sampleCheck.value.passed ? sampleCheck.value : null,
|
||||
)
|
||||
|
||||
/**
|
||||
* 结果标题(设计文档第 6 节)。比「答案错误 · 通过 1/3 个测试点」多走一步:
|
||||
* 例子上就错了的说「在例子 N 上就错了」,例子都对的才报测试点;做对了说全对了。
|
||||
* 提交详情页还用通用的 submissionResultTitle
|
||||
*/
|
||||
const title = computed(() => {
|
||||
const submission = props.submission
|
||||
if (!submission) return ""
|
||||
if (submission.result === SubmissionStatus.accepted) return "答案正确 · 所有测试点都对了"
|
||||
if (failedOnSample.value) {
|
||||
return `答案错误 · 在例子 ${(failedOnSample.value.index ?? 0) + 1} 上就错了`
|
||||
}
|
||||
const cases = hiddenCases.value
|
||||
if (cases) return `答案错误 · 通过 ${cases.passed}/${cases.total} 个测试点`
|
||||
return submissionResultTitle(submission)
|
||||
})
|
||||
|
||||
/**
|
||||
* 例子都对了、错在隐藏的测试点上:一个都没过也要报「通过 0/5」—— 那正说明例子之外的全错了。
|
||||
* 其余情况沿用 submissionPartialCases(一个都没过就不报)
|
||||
*/
|
||||
const hiddenCases = computed(() => {
|
||||
const summary = props.submission?.caseSummary
|
||||
if (!sampleCheck.value?.passed || !summary || summary.passed >= summary.total) return null
|
||||
return summary
|
||||
})
|
||||
const progressCases = computed(
|
||||
() => hiddenCases.value ?? (failedOnSample.value ? null : partialCases.value),
|
||||
)
|
||||
|
||||
// 是否显示AI提示区域。
|
||||
// 阈值和后端 POST /ai/hint 共用契约里的 HINT_MIN_FAILURES,别在这里写死数字;
|
||||
// 编译失败不数次数,和后端同口径(理由见 HINT_MIN_FAILURES 的注释);
|
||||
@@ -214,16 +249,12 @@ const columns: DataTableColumn<JudgeCaseResult>[] = [
|
||||
|
||||
<template>
|
||||
<div v-if="submission">
|
||||
<n-alert
|
||||
:type="JUDGE_STATUS[submission.result]['type']"
|
||||
:title="submissionResultTitle(submission)"
|
||||
class="mb-3"
|
||||
>
|
||||
<template v-if="partialCases" #default>
|
||||
<n-alert :type="JUDGE_STATUS[submission.result]['type']" :title="title" class="mb-3">
|
||||
<template v-if="progressCases" #default>
|
||||
<n-progress
|
||||
type="line"
|
||||
status="success"
|
||||
:percentage="(partialCases.passed / partialCases.total) * 100"
|
||||
:percentage="(progressCases.passed / progressCases.total) * 100"
|
||||
:show-indicator="false"
|
||||
/>
|
||||
</template>
|
||||
@@ -248,6 +279,7 @@ const columns: DataTableColumn<JudgeCaseResult>[] = [
|
||||
<RuntimeErrorExplain v-if="runtimeError" :info="runtimeError" :code="submission.code" />
|
||||
<WrongAnswerExplain
|
||||
v-if="sampleCheck"
|
||||
full
|
||||
:check="sampleCheck"
|
||||
:code="submission.code"
|
||||
:language="submission.language"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from "pinia"
|
||||
import { useDark } from "@vueuse/core"
|
||||
import { MdPreview } from "md-editor-v3"
|
||||
import "md-editor-v3/lib/preview.css"
|
||||
import { useProblemStore } from "oj/store/problem"
|
||||
import { useSubmissionStore } from "oj/store/submission"
|
||||
import { JUDGE_STATUS, SubmissionStatus } from "utils/constants"
|
||||
import {
|
||||
classifyDiff,
|
||||
@@ -21,8 +27,24 @@ const props = defineProps<{
|
||||
* 前端试跑也不能绕过去
|
||||
*/
|
||||
plain?: boolean
|
||||
/**
|
||||
* 提交结果里用:末尾摆出题目对输出的原话,例子都对时再给「去自己输入试试」。
|
||||
* 格式错、漏了一行这类错误,对着题目原话一看就明白;运行例子那边不需要
|
||||
*/
|
||||
full?: boolean
|
||||
}>()
|
||||
|
||||
const isDark = useDark()
|
||||
const { problem } = storeToRefs(useProblemStore())
|
||||
const submissionStore = useSubmissionStore()
|
||||
|
||||
/** 题目要求的输出(题面「输出」那一节的原文,Markdown)。SQL 题没有这一节 */
|
||||
const requirement = computed(() =>
|
||||
props.full && !problem.value?.sqlConfig ? (problem.value?.outputDescription ?? "").trim() : "",
|
||||
)
|
||||
/** 自己输入走 Judge0,SQL 跑不了 */
|
||||
const canCustomRun = computed(() => props.full && !problem.value?.sqlConfig)
|
||||
|
||||
/** 后端每段截到 2000 字,到了上限就是被截过 */
|
||||
const TEXT_LIMIT = 2000
|
||||
|
||||
@@ -62,9 +84,20 @@ function lines(text: string) {
|
||||
|
||||
<template>
|
||||
<n-card embedded class="explain-card">
|
||||
<div v-if="check.passed" class="explain">
|
||||
题目里的例子都对了,没通过的是隐藏的测试点。想想特殊情况:最大的数、最小的数、0、负数,或者题目里专门提到的情况。
|
||||
</div>
|
||||
<n-flex v-if="check.passed" vertical :size="10">
|
||||
<div class="explain">
|
||||
题目里的例子都对了,没通过的是隐藏的测试点。想想特殊情况:最大的数、最小的数、0、负数,或者题目里专门提到的情况。
|
||||
</div>
|
||||
<n-button
|
||||
v-if="canCustomRun"
|
||||
text
|
||||
type="primary"
|
||||
class="custom"
|
||||
@click="submissionStore.revealResult('custom')"
|
||||
>
|
||||
去自己输入试试 ›
|
||||
</n-button>
|
||||
</n-flex>
|
||||
<n-flex v-else vertical :size="12">
|
||||
<div class="explain">
|
||||
<b>例子 {{ (check.index ?? 0) + 1 }} 没有通过{{ plain ? "。" : ":" }}</b
|
||||
@@ -112,6 +145,14 @@ function lines(text: string) {
|
||||
</div>
|
||||
</div>
|
||||
</n-flex>
|
||||
<div v-if="requirement" class="requirement">
|
||||
<div class="label">题目要求的输出</div>
|
||||
<MdPreview
|
||||
preview-theme="vuepress"
|
||||
:model-value="requirement"
|
||||
:theme="isDark ? 'dark' : 'light'"
|
||||
/>
|
||||
</div>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
@@ -120,6 +161,33 @@ function lines(text: string) {
|
||||
max-width: 560px;
|
||||
}
|
||||
|
||||
.custom {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.requirement {
|
||||
margin-top: 14px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px dashed rgba(128, 128, 128, 0.3);
|
||||
}
|
||||
|
||||
/* md-editor 的预览自带白底、一圈 padding 和段落外边距,放在灰卡片里像一块补丁 */
|
||||
.requirement :deep(.md-editor) {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.requirement :deep(.md-editor-preview-wrapper) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.requirement :deep(.md-editor-preview > :first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.requirement :deep(.md-editor-preview > :last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.explain {
|
||||
font-size: 16px;
|
||||
line-height: 1.7;
|
||||
|
||||
Reference in new issue
Block a user