feat(流程图): AI 点评改成拿例子和测试数据在图上走一遍,同一张图不能再原样重交抽等级

原来让 AI 按逻辑 40 / 完整 30 / 规范 20 / 清晰 10 打总分:同一张图交两次能差 35 分
(有一张 C 再交变 S),22% 的提交和上一次一模一样;评语里写 node_9 这种学生看不到的编号。
照画布稿 FlowResFail / FlowResPass:
- AI 拿题目的例子和最多 3 组测试数据,从开始照着图走到结束,逐组说输出什么、对不对、
  最先错在哪个框;全对 A,全对且写法挑不出毛病 S,走对一半以上 B,否则 C
- 结果页签:「3 组走对 2 组」,逐组 ✓ / ✗,点开看「你的图输出 / 应该输出」,画布上按先后
  编号亮出这一组走过的框、错的那个标红;图一改就不亮,载回那一版又能亮
- 画布和上次评完的那张一模一样时「交给 AI 点评」灰掉;后端也兜着:同一道题一模一样的图
  直接照搬上次走例子的结果,不再问 AI
- 题目一组例子、测试数据都没有时退回老的四项分;老提交照旧按四项分显示
- 历次等级、提交列表的胶囊只写等级,不写分数

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-12 21:08:42 +08:00
1 parent 09f8a56913
commit 099c6d7ba6
17 files changed
+969 -77

No files matched your search

@@ -10,6 +10,8 @@ import { useTone } from "../composables/tone"
import { submissionTimeText } from "../utils"
import FlowchartState from "./FlowchartState.vue"
import UserName from "shared/components/UserName.vue"
import FlowchartCases from "shared/components/FlowchartCases.vue"
import { caseHeadline, caseReport } from "utils/flowchart"
/**
* 流程图模式的右栏:左边画出来的图,右边四项评分和建议。原来要点编号再开一个
@@ -124,6 +126,14 @@ function barColor(score: number, max: number) {
return tone("error").solid
}
/** 2026-10 起的「走例子」报告;老提交是 null,照旧显示四项分 */
const report = computed(() => caseReport(shown.value?.aiCriteriaDetails))
const openCase = ref<number | null>(null)
watch(
() => shown.value?.id,
() => (openCase.value = null),
)
const suggestions = computed(() =>
(shown.value?.aiSuggestions ?? "")
.split("\n")
@@ -193,7 +203,7 @@ const canRetry = computed(
</div>
<div class="meta">
<FlowchartState :status="row.status" :grade="row.aiGrade" :score="row.aiScore" />
<FlowchartState :status="row.status" :grade="row.aiGrade" />
<span>{{ submissionTimeText(row.createTime, true) }}</span>
<span v-if="row.processingTime">评分用时 {{ row.processingTime.toFixed(1) }} 秒</span>
</div>
@@ -232,6 +242,15 @@ const canRetry = computed(
<template v-else-if="row.status === FlowchartSubmissionStatus.FAILED">
<span class="muted">这次评分失败了{{ teacher ? ",可以点「重新评分」" : "" }}</span>
</template>
<template v-else-if="shown && report">
<b class="headline">{{ caseHeadline(report) }}</b>
<FlowchartCases v-model:selected="openCase" :report="report" />
<div v-if="shown.aiFeedback" class="note">{{ shown.aiFeedback }}</div>
<div v-if="shown.aiSuggestions" class="note">
<b>还可以更好:</b>
<div>{{ shown.aiSuggestions }}</div>
</div>
</template>
<template v-else-if="shown">
<div v-for="[name, item] in criteria" :key="name" class="crit">
<div class="crit-head">
@@ -442,6 +461,10 @@ const canRetry = computed(
max-height: 100%;
}
.headline {
font-size: 16px;
}
.score-box {
flex: 1 1 0;
min-width: 0;
@@ -3,13 +3,12 @@ import { FlowchartSubmissionStatus } from "utils/types"
import { useTone, type Tone } from "../composables/tone"
/**
* 流程图提交在列表里的那个胶囊:评完的直接是「A 级 86 分」,没评完的是
* 流程图提交在列表里的那个胶囊:评完的直接是「A 级」,没评完的是
* 排队中 / 评分中 / 评分失败。原来等级、分数、状态分三列,老师要横着对。
*/
const props = defineProps<{
status: number
grade: string | null
score: number | null
}>()
const tone = useTone()
@@ -35,7 +34,7 @@ const colors = computed(() => tone(view.value.tone))
<template>
<span class="pill" :style="{ color: colors.color, background: colors.background }">
<template v-if="view.grade">
<b>{{ view.grade }} 级</b><span class="score">{{ score ?? 0 }} 分</span>
<b>{{ view.grade }} 级</b>
</template>
<template v-else>{{ view.text }}</template>
</span>
@@ -54,8 +53,4 @@ const colors = computed(() => tone(view.value.tone))
white-space: nowrap;
flex: none;
}
.score {
font-weight: 400;
}
</style>