Files
OJ2/apps/web/src/oj/problem/components/CompileErrorExplain.vue
T
xuyueandClaude Opus 5.5 566599614a
Deploy / deploy (push) Successful in 1m0s
style(结果页签): 分段、说明、对比改成和题面同一套样子;做对后「接着做」直接给下一题
- 提交结果 / 运行例子 / 自己输入改成浅灰底的分段按钮;状态大字和测试点方块放大一档
- 哪里不对一律是黄色小节标题(例子 1 没对上、错在没给你看的测试点、第 2 行出错),说明用正文大小
- 答错的对比竖着排成灰 / 绿 / 红三格,和题面的例子一个样子;运行时错误把出错那一行放进红格
- 做对了去掉浅绿卡片,改成「接着做」一句话加写着下一题题号题名的大按钮
- 提交详情页的答错对比不变

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 22:09:31 +08:00

138 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { useThemeVars } from 'naive-ui'
import { useCodeStore } from 'oj/store/code'
import { findChinesePunctuation } from 'oj/problem/utils/chinesePunctuation'
import { applyFixes, clearErrorMark, currentCode, showErrorMark, showPunctuationMarks } from 'oj/problem/utils/errorMark'
import { explainCCompileError } from 'oj/problem/utils/cError'
import { explainPythonCompileError } from 'utils/pythonError'
import { stripJudgePath } from 'utils/judge'
import SectionHead from './SectionHead.vue'
/**
* 编译错误的中文说明卡片:Python 的语法错误走 pythonError.ts,C / C++ 的 gcc 报错走
* cError.ts,两张表给出同一种形状。Python 有两处来源:提交前的语法检查(SubmitCode,
* 报错来自服务端的 CPython)和判题回来的编译错误(来自判题机),同一个大版本的
* CPython,报错原文一样。
*
* 挂上就在编辑器里标出位置,卸掉就清掉。
*/
const props = withDefaults(
defineProps<{
/** 编译器的报错原文(判题机的 `err_info`,或 `/code/format` 的 syntax-error) */
errInfo: string
language?: string
}>(),
{ language: 'Python' },
)
const codeStore = useCodeStore()
const theme = useThemeVars()
const explanation = computed(() =>
props.language === 'Python'
? explainPythonCompileError(props.errInfo, codeStore.code.value)
: explainCCompileError(props.errInfo, codeStore.code.value, props.language),
)
const rawError = computed(() => stripJudgePath(props.errInfo))
/**
* 报错只点名第一处。别的行也有中文标点的话,一句话带过(设计稿「语法没过」:
* 「第 4 行也有一个中文冒号,编辑器里都标出来了」)。原来这里还摆一段出错那行的代码摘录,
* 编辑器里已经标着红,设计稿里去掉了
*/
const otherPunctuationLines = computed(() => {
const ex = explanation.value
if (!ex?.punctuation) return []
const code = codeStore.code.value
const lines = new Set<number>()
for (const fix of findChinesePunctuation(code, props.language)) {
lines.add(code.slice(0, fix.from).split('\n').length)
}
lines.delete(ex.line ?? -1)
return [...lines].sort((a, b) => a - b)
})
// 数的是编辑器里**现在**的代码:学生可能已经自己改掉几处了
const punctuationFixCount = computed(() => (explanation.value?.punctuation ? findChinesePunctuation(codeStore.code.value, props.language).length : 0))
const fixedCount = ref<number | null>(null)
function fixPunctuation() {
const code = currentCode()
if (code === null) return
const fixes = findChinesePunctuation(code, props.language)
if (applyFixes(fixes)) fixedCount.value = fixes.length
}
watch(
explanation,
(ex) => {
fixedCount.value = null
if (ex?.line) showErrorMark(ex.line, ex.sourceLine, ex.caret)
else clearErrorMark()
// 中文标点一处不漏地标出来,和按钮上的「N 处」对得上
const code = ex?.punctuation ? currentCode() : null
if (code !== null) showPunctuationMarks(findChinesePunctuation(code, props.language))
},
{ immediate: true },
)
onUnmounted(clearErrorMark)
</script>
<template>
<!-- 设计稿「题目页观感」结果 X:黄色小节标题说第几行,正文大小的中文说明;那一行编辑器里已经标红了 -->
<div class="explain-section">
<template v-if="explanation">
<SectionHead icon="problem" tone="amber">{{ explanation.line ? `第 ${explanation.line} 行` : '代码的格式写错了' }}</SectionHead>
<p class="explain">{{ explanation.message }}</p>
<p v-if="otherPunctuationLines.length" class="explain other">第 {{ otherPunctuationLines.join('、') }} 行也有中文标点,编辑器里都标出来了。</p>
<div v-if="explanation.punctuation" class="fix">
<n-button v-if="punctuationFixCount" type="primary" @click="fixPunctuation"> 把中文标点都换成英文({{ punctuationFixCount }} 处) </n-button>
<n-text v-else-if="fixedCount" type="success"> 换好了 {{ fixedCount }} 处,再提交一次试试。 </n-text>
</div>
<n-collapse class="raw-collapse">
<n-collapse-item title="原始报错(英文)" name="raw">
<div class="raw">{{ rawError }}</div>
</n-collapse-item>
</n-collapse>
</template>
<!-- 翻译表没覆盖到的句式(生产数据里约 0.3%):照旧给原文 -->
<template v-else>
<SectionHead icon="problem" tone="amber">代码的格式写错了</SectionHead>
<p class="explain">请仔细检查,看看代码的格式是不是写错了!</p>
<div class="raw">{{ rawError }}</div>
</template>
</div>
</template>
<style scoped>
.explain-section {
display: flex;
flex-direction: column;
}
.explain {
margin: 0 0 10px;
font-size: 16px;
line-height: 1.75;
}
.explain.other {
font-size: 14px;
color: v-bind('theme.textColor2');
}
.fix {
margin-bottom: 10px;
}
.raw {
white-space: pre;
overflow-x: auto;
line-height: 1.5;
font-family: Consolas, Monaco, monospace;
font-size: 13px;
}
</style>