|
@@ -6,7 +6,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="选做科目">
|
|
|
<el-select
|
|
|
- v-model="searchModel.isOptionalException"
|
|
|
+ v-model="searchModel.selective"
|
|
|
placeholder="不限"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -17,7 +17,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="状态">
|
|
|
<el-select
|
|
|
- v-model="searchModel.isReviewed"
|
|
|
+ v-model="searchModel.inspected"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -27,19 +27,13 @@
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="学院">
|
|
|
- <el-select
|
|
|
- v-model="searchModel.academyId"
|
|
|
- placeholder="请选择"
|
|
|
- clearable
|
|
|
- style="width: 120px"
|
|
|
- >
|
|
|
- <el-option label="请选11择" :value="11" />
|
|
|
- </el-select>
|
|
|
+ <select-option v-model="searchModel.college" type="college">
|
|
|
+ </select-option>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="试卷总分">
|
|
|
<el-space>
|
|
|
<el-input-number
|
|
|
- v-model="searchModel.totalStartScore"
|
|
|
+ v-model="searchModel.startScore"
|
|
|
placeholder="低分"
|
|
|
:min="0"
|
|
|
:max="999"
|
|
@@ -51,7 +45,7 @@
|
|
|
/>
|
|
|
<span>到</span>
|
|
|
<el-input-number
|
|
|
- v-model="searchModel.totalEndScore"
|
|
|
+ v-model="searchModel.endScore"
|
|
|
placeholder="高分"
|
|
|
:min="0"
|
|
|
:max="999"
|
|
@@ -65,7 +59,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="选做题">
|
|
|
<el-select
|
|
|
- v-model="searchModel.optionalExceptionType"
|
|
|
+ v-model="searchModel.selectiveStatus"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -80,17 +74,22 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="复核次数">
|
|
|
<el-select
|
|
|
- v-model="searchModel.reviewedTimes"
|
|
|
+ v-model="searchModel.inspectRound"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
|
>
|
|
|
- <el-option label="1" :value="1" />
|
|
|
+ <el-option
|
|
|
+ v-for="item in reviewRoundList"
|
|
|
+ :key="item"
|
|
|
+ :label="item"
|
|
|
+ :value="item"
|
|
|
+ />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="复核人">
|
|
|
<el-input
|
|
|
- v-model.trim="searchModel.reviewer"
|
|
|
+ v-model.trim="searchModel.inspectorName"
|
|
|
placeholder=""
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -98,7 +97,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="大题">
|
|
|
<el-select
|
|
|
- v-model="searchModel.bigQuestionNo"
|
|
|
+ v-model="searchModel.mainNumber"
|
|
|
placeholder="请选择"
|
|
|
clearable
|
|
|
style="width: 120px"
|
|
@@ -109,7 +108,7 @@
|
|
|
<el-form-item label="大题得分">
|
|
|
<el-space>
|
|
|
<el-input-number
|
|
|
- v-model="searchModel.bigQuestionStartScore"
|
|
|
+ v-model="searchModel.mainStartScore"
|
|
|
placeholder="低分"
|
|
|
:min="0"
|
|
|
:max="999"
|
|
@@ -121,7 +120,7 @@
|
|
|
/>
|
|
|
<span>到</span>
|
|
|
<el-input-number
|
|
|
- v-model="searchModel.bigQuestionEndScore"
|
|
|
+ v-model="searchModel.mainEndScore"
|
|
|
placeholder="高分"
|
|
|
:min="0"
|
|
|
:max="999"
|
|
@@ -135,7 +134,7 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item label="小题得分">
|
|
|
<el-input-number
|
|
|
- v-model="searchModel.smallQuestionScore"
|
|
|
+ v-model="searchModel.questionScore"
|
|
|
placeholder=""
|
|
|
:min="0"
|
|
|
:max="999"
|
|
@@ -159,10 +158,11 @@
|
|
|
|
|
|
<div class="part-action">
|
|
|
<el-space wrap>
|
|
|
- <el-button type="primary" @click="toPage(1)">查询</el-button>
|
|
|
+ <el-button type="primary" @click="search">查询</el-button>
|
|
|
<el-button @click="onBatchReview"
|
|
|
>批量复核({{ pagination.total }})</el-button
|
|
|
>
|
|
|
+ <el-button @click="onRestartReview">再次复核</el-button>
|
|
|
<el-button @click="onBatchCancelReview">取消复核</el-button>
|
|
|
<el-button @click="onImport">导入</el-button>
|
|
|
<el-dropdown @command="onExportCommand">
|
|
@@ -172,13 +172,15 @@
|
|
|
</el-button>
|
|
|
<template #dropdown>
|
|
|
<el-dropdown-menu>
|
|
|
- <el-dropdown-item command="list">复核列表</el-dropdown-item>
|
|
|
- <el-dropdown-item command="gzl">工作量</el-dropdown-item>
|
|
|
+ <el-dropdown-item command="exportFullReviewList"
|
|
|
+ >复核列表</el-dropdown-item
|
|
|
+ >
|
|
|
+ <el-dropdown-item command="exportReviewWorkload"
|
|
|
+ >工作量</el-dropdown-item
|
|
|
+ >
|
|
|
</el-dropdown-menu>
|
|
|
</template>
|
|
|
</el-dropdown>
|
|
|
- <el-button @click="onExportSign">导出标记卷</el-button>
|
|
|
- <el-button @click="onExportLog">错误日志</el-button>
|
|
|
</el-space>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -195,7 +197,7 @@
|
|
|
>
|
|
|
<el-table-column type="selection" width="55" />
|
|
|
<el-table-column
|
|
|
- prop="courseName"
|
|
|
+ prop="subjectName"
|
|
|
label="科目"
|
|
|
min-width="200"
|
|
|
sortable
|
|
@@ -203,20 +205,28 @@
|
|
|
<el-table-column prop="secretNumber" label="密号" width="120" />
|
|
|
<el-table-column label="选做异常" width="100">
|
|
|
<template #default="scope">
|
|
|
- <el-tag :type="scope.row.isOptionalException ? 'warning' : 'success'">
|
|
|
- {{ scope.row.isOptionalException ? '是' : '否' }}
|
|
|
+ <el-tag :type="scope.row.selectiveError ? 'warning' : 'success'">
|
|
|
+ {{ scope.row.selectiveError || '否' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="objectiveScore" label="客观分" width="100" />
|
|
|
- <el-table-column prop="subjectiveScore" label="主观分" width="100" />
|
|
|
+ <el-table-column prop="objectiveScoreString" label="客观分" width="100" />
|
|
|
+ <el-table-column
|
|
|
+ prop="subjectiveScoreString"
|
|
|
+ label="主观分"
|
|
|
+ width="100"
|
|
|
+ />
|
|
|
<el-table-column
|
|
|
prop="totalScore"
|
|
|
label="试卷总分"
|
|
|
width="110"
|
|
|
sortable
|
|
|
/>
|
|
|
- <el-table-column prop="scoreDetail" label="得分明细" min-width="200" />
|
|
|
+ <el-table-column
|
|
|
+ prop="subjectiveScoreList"
|
|
|
+ label="得分明细"
|
|
|
+ min-width="200"
|
|
|
+ />
|
|
|
<el-table-column label="操作" width="100" fixed="right">
|
|
|
<template #default="scope">
|
|
|
<el-button size="small" link @click="onTrackView(scope.row)">
|
|
@@ -230,14 +240,48 @@
|
|
|
</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <!-- TODO:复核人,复核时间 sortable -->
|
|
|
- <el-table-column prop="reviewer" label="复核人" width="120" sortable />
|
|
|
- <el-table-column
|
|
|
- prop="reviewTime"
|
|
|
- label="复核时间"
|
|
|
- width="180"
|
|
|
- sortable
|
|
|
- />
|
|
|
+ <template v-for="item in reviewRoundList" :key="item">
|
|
|
+ <el-table-column
|
|
|
+ :prop="`inspectHistoryMap.additionalProperties${item}.inspectorName`"
|
|
|
+ label="复核人"
|
|
|
+ width="120"
|
|
|
+ sortable
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ <span
|
|
|
+ v-if="
|
|
|
+ scope.row.inspectHistoryMap &&
|
|
|
+ scope.row.inspectHistoryMap[`additionalProperties${item}`]
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ scope.row.inspectHistoryMap?.[`additionalProperties${item}`]
|
|
|
+ .inspectorName
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ :prop="`inspectHistoryMap.additionalProperties${item}.inspectTime`"
|
|
|
+ label="复核时间"
|
|
|
+ width="180"
|
|
|
+ sortable
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ <span
|
|
|
+ v-if="
|
|
|
+ scope.row.inspectHistoryMap &&
|
|
|
+ scope.row.inspectHistoryMap[`additionalProperties${item}`]
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{
|
|
|
+ scope.row.inspectHistoryMap?.[`additionalProperties${item}`]
|
|
|
+ .inspectTime
|
|
|
+ }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </template>
|
|
|
</el-table>
|
|
|
<el-pagination
|
|
|
v-model:current-page="pagination.pageNumber"
|
|
@@ -248,17 +292,39 @@
|
|
|
@current-change="toPage"
|
|
|
/>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 导入 -->
|
|
|
+ <ImportDialog
|
|
|
+ ref="importDialogRef"
|
|
|
+ title="导入数据"
|
|
|
+ upload-url="/api/admin/user/class/import"
|
|
|
+ :format="['xls', 'xlsx']"
|
|
|
+ :download-handle="() => downloadExport('reviewImportTemplate')"
|
|
|
+ download-filename="导入模板.xlsx"
|
|
|
+ />
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { reactive } from 'vue';
|
|
|
+ import { reactive, ref, computed } from 'vue';
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
import { ArrowDown } from '@element-plus/icons-vue';
|
|
|
- import { getFullReviewList } from '@/api/review';
|
|
|
- import { FullReviewItem, FullReviewListFilter } from '@/api/types/review';
|
|
|
- import useTable from '@/hooks/table';
|
|
|
-
|
|
|
+ import {
|
|
|
+ getFullReviewList,
|
|
|
+ cancelReview,
|
|
|
+ checkReReview,
|
|
|
+ reReview,
|
|
|
+ getSubjectStatusInfo,
|
|
|
+ getReviewRoundList,
|
|
|
+ } from '@/api/review';
|
|
|
import { OPTIONAL_EXCEPTION_TYPE } from '@/constants/enumerate';
|
|
|
+ import {
|
|
|
+ FullReviewItem,
|
|
|
+ FullReviewListFilter,
|
|
|
+ SubjectStatusInfo,
|
|
|
+ } from '@/api/types/review';
|
|
|
+ import useTable from '@/hooks/table';
|
|
|
+ import { modalConfirm } from '@/utils/ui';
|
|
|
+ import { downloadExport } from '@/utils/download-export';
|
|
|
|
|
|
defineOptions({
|
|
|
name: 'AllReview',
|
|
@@ -266,18 +332,18 @@
|
|
|
|
|
|
const searchModel = reactive<FullReviewListFilter>({
|
|
|
subjectCode: null,
|
|
|
- isOptionalException: undefined,
|
|
|
- isReviewed: undefined,
|
|
|
- academyId: undefined,
|
|
|
- totalStartScore: undefined,
|
|
|
- totalEndScore: undefined,
|
|
|
- optionalExceptionType: undefined,
|
|
|
- reviewedTimes: undefined,
|
|
|
- reviewer: undefined,
|
|
|
- bigQuestionNo: undefined,
|
|
|
- bigQuestionStartScore: undefined,
|
|
|
- bigQuestionEndScore: undefined,
|
|
|
- smallQuestionScore: undefined,
|
|
|
+ selective: undefined,
|
|
|
+ inspected: undefined,
|
|
|
+ college: undefined,
|
|
|
+ startScore: undefined,
|
|
|
+ endScore: undefined,
|
|
|
+ selectiveStatus: undefined,
|
|
|
+ inspectRound: undefined,
|
|
|
+ inspectorName: undefined,
|
|
|
+ mainNumber: undefined,
|
|
|
+ mainStartScore: undefined,
|
|
|
+ mainEndScore: undefined,
|
|
|
+ questionScore: undefined,
|
|
|
secretNumber: undefined,
|
|
|
});
|
|
|
|
|
@@ -287,11 +353,43 @@
|
|
|
loading,
|
|
|
selectedRows,
|
|
|
toPage,
|
|
|
+ getList,
|
|
|
pageSizeChange,
|
|
|
handleSelectionChange,
|
|
|
handleSortChange,
|
|
|
} = useTable<FullReviewItem>(getFullReviewList, searchModel, false);
|
|
|
|
|
|
+ async function search() {
|
|
|
+ await toPage(1);
|
|
|
+ await updateSubjectInfo();
|
|
|
+ await updateReviewRoundList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算选中的学生ID列表
|
|
|
+ const selectedStudentIds = computed(() => {
|
|
|
+ return selectedRows.value.map((row) => row.id);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 科目状态信息
|
|
|
+ const curSubjectInfo = ref<SubjectStatusInfo>({
|
|
|
+ showNextInspect: false,
|
|
|
+ showNextInspectMsg: false,
|
|
|
+ });
|
|
|
+ async function updateSubjectInfo() {
|
|
|
+ const res = await getSubjectStatusInfo(searchModel.subjectCode);
|
|
|
+ curSubjectInfo.value = res || {
|
|
|
+ showNextInspect: false,
|
|
|
+ showNextInspectMsg: false,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复核轮数信息
|
|
|
+ const reviewRoundList = ref<number[]>([]);
|
|
|
+ async function updateReviewRoundList() {
|
|
|
+ const res = await getReviewRoundList(searchModel);
|
|
|
+ reviewRoundList.value = res || [];
|
|
|
+ }
|
|
|
+
|
|
|
// 批量复核
|
|
|
function onBatchReview() {
|
|
|
if (selectedRows.length === 0) {
|
|
@@ -301,14 +399,11 @@
|
|
|
// TODO: 批量复核
|
|
|
console.log('批量复核:', selectedRows);
|
|
|
}
|
|
|
- // 批量取消复核
|
|
|
- function onBatchCancelReview() {
|
|
|
- if (selectedRows.length === 0) {
|
|
|
- ElMessage.warning('请选择要取消复核的试卷');
|
|
|
- return;
|
|
|
- }
|
|
|
- // TODO: 批量取消复核
|
|
|
- console.log('批量复核:', selectedRows);
|
|
|
+
|
|
|
+ // 进入复核
|
|
|
+ function onReview(row: FullReviewItem) {
|
|
|
+ // TODO: 进入复核
|
|
|
+ console.log('复核:', row);
|
|
|
}
|
|
|
|
|
|
// 轨迹图
|
|
@@ -316,35 +411,87 @@
|
|
|
// TODO: 轨迹图
|
|
|
console.log('复核:', row);
|
|
|
}
|
|
|
- // 取消复核
|
|
|
- function onCancelReview(row: FullReviewItem) {
|
|
|
- // TODO: 取消复核
|
|
|
- console.log('复核:', row);
|
|
|
+
|
|
|
+ // 再次复核
|
|
|
+ async function onRestartReview() {
|
|
|
+ const checkRes = await checkReReview(searchModel.subjectCode);
|
|
|
+ // -1-不可以再次复核,并弹出消息,0-需要弹出消息以待确认,1-可以再次复核
|
|
|
+ if (checkRes.status === 1) {
|
|
|
+ await reReview(searchModel.subjectCode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (checkRes.status === 0) {
|
|
|
+ const confirm = await modalConfirm(checkRes.message, '提示 ').catch(
|
|
|
+ () => false
|
|
|
+ );
|
|
|
+ if (!confirm) return;
|
|
|
+
|
|
|
+ await reReview(searchModel.subjectCode);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (checkRes.status === -1) {
|
|
|
+ ElMessage.error(checkRes.message);
|
|
|
+ }
|
|
|
}
|
|
|
- // 进入复核
|
|
|
- function onReview(row: FullReviewItem) {
|
|
|
- // TODO: 进入复核
|
|
|
- console.log('复核:', row);
|
|
|
+
|
|
|
+ // 批量取消复核
|
|
|
+ async function onBatchCancelReview() {
|
|
|
+ if (selectedRows.length === 0) {
|
|
|
+ ElMessage.warning('请选择要取消复核的数据');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const confirm = await modalConfirm(
|
|
|
+ `确认取消复核选中的 ${selectedStudentIds.value.length}条数据吗?`,
|
|
|
+ '提示 '
|
|
|
+ ).catch(() => false);
|
|
|
+ if (!confirm) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await cancelReview(selectedStudentIds.value);
|
|
|
+ if (res.success) {
|
|
|
+ ElMessage.success('取消复核成功');
|
|
|
+ getList();
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.message);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('取消复核失败:', error);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取消复核
|
|
|
+ async function onCancelReview(row: FullReviewItem) {
|
|
|
+ const confirm = await modalConfirm(
|
|
|
+ `确认取消当前复核数据吗?`,
|
|
|
+ '提示 '
|
|
|
+ ).catch(() => false);
|
|
|
+ if (!confirm) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const res = await cancelReview([row.id]);
|
|
|
+ if (res.success) {
|
|
|
+ ElMessage.success('取消复核成功');
|
|
|
+ getList();
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.message);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('取消复核失败:', error);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 导入
|
|
|
+ const importDialogRef = ref();
|
|
|
function onImport() {
|
|
|
- // TODO: 实现导入功能
|
|
|
- console.log('导入');
|
|
|
+ importDialogRef.value?.open();
|
|
|
}
|
|
|
|
|
|
// 导出
|
|
|
- const onExportCommand = (command: string) => {
|
|
|
- console.log('导出命令:', command);
|
|
|
+ const onExportCommand = async (
|
|
|
+ command: 'exportReviewWorkload' | 'exportReviewStatList'
|
|
|
+ ) => {
|
|
|
+ await downloadExport(command, searchModel);
|
|
|
};
|
|
|
- // 导出标记卷
|
|
|
- function onExportSign() {
|
|
|
- // TODO: 导出标记卷
|
|
|
- console.log('导出标记卷');
|
|
|
- }
|
|
|
- // 导出错误日志
|
|
|
- function onExportLog() {
|
|
|
- // TODO: 导出错误日志
|
|
|
- console.log('导出错误日志');
|
|
|
- }
|
|
|
</script>
|