已修改完成,同时解决了“考生名单都是 0 人”的根因。
考生范围统一为“行政班关联学生 + 已选课学生”,并自动去重;考场分配、人数显示、冲突检测、学生考试安排均使用同一口径。[TeachingTaskRosterQuery.cs (line 40)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Teaching/TeachingTaskRosterQuery.cs:40) 新增考场签名单 Excel 导出接口。[ExamsController.cs (line 568)](E:/jiaowu/src/Jiaowu.Api/Controllers/ExamsController.cs:568) 考试计划页面新增“导出考场签名单”按钮。[ExamsView.vue (line 255)](E:/jiaowu/web/src/views/ExamsView.vue:255) 工作簿包含“考场汇总”以及每个考试场次独立的 A4 签到表,字段包括座位号、学号、姓名、行政班、考生签名和备注。[ExamSignInWorkbookExporter.cs (line 12)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Exams/ExamSignInWorkbookExporter.cs:12) 未分配考场或监考教师时,也能导出并显示“待分配”。
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { Plus, Promotion, Refresh, UserFilled, Setting } from '@element-plus/icons-vue'
|
||||
import { Download, Plus, Promotion, Refresh, UserFilled, Setting } from '@element-plus/icons-vue'
|
||||
import http, { apiErrorMessage } from '../api/http'
|
||||
import { downloadApiFile } from '../api/excel'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { academicTermLabel, academicTermOptionClass, defaultAcademicTermId } from '../utils/academicTerms'
|
||||
|
||||
@@ -20,6 +21,7 @@ const buildings = ref<any[]>([])
|
||||
const timeSlots = ref<any[]>([])
|
||||
const loading = ref(false)
|
||||
const arrangeLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const planDialog = ref(false)
|
||||
const sessionDialog = ref(false)
|
||||
const editingSession = ref<any | null>(null)
|
||||
@@ -250,6 +252,21 @@ async function publishPlan() {
|
||||
if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error))
|
||||
}
|
||||
}
|
||||
async function exportSignInSheets() {
|
||||
if (!selected.value) return
|
||||
exportLoading.value = true
|
||||
try {
|
||||
await downloadApiFile(
|
||||
`/exams/plans/${selected.value.id}/sign-in-sheets.xlsx`,
|
||||
`考场签名单-${selected.value.name}.xlsx`,
|
||||
)
|
||||
ElMessage.success('考场签名单已导出')
|
||||
} catch (error) {
|
||||
ElMessage.error(apiErrorMessage(error))
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
async function showRoster(row: any) {
|
||||
try {
|
||||
roster.value = (await http.get(`/exams/sessions/${row.id}/roster`)).data
|
||||
@@ -317,6 +334,12 @@ onMounted(async () => {
|
||||
<p>{{ selected.termName }} · {{ selected.sessions.length }} 个考试场次</p>
|
||||
</div>
|
||||
<div class="exam-actions">
|
||||
<el-button
|
||||
:icon="Download"
|
||||
:loading="exportLoading"
|
||||
:disabled="selected.sessions.length === 0"
|
||||
@click="exportSignInSheets"
|
||||
>导出考场签名单</el-button>
|
||||
<el-button v-if="selected.status === 'Draft'" @click="autoArrange('rooms')" :loading="arrangeLoading">一键分配考场</el-button>
|
||||
<el-button v-if="selected.status === 'Draft'" @click="autoArrange('invigilators')" :loading="arrangeLoading">一键分配监考</el-button>
|
||||
<el-button v-if="selected.status === 'Draft'" :icon="Setting" @click="autoArrange('all')" :loading="arrangeLoading">一键完成</el-button>
|
||||
|
||||
Reference in New Issue
Block a user