|
@@ -6,54 +6,49 @@
|
|
|
v-model.trim="searchModel.name"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="准考证号">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.examNo"
|
|
|
+ v-model.trim="searchModel.examNumber"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="密号">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.secretNo"
|
|
|
+ v-model.trim="searchModel.secretNumber"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="学号">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.studentNo"
|
|
|
+ v-model.trim="searchModel.studentCode"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="科目">
|
|
|
- <select-subject v-model="searchModel.subject"></select-subject>
|
|
|
+ <select-subject v-model="searchModel.subjectCode"></select-subject>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="层次">
|
|
|
<el-select
|
|
|
- v-model="searchModel.level"
|
|
|
- placeholder="请选择"
|
|
|
+ v-model="searchModel.subjectLevel"
|
|
|
+ placeholder="不限"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
|
>
|
|
|
<el-option label="请选择" value="" />
|
|
|
- <el-option label="不限" value="不限" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="专业类型">
|
|
|
<el-select
|
|
|
- v-model="searchModel.majorType"
|
|
|
+ v-model="searchModel.subjectCategory"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -64,68 +59,70 @@
|
|
|
<el-form-item label="状态">
|
|
|
<el-space>
|
|
|
<el-select
|
|
|
- v-model="searchModel.status"
|
|
|
- placeholder="请选择"
|
|
|
+ v-model="searchModel.upload"
|
|
|
+ placeholder="不限"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
|
>
|
|
|
- <el-option label="不限" value="" />
|
|
|
+ <el-option label="已上传" :value="true" />
|
|
|
+ <el-option label="未上传" :value="false" />
|
|
|
</el-select>
|
|
|
- <el-select placeholder="不限" clearable style="width: 120px">
|
|
|
- <el-option label="不限" value="" />
|
|
|
+ <el-select
|
|
|
+ v-model="searchModel.absent"
|
|
|
+ placeholder="不限"
|
|
|
+ clearable
|
|
|
+ style="width: 120px"
|
|
|
+ >
|
|
|
+ <el-option label="缺考" :value="true" />
|
|
|
+ <el-option label="正常" :value="false" />
|
|
|
</el-select>
|
|
|
- <el-select placeholder="不限" clearable style="width: 120px">
|
|
|
- <el-option label="不限" value="" />
|
|
|
+ <el-select
|
|
|
+ v-model="searchModel.breach"
|
|
|
+ placeholder="不限"
|
|
|
+ clearable
|
|
|
+ style="width: 120px"
|
|
|
+ >
|
|
|
+ <el-option label="违纪" :value="true" />
|
|
|
+ <el-option label="正常" :value="false" />
|
|
|
</el-select>
|
|
|
- <el-select placeholder="不限" clearable style="width: 120px">
|
|
|
- <el-option label="不限" value="" />
|
|
|
+ <el-select
|
|
|
+ v-model="searchModel.manualAbsent"
|
|
|
+ placeholder="不限"
|
|
|
+ clearable
|
|
|
+ style="width: 140px"
|
|
|
+ >
|
|
|
+ <el-option label="人工指定缺考" :value="true" />
|
|
|
+ <el-option label="正常" :value="false" />
|
|
|
</el-select>
|
|
|
</el-space>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="签到表编号">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.signBookNo"
|
|
|
+ v-model.trim="searchModel.packageCode"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="批次编号">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.batchNo"
|
|
|
+ v-model.trim="searchModel.batchCode"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="学院">
|
|
|
- <el-select
|
|
|
- v-model="searchModel.college"
|
|
|
- placeholder="请选择"
|
|
|
- clearable
|
|
|
- style="width: 120px"
|
|
|
- >
|
|
|
- <el-option label="请选择" value="" />
|
|
|
- </el-select>
|
|
|
+ <select-college v-model="searchModel.college"> </select-college>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="班级">
|
|
|
- <el-select
|
|
|
- v-model="searchModel.className"
|
|
|
- placeholder="请选择"
|
|
|
- clearable
|
|
|
- style="width: 120px"
|
|
|
- >
|
|
|
- <el-option label="请选择" value="" />
|
|
|
- </el-select>
|
|
|
+ <select-class v-model="searchModel.className"> </select-class>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="任课老师">
|
|
|
<el-input
|
|
|
v-model.trim="searchModel.teacher"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
@@ -134,7 +131,6 @@
|
|
|
v-model.trim="searchModel.examSite"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
@@ -143,15 +139,14 @@
|
|
|
v-model.trim="searchModel.examRoom"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
>
|
|
|
</el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="扫描张数">
|
|
|
<el-input-number
|
|
|
- v-model.number="searchModel.scanPages"
|
|
|
- :min="1"
|
|
|
- :max="20"
|
|
|
+ v-model.number="searchModel.sheetCount"
|
|
|
+ :min="0"
|
|
|
+ :max="30"
|
|
|
:step="1"
|
|
|
:precision="0"
|
|
|
:controls="false"
|
|
@@ -169,17 +164,17 @@
|
|
|
<el-button type="success" @click="onImport">导入</el-button>
|
|
|
<el-dropdown @command="onImportCommand">
|
|
|
<el-button type="primary">
|
|
|
- 导入
|
|
|
+ 导入名单
|
|
|
<el-icon class="el-icon--right"><ArrowDown /> </el-icon>
|
|
|
</el-button>
|
|
|
<template #dropdown>
|
|
|
<el-dropdown-menu>
|
|
|
- <el-dropdown-item command="breaking">违纪名单</el-dropdown-item>
|
|
|
- <el-dropdown-item command="miss">缺考名单</el-dropdown-item>
|
|
|
+ <el-dropdown-item command="breach">违纪名单</el-dropdown-item>
|
|
|
+ <el-dropdown-item command="absent">缺考名单</el-dropdown-item>
|
|
|
</el-dropdown-menu>
|
|
|
</template>
|
|
|
</el-dropdown>
|
|
|
- <el-button @click="exportData">导入名单</el-button>
|
|
|
+ <el-button @click="exportData">导出</el-button>
|
|
|
</el-space>
|
|
|
|
|
|
<table-field v-model="headFields" :fields="tableFields"></table-field>
|
|
@@ -195,14 +190,14 @@
|
|
|
>
|
|
|
<el-table-column type="index" label="序号" width="60" />
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('examNo')"
|
|
|
- prop="examNo"
|
|
|
+ v-if="checkFieldVisible('examNumber')"
|
|
|
+ prop="examNumber"
|
|
|
label="准考证号"
|
|
|
width="120"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('secretNo')"
|
|
|
- prop="secretNo"
|
|
|
+ v-if="checkFieldVisible('secretNumber')"
|
|
|
+ prop="secretNumber"
|
|
|
label="密号"
|
|
|
min-width="100"
|
|
|
/>
|
|
@@ -213,46 +208,48 @@
|
|
|
min-width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('studentNo')"
|
|
|
- prop="studentNo"
|
|
|
+ v-if="checkFieldVisible('studentCode')"
|
|
|
+ prop="studentCode"
|
|
|
label="学号"
|
|
|
width="120"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('subject')"
|
|
|
- prop="subject"
|
|
|
+ v-if="checkFieldVisible('subjectName')"
|
|
|
+ prop="subjectName"
|
|
|
label="科目"
|
|
|
min-width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('examType')"
|
|
|
- prop="examType"
|
|
|
+ v-if="checkFieldVisible('paperType')"
|
|
|
+ prop="paperType"
|
|
|
label="试卷类型"
|
|
|
width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('level')"
|
|
|
- prop="level"
|
|
|
+ v-if="checkFieldVisible('subjectLevel')"
|
|
|
+ prop="subjectLevel"
|
|
|
label="层次"
|
|
|
width="80"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('majorType')"
|
|
|
- prop="majorType"
|
|
|
+ v-if="checkFieldVisible('subjectCategory')"
|
|
|
+ prop="subjectCategory"
|
|
|
label="专业类型"
|
|
|
width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('scanRecognition')"
|
|
|
+ v-if="checkFieldVisible('upload')"
|
|
|
label="扫描识别"
|
|
|
width="100"
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
- <el-tag :type="scope.row.scanRecognition ? 'success' : 'danger'">
|
|
|
- {{ scope.row.scanRecognition ? '是' : '否' }}
|
|
|
+ <el-tag :type="scope.row.upload ? 'success' : 'danger'">
|
|
|
+ {{ scope.row.upload ? '是' : '否' }}
|
|
|
</el-tag>
|
|
|
<el-button
|
|
|
v-if="scope.row.sheetUrls.length > 0"
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
link
|
|
|
style="margin-left: 5px"
|
|
|
@click="onPreviewImg(scope.row)"
|
|
@@ -262,31 +259,31 @@
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('scanPages')"
|
|
|
- prop="scanPages"
|
|
|
+ v-if="checkFieldVisible('sheetCount')"
|
|
|
+ prop="sheetCount"
|
|
|
label="扫描张数"
|
|
|
width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('manualAssign')"
|
|
|
+ v-if="checkFieldVisible('manualAbsent')"
|
|
|
label="人工指定"
|
|
|
width="100"
|
|
|
>
|
|
|
<template #default="scope">
|
|
|
- <el-tag :type="scope.row.manualAssign ? 'success' : 'danger'">
|
|
|
- {{ scope.row.manualAssign ? '是' : '否' }}
|
|
|
+ <el-tag :type="scope.row.manualAbsent ? 'success' : 'danger'">
|
|
|
+ {{ scope.row.manualAbsent ? '是' : '否' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('batchNo')"
|
|
|
- prop="batchNo"
|
|
|
+ v-if="checkFieldVisible('batchCode')"
|
|
|
+ prop="batchCode"
|
|
|
label="批次编号"
|
|
|
width="100"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
- v-if="checkFieldVisible('signBookNo')"
|
|
|
- prop="signBookNo"
|
|
|
+ v-if="checkFieldVisible('packageCode')"
|
|
|
+ prop="packageCode"
|
|
|
label="签到表编号"
|
|
|
width="120"
|
|
|
/>
|
|
@@ -320,11 +317,19 @@
|
|
|
label="考场"
|
|
|
width="80"
|
|
|
/>
|
|
|
- <el-table-column label="操作" width="100" fixed="right">
|
|
|
+ <el-table-column label="操作" width="120" fixed="right">
|
|
|
<template #default="scope">
|
|
|
- <el-button size="small" link @click="onEdit(scope.row)">
|
|
|
+ <el-button
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ link
|
|
|
+ @click="onEdit(scope.row)"
|
|
|
+ >
|
|
|
编辑
|
|
|
</el-button>
|
|
|
+ <el-button size="small" type="danger" link @click="onDelete(row)"
|
|
|
+ >删除</el-button
|
|
|
+ >
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
@@ -347,17 +352,17 @@
|
|
|
|
|
|
<!-- 导入学生 -->
|
|
|
<ImportDialog
|
|
|
- ref="importDialogRef"
|
|
|
+ ref="importStudentDialogRef"
|
|
|
title="导入学生"
|
|
|
- upload-url="/api/admin/site/import"
|
|
|
+ :upload-url="importStudentUrl"
|
|
|
:format="['xls', 'xlsx']"
|
|
|
- :download-handle="downloadTemplate"
|
|
|
+ :download-handle="downloadStudentTemplate"
|
|
|
download-filename="学生导入模板.xlsx"
|
|
|
/>
|
|
|
|
|
|
<!-- 导入名单 -->
|
|
|
<ImportDialog
|
|
|
- ref="importUserDialogRef"
|
|
|
+ ref="importAbDialogRef"
|
|
|
:title="importConfig?.title"
|
|
|
:upload-url="importConfig?.url"
|
|
|
:format="importConfig?.format"
|
|
@@ -377,9 +382,14 @@
|
|
|
<script setup lang="ts">
|
|
|
import { reactive, ref, computed } from 'vue';
|
|
|
import { ArrowDown } from '@element-plus/icons-vue';
|
|
|
- import { getStudentList } from '@/api/student';
|
|
|
+ import { ElMessage } from 'element-plus';
|
|
|
+ import { getStudentList, deleteStudent } from '@/api/student';
|
|
|
import { StudentItem, StudentListFilter } from '@/api/types/student';
|
|
|
import useTable from '@/hooks/table';
|
|
|
+ import useLoading from '@/hooks/loading';
|
|
|
+ import { modalConfirm } from '@/utils/ui';
|
|
|
+ import { downloadExport } from '@/utils/download-export';
|
|
|
+ import { useAppStore } from '@/store';
|
|
|
|
|
|
import ModifyStudent from './ModifyStudent.vue';
|
|
|
|
|
@@ -387,23 +397,28 @@
|
|
|
name: 'StudentManage',
|
|
|
});
|
|
|
|
|
|
+ const appStore = useAppStore();
|
|
|
+
|
|
|
const searchModel = reactive<StudentListFilter>({
|
|
|
name: '',
|
|
|
- examNo: '',
|
|
|
- secretNo: '',
|
|
|
- studentNo: '',
|
|
|
- subject: null,
|
|
|
- level: '',
|
|
|
- majorType: '',
|
|
|
- status: '',
|
|
|
- batchNo: '',
|
|
|
- signBookNo: '',
|
|
|
+ examNumber: '',
|
|
|
+ secretNumber: '',
|
|
|
+ studentCode: '',
|
|
|
+ subjectCode: '',
|
|
|
+ subjectLevel: '',
|
|
|
+ subjectCategory: '',
|
|
|
+ upload: undefined,
|
|
|
+ absent: undefined,
|
|
|
+ manualAbsent: undefined,
|
|
|
+ breach: undefined,
|
|
|
+ batchCode: '',
|
|
|
+ packageCode: '',
|
|
|
college: '',
|
|
|
className: '',
|
|
|
teacher: '',
|
|
|
examSite: '',
|
|
|
examRoom: '',
|
|
|
- scanPages: undefined,
|
|
|
+ sheetCount: undefined,
|
|
|
});
|
|
|
|
|
|
const { dataList, pagination, loading, getList, toPage, pageSizeChange } =
|
|
@@ -411,19 +426,19 @@
|
|
|
|
|
|
// 表头配置
|
|
|
const tableFields = [
|
|
|
- { name: '准考证号', field: 'examNo' },
|
|
|
- { name: '密号', field: 'secretNo' },
|
|
|
+ { name: '准考证号', field: 'examNumber' },
|
|
|
+ { name: '密号', field: 'secretNumber' },
|
|
|
{ name: '姓名', field: 'name' },
|
|
|
- { name: '学号', field: 'studentNo' },
|
|
|
- { name: '科目', field: 'subject' },
|
|
|
- { name: '试卷类型', field: 'examType' },
|
|
|
- { name: '层次', field: 'level' },
|
|
|
- { name: '专业类型', field: 'majorType' },
|
|
|
- { name: '扫描识别', field: 'scanRecognition' },
|
|
|
- { name: '扫描张数', field: 'scanPages' },
|
|
|
- { name: '人工指定', field: 'manualAssign' },
|
|
|
- { name: '批次编号', field: 'batchNo' },
|
|
|
- { name: '签到表编号', field: 'signBookNo' },
|
|
|
+ { name: '学号', field: 'studentCode' },
|
|
|
+ { name: '科目', field: 'subjectName' },
|
|
|
+ { name: '试卷类型', field: 'paperType' },
|
|
|
+ { name: '层次', field: 'subjectLevel' },
|
|
|
+ { name: '专业类型', field: 'subjectCategory' },
|
|
|
+ { name: '扫描识别', field: 'upload' },
|
|
|
+ { name: '扫描张数', field: 'sheetCount' },
|
|
|
+ { name: '人工指定', field: 'manualAbsent' },
|
|
|
+ { name: '批次编号', field: 'batchCode' },
|
|
|
+ { name: '签到表编号', field: 'packageCode' },
|
|
|
{ name: '学院', field: 'college' },
|
|
|
{ name: '班级', field: 'className' },
|
|
|
{ name: '任课老师', field: 'teacher' },
|
|
@@ -449,6 +464,28 @@
|
|
|
modifyStudentRef.value?.open();
|
|
|
}
|
|
|
|
|
|
+ // 删除
|
|
|
+ const { loading: deleteLoading, setLoading: setDeleteLoading } = useLoading();
|
|
|
+ async function onDelete(row: StudentItem) {
|
|
|
+ if (deleteLoading.value) return;
|
|
|
+ const confirm = await modalConfirm(
|
|
|
+ `确定要删除分类"${row.name}"吗?`,
|
|
|
+ '删除确认'
|
|
|
+ ).catch(() => false);
|
|
|
+ if (!confirm) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ setDeleteLoading(true);
|
|
|
+ await deleteStudent(row.id);
|
|
|
+ ElMessage.success('删除成功');
|
|
|
+ getList();
|
|
|
+ } catch (error) {
|
|
|
+ console.log('删除失败:', error);
|
|
|
+ } finally {
|
|
|
+ setDeleteLoading(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 查看图片
|
|
|
const showPreview = ref(false);
|
|
|
const curStudentSheetUrls = ref<string[]>([]);
|
|
@@ -458,48 +495,63 @@
|
|
|
}
|
|
|
|
|
|
// 导入学生
|
|
|
- const importDialogRef = ref();
|
|
|
- function downloadTemplate() {
|
|
|
- // TODO: 实现下载模板功能
|
|
|
+ const importStudentDialogRef = ref();
|
|
|
+ const importStudentUrl = computed(() => {
|
|
|
+ return appStore.curExam?.type === 'SCAN_IMAGE'
|
|
|
+ ? '/api/admin/student/import'
|
|
|
+ : '/api/admin/student/uploadImport';
|
|
|
+ });
|
|
|
+ function downloadStudentTemplate() {
|
|
|
+ downloadExport(
|
|
|
+ appStore.curExam?.type === 'SCAN_IMAGE'
|
|
|
+ ? 'studentTemplate'
|
|
|
+ : 'mediaStudentTemplate'
|
|
|
+ );
|
|
|
}
|
|
|
function onImport() {
|
|
|
- importDialogRef.value?.open();
|
|
|
+ importStudentDialogRef.value?.open();
|
|
|
}
|
|
|
|
|
|
// 导入名单
|
|
|
const impoartConfigList = ref([
|
|
|
{
|
|
|
- code: 'breaking',
|
|
|
- title: '缺考名单',
|
|
|
- url: '/api/admin/subject/import/kgt',
|
|
|
+ code: 'absent',
|
|
|
+ title: '导入缺考名单',
|
|
|
+ url: '/api/admin/student/absentImport',
|
|
|
format: ['xls', 'xlsx'],
|
|
|
donloadFilename: '缺考名单导入模板.xlsx',
|
|
|
},
|
|
|
{
|
|
|
- code: 'miss',
|
|
|
- title: '违纪名单',
|
|
|
- url: '/api/admin/subject/import/kgt',
|
|
|
+ code: 'breach',
|
|
|
+ title: '导入违纪名单',
|
|
|
+ url: '/api/admin/student/breachImport',
|
|
|
format: ['xls', 'xlsx'],
|
|
|
donloadFilename: '违纪名单导入模板.xlsx',
|
|
|
},
|
|
|
]);
|
|
|
- const importUserDialogRef = ref();
|
|
|
+ const importAbDialogRef = ref();
|
|
|
const importData = reactive({
|
|
|
- importType: 'breaking',
|
|
|
+ importType: 'absent',
|
|
|
});
|
|
|
const importConfig = computed(() => {
|
|
|
return impoartConfigList.value.find(
|
|
|
(item) => item.code === importData.importType
|
|
|
);
|
|
|
});
|
|
|
+ function downloadTemplate() {
|
|
|
+ downloadExport(
|
|
|
+ importData.importType === 'absent'
|
|
|
+ ? 'absentStudentTemplate'
|
|
|
+ : 'breachStudentTemplate'
|
|
|
+ );
|
|
|
+ }
|
|
|
const onImportCommand = (command: string) => {
|
|
|
- console.log('导入命令:', command);
|
|
|
importData.importType = command;
|
|
|
- importUserDialogRef.value?.open();
|
|
|
+ importAbDialogRef.value?.open();
|
|
|
};
|
|
|
|
|
|
// 导出
|
|
|
function exportData() {
|
|
|
- // TODO: 实现导出功能
|
|
|
+ downloadExport('exportStudent', searchModel);
|
|
|
}
|
|
|
</script>
|