feat: 同学作品和批改都能看全部班级,批改默认大图预览
Deploy / deploy (build, debian, 22) (push) Canceled after 0s

- 学生“同学作品”加“本班 / 全部班级”切换(peers?scope=all),作品标班级,仍是交过才开放、打分前匿名;
  服务端放开:交过某题后能看任何班同学在这道题上的提交
- 批改页班级下拉加“全部班级”:一道题全校作品按班级分组,没人交的班收起成一行;
  /review/class、/review/progress 不传 classname 就是全部班级
- 点开作品默认大图:作品墙收起,预览占满中间,打分 / 课上展示 / 提示词放右栏;
  Esc 返回作品墙,可切回小面板(记住选择);成绩册弹出的详情也用大图布局

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-27 09:22:41 +08:00
1 parent 8653d411a6
commit 75e20a3ae1
11 files changed
+265 -68

No files matched your search

+36 -10
View File
@@ -10,9 +10,15 @@
style="margin-top: 40px"
/>
<template v-else-if="data">
<p class="hint">
本班同学在这道题上最新的作品。打分之前不显示是谁做的,打完分才显示。
</p>
<n-flex justify="space-between" align="center" class="bar">
<span class="hint">
同学们在这道题上最新的作品。打分之前不显示是谁做的,打完分才显示。
</span>
<n-radio-group v-model:value="scope" size="small">
<n-radio-button value="class">本班</n-radio-button>
<n-radio-button value="all">全部班级</n-radio-button>
</n-radio-group>
</n-flex>
<n-empty v-if="!data.items.length" description="还没有同学交这道题" />
<div class="grid">
<div v-for="w in data.items" :key="w.id" class="work">
@@ -25,7 +31,10 @@
></iframe>
</button>
<div class="info">
<span :class="{ anon: !w.username }">{{ w.username ?? "匿名同学" }}</span>
<span :class="{ anon: !w.username }">
<span v-if="scope === 'all' && w.classname" class="cls">{{ w.classname }} 班</span>
{{ w.username ?? "匿名同学" }}
</span>
<span v-if="w.my_score" class="mine">我给了 {{ w.my_score }} 分</span>
</div>
<div v-if="!w.my_score" class="rates">
@@ -79,19 +88,26 @@ const data = ref<PeerWorks | null>(null)
const loading = ref(false)
const rating = ref<string | null>(null)
const large = ref<PeerWork | null>(null)
const scope = ref<"class" | "all">("class")
const docOf = (w: PeerWork) =>
buildPreviewDocument({ html: w.html, css: w.css, js: w.js, assetBaseUrl: props.assetBaseUrl })
watch(show, async (open) => {
if (!open || !props.taskId) return
let seq = 0
async function load() {
if (!props.taskId) return
const s = ++seq
loading.value = true
try {
data.value = await Review.peers(props.taskId)
const res = await Review.peers(props.taskId, scope.value)
if (s === seq) data.value = res
} finally {
loading.value = false
if (s === seq) loading.value = false
}
})
}
watch(show, (open) => open && load())
watch(scope, load)
async function rate(w: PeerWork, score: number) {
rating.value = w.id
@@ -107,12 +123,22 @@ async function rate(w: PeerWork, score: number) {
}
</script>
<style scoped>
.bar {
margin-bottom: 12px;
flex-wrap: nowrap !important;
}
.hint {
margin: 0 0 12px;
font-size: 13px;
color: var(--wp-muted);
}
.cls {
margin-right: 4px;
color: var(--wp-muted);
font-size: 12px;
}
.grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));