fix(提交列表/统计): 按方向键会顺手切掉「代码/流程图」、重判后右栏还是旧内容、没人交时统计说「全都做完了」
提交列表: - 焦点在单选框、下拉框上时方向键不再一边切控件一边换条;跨页没回来前不再连跳一整页 - 重判、重新评分之后右栏重新拉,不再命中旧缓存;同一条新旧请求不再互相覆盖 - 从「我的提交」点顶栏「提交」、浏览器后退时,地址里没有的筛选回到默认 - 找回点用户名开个人主页;「只看他 / 只看这题」学生也能用;重判不用等代码拉下来 - 手机上老师也能重判、能按语言筛,流程图行有手机排版;学生界面带着的班级筛选显示成能点掉的标签 - mermaid 画不出来时先说中文、原始报错折起来 统计页: - 没人交时说「这段时间没有人交」,不再说「全都做完了」;没填题号时各处统一叫「做对过题」 - 班级按 class_name 单独传;查询失败清掉旧数据并说清原因;标签跟着查出来的那一份走 - 「语法未过」的格子单独标「语」;正确率不算还在判的;截断提示说清哪些数字受影响 - 看板的请假隐藏只藏还没交过、没在举手的人,「恢复」只恢复这个班的 - 手机上筛选折行、上下排,不再挤出屏幕 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
26c8d65e89
commit
0bcc981e6f
15 files changed
+613
-197
No files matched your search
@@ -49,29 +49,41 @@ const evaluating = computed(
|
||||
props.row.status === FlowchartSubmissionStatus.PROCESSING,
|
||||
)
|
||||
|
||||
/**
|
||||
* 按 id 缓存,重新评分一开始(状态回到排队 / 评分中)就把这一条扔掉。原来按「id + 状态」
|
||||
* 缓存,评完 → 排队 → 评分中 → 评完 转一圈回来正好命中重评之前的旧评语
|
||||
*/
|
||||
let loadSeq = 0
|
||||
|
||||
async function load() {
|
||||
const row = props.row
|
||||
const seq = ++loadSeq
|
||||
failed.value = false
|
||||
bigOpen.value = false
|
||||
if (evaluating.value) cache.delete(row.id)
|
||||
if (!row.showLink) {
|
||||
detail.value = null
|
||||
return
|
||||
}
|
||||
const key = `${row.id}:${row.status}`
|
||||
let res = cache.get(key)
|
||||
if (!res) {
|
||||
let res = cache.get(row.id)
|
||||
if (!res || res.status !== row.status) {
|
||||
loading.value = true
|
||||
try {
|
||||
res = await getFlowchartSubmission(row.id)
|
||||
if (!evaluating.value) cache.set(key, res)
|
||||
if (seq !== loadSeq) return
|
||||
if (!evaluating.value && res.status === props.row.status) cache.set(row.id, res)
|
||||
} catch {
|
||||
if (props.row.id === row.id) failed.value = true
|
||||
if (seq !== loadSeq) return
|
||||
failed.value = true
|
||||
// 别让上一条的图留在那儿,旁边却写着「没拉下来」
|
||||
detail.value = null
|
||||
if (graph.value) graph.value.innerHTML = ""
|
||||
return
|
||||
} finally {
|
||||
if (props.row.id === row.id) loading.value = false
|
||||
if (seq === loadSeq) loading.value = false
|
||||
}
|
||||
}
|
||||
if (props.row.id !== row.id) return
|
||||
if (seq !== loadSeq) return
|
||||
detail.value = res
|
||||
await nextTick()
|
||||
await renderFlowchart(graph.value, res.mermaidCode)
|
||||
@@ -131,8 +143,14 @@ const canRetry = computed(
|
||||
<section class="pane" :class="{ narrow }">
|
||||
<div class="head">
|
||||
<div class="who">
|
||||
<UserName :username="row.username" />
|
||||
<button v-if="teacher" class="filter-pill" @click="emit('filterUser', row.username)">
|
||||
<a
|
||||
class="user-link"
|
||||
:href="`/user?name=${encodeURIComponent(row.username)}`"
|
||||
target="_blank"
|
||||
>
|
||||
<UserName :username="row.username" />
|
||||
</a>
|
||||
<button class="filter-pill" @click="emit('filterUser', row.username)">
|
||||
<Icon icon="ph:funnel-simple-bold" :width="11" />只看他
|
||||
</button>
|
||||
</div>
|
||||
@@ -141,11 +159,7 @@ const canRetry = computed(
|
||||
<span class="problem-id">{{ row.problemDisplayId }}</span>
|
||||
{{ row.problemTitle }}
|
||||
</a>
|
||||
<button
|
||||
v-if="teacher"
|
||||
class="filter-pill"
|
||||
@click="emit('filterProblem', row.problemDisplayId)"
|
||||
>
|
||||
<button class="filter-pill" @click="emit('filterProblem', row.problemDisplayId)">
|
||||
<Icon icon="ph:funnel-simple-bold" :width="11" />只看这题
|
||||
</button>
|
||||
<div class="spacer"></div>
|
||||
@@ -171,13 +185,22 @@ const canRetry = computed(
|
||||
|
||||
<div v-if="!row.showLink" class="locked">
|
||||
<Icon icon="ph:lock-simple" :width="30" class="lock-icon" />
|
||||
<span class="locked-title">别人画的流程图看不到</span>
|
||||
<!-- 列表项里没有 userId,分不出是别人的还是自己被题单挡住的,文案两种都说得通 -->
|
||||
<span class="locked-title">这张流程图看不到</span>
|
||||
<span class="muted">别人画的看不到;自己的在题单里做完这道题就能看到。</span>
|
||||
</div>
|
||||
<div v-else class="body">
|
||||
<div class="graph-box">
|
||||
<n-alert v-if="renderError" type="error" title="流程图画不出来">
|
||||
{{ renderError }}
|
||||
</n-alert>
|
||||
<!-- mermaid 的报错是英文,学生看自己的图也会碰到:先说中文,原文折起来 -->
|
||||
<div v-if="renderError" class="render-error">
|
||||
<b>这张流程图画不出来</b>
|
||||
<span class="muted">可能是画的时候有框没连上,或者文字里有特殊符号。</span>
|
||||
<n-collapse>
|
||||
<n-collapse-item title="原始报错" name="raw">
|
||||
<pre class="raw">{{ renderError }}</pre>
|
||||
</n-collapse-item>
|
||||
</n-collapse>
|
||||
</div>
|
||||
<div v-show="!renderError" ref="graph" class="graph"></div>
|
||||
<n-spin v-if="loading && !shown" size="small" />
|
||||
<span v-if="failed" class="muted"
|
||||
@@ -277,6 +300,29 @@ const canRetry = computed(
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
.user-link {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.render-error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 12px;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.raw {
|
||||
margin: 0;
|
||||
max-height: 140px;
|
||||
overflow: auto;
|
||||
font-size: 12px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.who {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user