feat(admin): 作品管理新增「提交状态」筛选(已提交 / 未提交)

- 工具栏新增「提交状态」下拉(已提交/未提交,clearable),class 与文案均与「成绩总览」同款逐字对齐

- 判据抽为单一真相源 isWorkSubmitted = (row.files||[]).length > 0,同时供表格「未提交」文案 / 计数 / 筛选三处使用,杜绝列表与筛选打架

- filteredSubmissions 增加状态分支(先姓名后状态),分页与 total 自动联动

- 新增计数「共 N 人 · 已提交 X · 未提交 Y |当前筛选出 M 人」;批量下载按钮补 title 明示「下载全组、不受筛选影响」

- 线上验证:R87 已部署(入口 index-Dhsp29Gt.js,gzip_static 命中 CL=106660,旧入口 404)
This commit is contained in:
2026-10-09 10:40:55 +08:00
parent e7179bfe54
commit 27665c2186

View File

@@ -652,11 +652,23 @@
<el-option label="教师组" value="jiaoshi" />
</el-select>
<el-input v-model="submissionSearch" placeholder="搜索选手姓名" clearable size="small" class="search-input" @input="onSubmissionFilterChange" />
<!-- R87:提交状态筛选。判据与表格内「未提交」文案同源(row.files.length === 0);
选项文案与「成绩管理 · 成绩总览」的提交状态下拉逐字对齐。 -->
<el-select v-model="submissionStatusFilter" placeholder="提交状态" clearable size="small" class="filter-select" @change="onSubmissionFilterChange">
<el-option label="已提交" value="true" />
<el-option label="未提交" value="false" />
</el-select>
<!-- R80:组别只剩本科/教师(两组都需下载作品)⇒ 原「仅 benke/jiaoshi 显示」判据已恒真,移除死判据 -->
<!-- R87:本按钮下载「该组全部作品」(后端全组 ZIP),⚠️ 不受上方筛选影响 ⇒ 以 title 明示口径 -->
<el-button
type="success"
v-guard="() => batchDownloadWorks()"
title="下载该组全部作品(不受上方筛选影响)"
>批量下载作品</el-button>
<span class="work-summary" v-if="submissions.length">
共 {{ submissionStatusCount.total }} 人 · 已提交 {{ submissionStatusCount.submitted }} · 未提交 {{ submissionStatusCount.unsubmitted }}
<template v-if="submissionStatusFilter !== ''">|当前筛选出 {{ filteredSubmissions.length }} 人</template>
</span>
</div>
<el-table :data="pagedSubmissions" stripe v-loading="submissionsLoading" class="admin-table">
<el-table-column prop="name" label="选手姓名" width="120" />
@@ -2851,6 +2863,16 @@ const submissionGroup = ref('benke')
const submissionsPage = ref(1)
const submissionsPageSize = ref(10)
const submissionSearch = ref('')
const submissionStatusFilter = ref('')
// 作品管理「已提交」判据的单一真相源 —— 与表格内「未提交」文案(row.files.length === 0)同源。
const isWorkSubmitted = row => (row.files || []).length > 0
const submissionStatusCount = computed(() => {
const total = submissions.value.length
const submitted = submissions.value.filter(isWorkSubmitted).length
return { total, submitted, unsubmitted: total - submitted }
})
const filteredSubmissions = computed(() => {
let list = submissions.value
@@ -2858,6 +2880,10 @@ const filteredSubmissions = computed(() => {
const s = submissionSearch.value.trim().toLowerCase()
list = list.filter(item => (item.name || '').toLowerCase().includes(s))
}
if (submissionStatusFilter.value !== '') {
const wantSubmitted = submissionStatusFilter.value === 'true'
list = list.filter(item => isWorkSubmitted(item) === wantSubmitted)
}
return list
})
@@ -3808,6 +3834,7 @@ onMounted(() => {
.score-input { width: 110px; }
.preview-frame { width: 100%; height: 70vh; border: 0; background: #fff; }
.preview-file-name { color: #303133; font-weight: 600; margin-bottom: 8px; }
.work-summary { color: #606266; font-size: 13px; margin-left: 8px; }
/* ==================== 统计卡片 ==================== */
.stats-row { margin-bottom: 20px; }