评阅与成绩:老师看代码、运行学生程序、打分、写评语;成绩表与导出
- 评阅页:全班学生列表(提交状态、得分、是否已评阅);选中学生的代码(只读)、自动评分结果、 规范提示(代码里用到的默认名字控件、注释行数)、老师评分项打分和评语,"保存并看下一个" - "运行他的程序":新标签页里打开学生的提交,可以操作实训台,改动不保存 - 学生能看到老师的各项得分和评语;作业列表显示总分 - 班级管理页"成绩"标签页:学生 × 作业的总分,点分数进入评阅;单个作业和全班成绩导出 CSV - 老师增删评分项后,已打的分按新的评分项对齐 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e6b0d5cb2
commit
89e9956a22
20 files changed
+999
-127
No files matched your search
@@ -1,13 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
// 一次提交的自动评分结果:每项通过与否、得分和不通过的原因;老师评分项只列出名称和分值。
|
||||
// 一次提交的评分结果:自动评分每项通过与否、得分和不通过的原因;
|
||||
// 老师评分项:老师已评阅时显示各项得分和评语,还没评阅时只列出名称和分值。
|
||||
import { computed } from 'vue'
|
||||
import { NSpin } from 'naive-ui'
|
||||
import type { Assignment, Submission } from '@iot/shared'
|
||||
import type { Assignment, Review, Submission } from '@iot/shared'
|
||||
|
||||
const props = defineProps<{ assignment: Assignment; submission: Submission }>()
|
||||
const props = withDefaults(defineProps<{ assignment: Assignment; submission: Submission; review?: Review | null; showManual?: boolean }>(), {
|
||||
review: null,
|
||||
showManual: true,
|
||||
})
|
||||
|
||||
const autoTotal = computed(() => props.assignment.scoring.auto.reduce((a, b) => a + b, 0))
|
||||
const manual = computed(() => props.assignment.scoring.manual)
|
||||
const manualTotal = computed(() => manual.value.reduce((a, m) => a + m.points, 0))
|
||||
const manualScore = computed(() => props.review?.scores.reduce<number>((a, s) => a + (s ?? 0), 0) ?? 0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,9 +40,22 @@ const manual = computed(() => props.assignment.scoring.manual)
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<div v-if="manual.length" class="manual">
|
||||
由老师评分:<span v-for="m in manual" :key="m.title">{{ m.title }}({{ m.points }} 分)</span>
|
||||
</div>
|
||||
<template v-if="showManual && manual.length">
|
||||
<div v-if="review" class="reviewed">
|
||||
<div class="summary">
|
||||
老师评分 <b>{{ manualScore }}</b> / {{ manualTotal }} 分
|
||||
</div>
|
||||
<ul class="items">
|
||||
<li v-for="(m, i) in manual" :key="i">
|
||||
<span class="title">{{ m.title }}<span class="points">{{ review.scores[i] ?? '未打分' }} / {{ m.points }} 分</span></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="review.comment" class="comment">老师评语:{{ review.comment }}</div>
|
||||
</div>
|
||||
<div v-else class="manual">
|
||||
由老师评分:<span v-for="m in manual" :key="m.title">{{ m.title }}({{ m.points }} 分)</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -99,6 +118,21 @@ const manual = computed(() => props.assignment.scoring.manual)
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.reviewed {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.comment {
|
||||
padding: 8px 10px;
|
||||
background: #f9fafb;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.manual {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user