|
@@ -0,0 +1,425 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="part-box is-filter">
|
|
|
|
+ <el-form inline>
|
|
|
|
+ <el-form-item label="科目">
|
|
|
|
+ <select-subject v-model="searchModel.subject"></select-subject>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item label="分组">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model.trim="searchModel.group"
|
|
|
|
+ placeholder="请输入分组"
|
|
|
|
+ clearable
|
|
|
|
+ style="width: 120px"
|
|
|
|
+ >
|
|
|
|
+ </el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item label="登录名">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model.trim="searchModel.loginName"
|
|
|
|
+ placeholder="请输入登录名"
|
|
|
|
+ clearable
|
|
|
|
+ style="width: 150px"
|
|
|
|
+ >
|
|
|
|
+ </el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item label="姓名">
|
|
|
|
+ <el-input
|
|
|
|
+ v-model.trim="searchModel.name"
|
|
|
|
+ placeholder="请输入姓名"
|
|
|
|
+ clearable
|
|
|
|
+ style="width: 120px"
|
|
|
|
+ >
|
|
|
|
+ </el-input>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item>
|
|
|
|
+ <el-checkbox v-model.trim="searchModel.marked">已评卷 </el-checkbox>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ <el-form-item>
|
|
|
|
+ <el-space wrap>
|
|
|
|
+ <el-button type="primary" @click="toPage(1)">查询</el-button>
|
|
|
|
+ <el-button @click="onImport">导入</el-button>
|
|
|
|
+ <el-button @click="onBatchEnable(true)">启用</el-button>
|
|
|
|
+ <el-button @click="onBatchEnable(false)">禁用</el-button>
|
|
|
|
+ <el-button @click="onBatchRecycle">回收</el-button>
|
|
|
|
+ <el-button @click="onBatchSetTaskCount">设置评卷数</el-button>
|
|
|
|
+ <el-button @click="onBatchResetPassword">重置密码</el-button>
|
|
|
|
+ </el-space>
|
|
|
|
+ </el-form-item>
|
|
|
|
+ </el-form>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="part-box">
|
|
|
|
+ <el-table
|
|
|
|
+ class="page-table"
|
|
|
|
+ :data="dataList"
|
|
|
|
+ :loading="loading"
|
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
|
+ >
|
|
|
|
+ <el-table-column type="selection" width="55" />
|
|
|
|
+ <el-table-column property="loginName" label="登录名" width="120" />
|
|
|
|
+ <el-table-column property="name" label="姓名" width="100" />
|
|
|
|
+ <el-table-column property="subject" label="科目" width="120" />
|
|
|
|
+ <el-table-column property="group" label="分组" width="100" />
|
|
|
|
+ <el-table-column label="状态" width="100">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <el-tag :type="getStatusType(scope.row.status)" size="small">
|
|
|
|
+ {{ getStatusText(scope.row.status) }}
|
|
|
|
+ </el-tag>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column property="completedCount" label="已评数量" width="100">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <span>
|
|
|
|
+ {{ scope.row.completedCount }}
|
|
|
|
+ </span>
|
|
|
|
+ <el-button
|
|
|
|
+ type="danger"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onResetFinishCount(scope.row)"
|
|
|
|
+ >重置</el-button
|
|
|
|
+ >
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="正在评卷" width="100">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <el-tag :type="scope.row.marking ? 'success' : 'info'" size="small">
|
|
|
|
+ {{ scope.row.marking ? '是' : '否' }}
|
|
|
|
+ </el-tag>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column property="taskCount" label="任务数" width="100" />
|
|
|
|
+ <el-table-column
|
|
|
|
+ property="bindClass"
|
|
|
|
+ label="绑定班级"
|
|
|
|
+ min-width="150"
|
|
|
|
+ show-overflow-tooltip
|
|
|
|
+ >
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ {{ scope.row.bindClass || '-' }}
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="操作" width="300" fixed="right">
|
|
|
|
+ <template #default="scope">
|
|
|
|
+ <el-button
|
|
|
|
+ v-if="scope.row.status === 'disabled'"
|
|
|
|
+ type="success"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onEnable(scope.row, true)"
|
|
|
|
+ >
|
|
|
|
+ 启用
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ v-if="scope.row.status === 'enabled'"
|
|
|
|
+ type="warning"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onEnable(scope.row, false)"
|
|
|
|
+ >
|
|
|
|
+ 禁用
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ type="danger"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onUnbind(scope.row)"
|
|
|
|
+ >
|
|
|
|
+ 解绑
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ type="primary"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onSetTaskCount(scope.row)"
|
|
|
|
+ >
|
|
|
|
+ 设置评卷数
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ type="info"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onRecycle(scope.row)"
|
|
|
|
+ >
|
|
|
|
+ 回收
|
|
|
|
+ </el-button>
|
|
|
|
+ <el-button
|
|
|
|
+ type="warning"
|
|
|
|
+ size="small"
|
|
|
|
+ link
|
|
|
|
+ @click="onResetPassword(scope.row)"
|
|
|
|
+ >
|
|
|
|
+ 重置密码
|
|
|
|
+ </el-button>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+ <el-pagination
|
|
|
|
+ v-model:current-page="pagination.pageNumber"
|
|
|
|
+ v-model:page-size="pagination.pageSize"
|
|
|
|
+ :layout="pagination.layout"
|
|
|
|
+ :total="pagination.total"
|
|
|
|
+ @size-change="pageSizeChange"
|
|
|
|
+ @current-change="toPage"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <SetMarkCountDialog
|
|
|
|
+ ref="setMarkCountDialogRef"
|
|
|
|
+ :marker-ids="curMarkerIds"
|
|
|
|
+ @modified="getList"
|
|
|
|
+ />
|
|
|
|
+
|
|
|
|
+ <!-- 导入 -->
|
|
|
|
+ <ImportDialog
|
|
|
|
+ ref="importDialogRef"
|
|
|
|
+ title="导入数据"
|
|
|
|
+ upload-url="/api/admin/site/import"
|
|
|
|
+ :format="['xls', 'xlsx']"
|
|
|
|
+ :download-handle="downloadTemplate"
|
|
|
|
+ download-filename="评卷员导入模板.xlsx"
|
|
|
|
+ />
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+ import { reactive, ref, computed } from 'vue';
|
|
|
|
+ import { ElMessage } from 'element-plus';
|
|
|
|
+ import {
|
|
|
|
+ getMarkMarkerList,
|
|
|
|
+ markMarkerEnable,
|
|
|
|
+ markMarkerUnbind,
|
|
|
|
+ markMarkerTaskRecycle,
|
|
|
|
+ markMarkerResetPassword,
|
|
|
|
+ markMarkerResetFinishCount,
|
|
|
|
+ } from '@/api/mark';
|
|
|
|
+ import { MarkMarkerItem, MarkMarkerListFilter } from '@/api/types/mark';
|
|
|
|
+ import useTable from '@/hooks/table';
|
|
|
|
+ import { modalConfirm } from '@/utils/ui';
|
|
|
|
+
|
|
|
|
+ import SetMarkCountDialog from './components/SetMarkCountDialog.vue';
|
|
|
|
+
|
|
|
|
+ defineOptions({
|
|
|
|
+ name: 'MarkerManage',
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const searchModel = reactive<MarkMarkerListFilter>({
|
|
|
|
+ subject: null,
|
|
|
|
+ group: '',
|
|
|
|
+ loginName: '',
|
|
|
|
+ name: '',
|
|
|
|
+ marked: false,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const setMarkCountDialogRef = ref<InstanceType<typeof SetMarkCountDialog>>();
|
|
|
|
+ const curMarkerIds = ref<number[]>([]);
|
|
|
|
+
|
|
|
|
+ const {
|
|
|
|
+ dataList,
|
|
|
|
+ pagination,
|
|
|
|
+ loading,
|
|
|
|
+ selectedRows,
|
|
|
|
+ toPage,
|
|
|
|
+ getList,
|
|
|
|
+ pageSizeChange,
|
|
|
|
+ handleSelectionChange,
|
|
|
|
+ } = useTable<MarkMarkerItem>(getMarkMarkerList, searchModel, false);
|
|
|
|
+
|
|
|
|
+ // 计算选中的评卷员ID列表
|
|
|
|
+ const selectedMarkerIds = computed(() => {
|
|
|
|
+ return selectedRows.value.map((row) => row.id);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 获取状态类型
|
|
|
|
+ function getStatusType(status: string) {
|
|
|
|
+ const statusMap: Record<string, string> = {
|
|
|
|
+ enabled: 'success',
|
|
|
|
+ disabled: 'danger',
|
|
|
|
+ binding: 'warning',
|
|
|
|
+ };
|
|
|
|
+ return statusMap[status] || 'info';
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取状态文本
|
|
|
|
+ function getStatusText(status: string) {
|
|
|
|
+ const statusMap: Record<string, string> = {
|
|
|
|
+ enabled: '已启用',
|
|
|
|
+ disabled: '已禁用',
|
|
|
|
+ binding: '绑定中',
|
|
|
|
+ };
|
|
|
|
+ return statusMap[status] || status;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 启用/禁用评卷员
|
|
|
|
+ async function onEnable(row: MarkMarkerItem, enable: boolean) {
|
|
|
|
+ const action = enable ? '启用' : '禁用';
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认${action}评卷员 ${row.name}(${row.loginName}) 吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerEnable({ ids: [row.id], enable });
|
|
|
|
+ ElMessage.success(`${action}成功`);
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`${action}评卷员失败:`, error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量启用/禁用
|
|
|
|
+ async function onBatchEnable(enable: boolean) {
|
|
|
|
+ if (!selectedRows.value.length) {
|
|
|
|
+ ElMessage.warning('请选择评卷员');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const action = enable ? '启用' : '禁用';
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认${action}所选的 ${selectedRows.value.length} 个评卷员吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerEnable({ ids: selectedMarkerIds.value, enable });
|
|
|
|
+ ElMessage.success(`批量${action}成功`);
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error(`批量${action}评卷员失败:`, error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 解绑评卷员
|
|
|
|
+ async function onUnbind(row: MarkMarkerItem) {
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认解绑评卷员 ${row.name}(${row.loginName}) 吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerUnbind(row.id);
|
|
|
|
+ ElMessage.success('解绑成功');
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('解绑评卷员失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 设置评卷数量
|
|
|
|
+ function onSetTaskCount(row: MarkMarkerItem) {
|
|
|
|
+ curMarkerIds.value = [row.id];
|
|
|
|
+ setMarkCountDialogRef.value?.open();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量设置评卷数量
|
|
|
|
+ function onBatchSetTaskCount() {
|
|
|
|
+ curMarkerIds.value = selectedMarkerIds.value;
|
|
|
|
+ setMarkCountDialogRef.value?.open();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 回收任务
|
|
|
|
+ async function onRecycle(row: MarkMarkerItem) {
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认回收评卷员 ${row.name}(${row.loginName}) 的任务吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerTaskRecycle([row.id]);
|
|
|
|
+ ElMessage.success('回收成功');
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('回收任务失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量回收
|
|
|
|
+ async function onBatchRecycle() {
|
|
|
|
+ if (!selectedRows.value.length) {
|
|
|
|
+ ElMessage.warning('请选择评卷员');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认回收所选的 ${selectedRows.value.length} 个评卷员的任务吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerTaskRecycle(selectedMarkerIds.value);
|
|
|
|
+ ElMessage.success('批量回收成功');
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('批量回收任务失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 重置密码
|
|
|
|
+ async function onResetPassword(row: MarkMarkerItem) {
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认重置评卷员 ${row.name}(${row.loginName}) 的密码吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerResetPassword([row.id]);
|
|
|
|
+ ElMessage.success('重置密码成功');
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('重置密码失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 批量重置密码
|
|
|
|
+ async function onBatchResetPassword() {
|
|
|
|
+ if (!selectedRows.value.length) {
|
|
|
|
+ ElMessage.warning('请选择评卷员');
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认重置所选的 ${selectedRows.value.length} 个评卷员的密码吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerResetPassword(selectedMarkerIds.value);
|
|
|
|
+ ElMessage.success('批量重置密码成功');
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('批量重置密码失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 重置已评数量
|
|
|
|
+ async function onResetFinishCount(row: MarkMarkerItem) {
|
|
|
|
+ const confirm = await modalConfirm(
|
|
|
|
+ `确认重置评卷员 ${row.name}(${row.loginName}) 的已评数量吗?`,
|
|
|
|
+ '提示 '
|
|
|
|
+ ).catch(() => false);
|
|
|
|
+ if (!confirm) return;
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ await markMarkerResetFinishCount(row.id);
|
|
|
|
+ ElMessage.success('重置已评数量成功');
|
|
|
|
+ getList();
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('重置已评数量失败:', error);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 导入
|
|
|
|
+ const importDialogRef = ref();
|
|
|
|
+ const onImport = () => {
|
|
|
|
+ importDialogRef.value?.open();
|
|
|
|
+ };
|
|
|
|
+ async function downloadTemplate() {
|
|
|
|
+ // const res = await downloadByApi(() => agentTemplate()).catch((e) => {
|
|
|
|
+ // Message.error(e || '下载失败,请重新尝试!');
|
|
|
|
+ // });
|
|
|
|
+ // if (!res) return;
|
|
|
|
+ // Message.success('下载成功!');
|
|
|
|
+ }
|
|
|
|
+</script>
|