-
-
-
-
-
-
AI 正在看你的图(一般 5 秒左右)
-
评的时候画布还能改,改了不影响这一次
-
-
-
-
-
- AI 这次没评出来,再点一次「交给 AI 点评」试试
-
-
-
-
-
+
+
+ AI 点评 · 画过 {{ scores.length + (phase === "evaluating" ? 1 : 0) }} 次:
+
+ →
+
+
+ →
+ 第 {{ scores.length + 1 }} 次
+
+
+
+ 另外 {{ hiddenCount }} 次是加入题单之前画的,先藏起来了:在题单里画到 A 或 S 就解锁
+
+
+
+
+
+
+
+
AI 正在看你的图
+
一般 5 秒左右。可以先去看题目,评完这里会亮起来
+
-
- 另外 {{ hiddenCount }} 次是加入题单之前画的,先藏起来了:在题单里画到 A 或 S 就解锁
-
+ 评的时候画布上还能改,改了不影响这一次的分数
+
-
-
-
- {{ current.score }} 分 · {{ current.grade }} 级
-
-
- 第 {{ currentIndex + 1 }} 次 · {{ parseTime(current.createTime, "MM-DD HH:mm") }}
-
-
+
+ AI 这次没评出来,再点一次「交给 AI 点评」试试
+
-
- 画到 {{ current.grade }} 级了,这道题的流程图算做完 ✓
-
+
+
+ {{ current.score }}
+ 分
+ {{ current.grade }} 级
+
+ {{ detail?.aiFeedback ?? ""
+ }}{{ isFlowchartPass(current.grade) ? " 这道题算做完了。" : "" }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ name }}
+ {{ item.score || 0 }} / {{ item.max }}
+
+
+
+
+
+
+
+
还可以改进
+
+ 重点
+ {{ line }}
+
+
+
+
+
照着它写代码 →
-
-
-
-
-
-
-
- {{ detail.aiFeedback }}
-
-
-
可以这样改
-
- - {{ line }}
-
-
-
-
-
四项得分
-
-
- {{ name }}
-
- {{ item.score || 0 }} / {{ item.max }}
-
-
-
-
-
-
-
- 把这一版载回画布
-
-
-
-
+
把这一版载回画布
+
+
+
@@ -271,18 +275,14 @@ function goCode() {
padding-bottom: 16px;
}
-.block {
- margin-bottom: 14px;
-}
-
.empty {
margin-top: 48px;
}
.note {
font-size: 13px;
- opacity: 0.75;
- margin: 2px 0 0;
+ color: v-bind("theme.textColor3");
+ margin: 0 0 10px;
}
.pad {
@@ -291,98 +291,220 @@ function goCode() {
.history {
display: flex;
+ align-items: center;
+ flex-wrap: wrap;
gap: 6px;
- overflow-x: auto;
- padding: 2px 2px 8px;
+ margin-bottom: 12px;
+ font-size: 13px;
+}
+
+.history-lead {
+ color: v-bind("theme.textColor2");
+}
+
+.arrow {
+ color: v-bind("theme.textColor3");
}
.attempt {
- flex: none;
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 1px;
- min-width: 58px;
- padding: 6px 8px;
- border-radius: 8px;
- border: 1px solid rgba(128, 128, 128, 0.25);
- background: transparent;
- color: inherit;
+ height: 26px;
+ box-sizing: border-box;
+ padding: 0 9px;
+ border-radius: 13px;
+ border: 1px solid transparent;
+ background-color: rgba(128, 128, 128, 0.12);
+ color: v-bind("theme.textColor2");
font: inherit;
font-size: 13px;
+ font-variant-numeric: tabular-nums;
cursor: pointer;
}
-.attempt b {
- font-size: 17px;
- font-variant-numeric: tabular-nums;
-}
-
-.attempt-no {
- font-size: 11px;
- opacity: 0.65;
-}
-
-.attempt.success b {
- color: #18a058;
-}
-
-.attempt.warning b {
- color: #f0a020;
-}
-
-.attempt.error b {
- color: #d03050;
-}
-
.attempt.active {
- border-color: #2080f0;
- box-shadow: 0 0 0 1px #2080f0;
+ background-color: v-bind("theme.textColor2");
+ color: v-bind("theme.cardColor");
+ font-weight: 600;
}
-.score {
- font-size: 22px;
+.attempt.pass.active {
+ background-color: v-bind("theme.successColor");
+ color: v-bind("passText");
+}
+
+.attempt.pending {
+ display: inline-flex;
+ align-items: center;
+ cursor: default;
+ background: transparent;
+ border: 1px dashed v-bind("theme.successColor");
+ color: v-bind("theme.successColorPressed");
+}
+
+.grading {
+ display: flex;
+ align-items: center;
+ gap: 14px;
+ padding: 18px;
+ margin-bottom: 10px;
+ border-radius: 8px;
+ background-color: rgba(24, 160, 88, 0.07);
+ border: 1px solid rgba(24, 160, 88, 0.25);
+}
+
+.grading-title {
+ font-size: 16px;
font-weight: 700;
}
-.pass {
- margin: 10px 0 4px;
- padding: 8px 12px;
+.grading-note {
+ margin-top: 2px;
+ font-size: 13px;
+ color: v-bind("theme.textColor2");
+}
+
+.failed {
+ padding: 12px 14px;
border-radius: 6px;
- background-color: rgba(24, 160, 88, 0.1);
+ background-color: rgba(240, 160, 32, 0.1);
+ border: 1px solid rgba(240, 160, 32, 0.35);
+}
+
+.score-line {
+ display: flex;
+ align-items: baseline;
+ flex-wrap: wrap;
+ gap: 4px 8px;
+ margin-bottom: 14px;
+}
+
+.score {
+ font-size: 34px;
+ font-weight: 700;
+ line-height: 1;
+ font-variant-numeric: tabular-nums;
+}
+
+.score.success {
+ color: v-bind("theme.successColorPressed");
+}
+
+.score.warning {
+ color: v-bind("theme.warningColorPressed");
+}
+
+.score.error {
+ color: v-bind("theme.errorColorPressed");
+}
+
+.score-unit {
+ color: v-bind("theme.textColor2");
+}
+
+.grade {
+ align-self: center;
+ padding: 2px 8px;
+ border-radius: 4px;
+ font-size: 13px;
+ font-weight: 700;
+ color: #fff;
+ background-color: v-bind("theme.errorColor");
+}
+
+.grade.success {
+ background-color: v-bind("theme.successColor");
+ color: v-bind("passText");
+}
+
+.grade.warning {
+ background-color: v-bind("theme.warningColor");
}
.feedback {
- margin: 12px 0;
- line-height: 1.7;
+ flex: 1 1 200px;
+ align-self: center;
+ margin-left: 6px;
+ font-size: 14px;
+ line-height: 1.6;
}
-h4 {
- margin: 14px 0 6px;
+/* 四项得分:两列,每项一条进度 */
+.criteria {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 12px 20px;
+ margin-bottom: 14px;
+}
+
+.criterion-head {
+ display: flex;
+ justify-content: space-between;
font-size: 14px;
}
-.suggestions ol {
- margin: 0;
- padding-left: 1.4em;
- line-height: 1.7;
+.criterion-score {
+ font-variant-numeric: tabular-nums;
+ color: v-bind("theme.textColor2");
}
-.criterion {
- padding: 6px 0;
+.bar {
+ height: 6px;
+ margin: 4px 0;
+ border-radius: 3px;
+ background-color: rgba(128, 128, 128, 0.14);
+ overflow: hidden;
}
-.criterion + .criterion {
- border-top: 1px dashed rgba(128, 128, 128, 0.2);
+.bar-fill {
+ height: 100%;
+ border-radius: 3px;
+ background-color: v-bind("theme.successColor");
+}
+
+.bar-fill.warning {
+ background-color: v-bind("theme.warningColor");
+}
+
+.bar-fill.error {
+ background-color: v-bind("theme.errorColor");
}
.comment {
- display: block;
- margin-top: 2px;
font-size: 13px;
+ color: v-bind("theme.textColor2");
}
-.load {
- margin-top: 14px;
+.suggestions {
+ padding: 12px 14px;
+ margin-bottom: 14px;
+ border-radius: 6px;
+ background-color: rgba(128, 128, 128, 0.06);
+ border: 1px solid v-bind("theme.dividerColor");
+}
+
+.suggestions-title {
+ font-weight: 600;
+ margin-bottom: 6px;
+}
+
+.suggestion {
+ display: flex;
+ align-items: baseline;
+ gap: 8px;
+ line-height: 1.7;
+}
+
+.tag {
+ flex: none;
+ padding: 0 6px;
+ border-radius: 3px;
+ font-size: 12px;
+ background-color: rgba(240, 160, 32, 0.16);
+ color: v-bind("theme.warningColorPressed");
+}
+
+.actions {
+ display: flex;
+ align-items: center;
+ gap: 12px;
}
diff --git a/apps/web/src/oj/problem/components/MobileActionBar.vue b/apps/web/src/oj/problem/components/MobileActionBar.vue
index 9b94041..2cceb08 100644
--- a/apps/web/src/oj/problem/components/MobileActionBar.vue
+++ b/apps/web/src/oj/problem/components/MobileActionBar.vue
@@ -31,6 +31,8 @@ const canRunSamples = computed(
+import { useThemeVars } from "naive-ui"
import { useCodeStore } from "oj/store/code"
import { findChinesePunctuation } from "oj/problem/utils/chinesePunctuation"
import {
@@ -23,23 +24,28 @@ const props = defineProps<{
}>()
const codeStore = useCodeStore()
+const theme = useThemeVars()
const explanation = computed(() => explainPythonCompileError(props.errInfo))
/** 判题机的临时目录名(`/judger/run/<32 位随机串>/`)对学生没有意义,只剩文件名 */
const rawError = computed(() => props.errInfo.replace(/\/judger\/run\/[^/"]+\//g, ""))
-/** 出错那一行拆成三段,中间那段是 `^` 标的地方 */
-const sourceParts = computed(() => {
+/**
+ * 报错只点名第一处。别的行也有中文标点的话,一句话带过(设计稿「语法没过」:
+ * 「第 4 行也有一个中文冒号,编辑器里都标出来了」)。原来这里还摆一段出错那行的代码摘录,
+ * 编辑器里已经标着红,设计稿里去掉了
+ */
+const otherPunctuationLines = computed(() => {
const ex = explanation.value
- if (!ex?.sourceLine) return null
- const { sourceLine: text, caret } = ex
- if (!caret) return { before: text, marked: "", after: "" }
- return {
- before: text.slice(0, caret.from),
- marked: text.slice(caret.from, caret.to),
- after: text.slice(caret.to),
+ if (!ex?.punctuation) return []
+ const code = codeStore.code.value
+ const lines = new Set()
+ for (const fix of findChinesePunctuation(code)) {
+ lines.add(code.slice(0, fix.from).split("\n").length)
}
+ lines.delete(ex.line ?? -1)
+ return [...lines].sort((a, b) => a - b)
})
// 数的是编辑器里**现在**的代码:学生可能已经自己改掉几处了
@@ -72,68 +78,63 @@ onUnmounted(clearErrorMark)
-
-
-
-
- 第 {{ explanation.line }} 行:{{ explanation.message }}
-
- {{ sourceParts.before
- }}{{ sourceParts.marked }}{{ sourceParts.after }}
-
-
- 把中文标点都换成英文({{ punctuationFixCount }} 处)
-
-
- 换好了 {{ fixedCount }} 处,再提交一次试试。
-
-
-
-
- {{ rawError }}
-
-
-
-
-
- 请仔细检查,看看代码的格式是不是写错了!
- {{ rawError }}
-
-
-
+
+
+
+ 第 {{ explanation.line }} 行:{{ explanation.message }}
+
+
+ 第 {{ otherPunctuationLines.join("、") }} 行也有中文标点,编辑器里都标出来了。
+
+
+
+ 把中文标点都换成英文({{ punctuationFixCount }} 处)
+
+
+ 换好了 {{ fixedCount }} 处,再提交一次试试。
+
+
+
+
+ {{ rawError }}
+
+
+
+
+
+ 请仔细检查,看看代码的格式是不是写错了!
+ {{ rawError }}
+
+
diff --git a/apps/web/src/oj/problem/components/ResultPane.vue b/apps/web/src/oj/problem/components/ResultPane.vue
index cef45ef..14feefd 100644
--- a/apps/web/src/oj/problem/components/ResultPane.vue
+++ b/apps/web/src/oj/problem/components/ResultPane.vue
@@ -83,6 +83,9 @@ const canTrial = computed(() => {
>
{{ segment.label }} · {{ segment.time }}
+ 自己编数据试试,这里不判对错
@@ -135,6 +138,13 @@ const canTrial = computed(() => {
cursor: pointer;
}
+.segment-note {
+ margin-left: auto;
+ align-self: center;
+ font-size: 13px;
+ color: v-bind("theme.textColor3");
+}
+
.segment.active {
background-color: v-bind("theme.textColor1");
color: v-bind("theme.cardColor");
diff --git a/apps/web/src/oj/problem/components/SampleRunResult.vue b/apps/web/src/oj/problem/components/SampleRunResult.vue
index f542d0e..53c2948 100644
--- a/apps/web/src/oj/problem/components/SampleRunResult.vue
+++ b/apps/web/src/oj/problem/components/SampleRunResult.vue
@@ -1,18 +1,17 @@