<script lang="ts" setup>
|
import type { ActionItem, BasicColumn } from '@jnpf/ui/vxeTable';
|
|
import type { MyPaperListItem } from './types';
|
|
import { onMounted, ref } from 'vue';
|
import { useRouter } from 'vue-router';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { BasicVxeTable, TableAction, useVxeTable } from '@jnpf/ui/vxeTable';
|
|
import { getMyPaperList, startOnlineExam } from '#/api/x/tms/onlineExam';
|
import { TMS_DIC_FIELD_NAMES } from '#/views/x/tms/shared/dic';
|
import { TMS_BTN } from '#/views/x/tms/shared/ui';
|
|
import {
|
MY_PAPER_STATUS_OPTIONS,
|
colorOfMyPaperStatus,
|
colorOfPassFlag,
|
labelOfMyPaperStatus,
|
labelOfPassFlag,
|
loadOnlineExamDics,
|
} from './constants';
|
|
import '#/views/x/tms/shared/page.css';
|
|
defineOptions({ name: 'TmsOnlineExam' });
|
|
const router = useRouter();
|
const { createMessage } = useMessage();
|
const starting = ref(false);
|
|
const columns: BasicColumn[] = [
|
{ title: '试卷名称', dataIndex: 'paperName', minWidth: 220 },
|
{
|
title: '考试类型',
|
dataIndex: 'attemptLabel',
|
width: 130,
|
align: 'center',
|
customRender: ({ record }) => {
|
const row = record as MyPaperListItem;
|
return row.attemptLabel
|
|| (row.attemptNo && row.attemptNo > 1 ? `补考(第${row.attemptNo - 1}次)` : '首考');
|
},
|
},
|
{
|
title: '状态',
|
dataIndex: 'status',
|
width: 100,
|
align: 'center',
|
slots: { default: 'status' },
|
},
|
{
|
title: '考试时间',
|
dataIndex: 'examTimeText',
|
minWidth: 260,
|
customRender: ({ record }) => (record as MyPaperListItem).examTimeText || '-',
|
},
|
{
|
title: '卷面总分',
|
dataIndex: 'totalScore',
|
width: 100,
|
align: 'center',
|
},
|
{
|
title: '是否合格',
|
dataIndex: 'passFlag',
|
width: 100,
|
align: 'center',
|
slots: { default: 'passFlag' },
|
},
|
{
|
title: '剩余补考',
|
dataIndex: 'remainingRetakes',
|
width: 100,
|
align: 'center',
|
customRender: ({ record }) => {
|
const row = record as MyPaperListItem;
|
if (row.retakeLimit == null) return '-';
|
return `${row.remainingRetakes ?? 0} / ${row.retakeLimit}`;
|
},
|
},
|
];
|
|
const [registerTable, { reload, getForm }] = useVxeTable({
|
api: fetchList,
|
columns,
|
immediate: false,
|
rowKey: 'id',
|
useSearchForm: true,
|
formConfig: {
|
baseColProps: { span: 6 },
|
compact: true,
|
schemas: [
|
{
|
field: 'keyword',
|
label: '试卷名称',
|
component: 'Input',
|
componentProps: { placeholder: '请输入试卷名称', submitOnPressEnter: true },
|
},
|
{
|
field: 'status',
|
label: '状态',
|
component: 'Select',
|
componentProps: {
|
allowClear: true,
|
placeholder: '请选择状态',
|
options: MY_PAPER_STATUS_OPTIONS.value,
|
fieldNames: TMS_DIC_FIELD_NAMES,
|
},
|
},
|
],
|
},
|
actionColumn: {
|
width: 200,
|
title: '操作',
|
dataIndex: 'action',
|
fixed: 'right',
|
},
|
});
|
|
onMounted(async () => {
|
await loadOnlineExamDics();
|
getForm()?.updateSchema?.({
|
field: 'status',
|
componentProps: {
|
allowClear: true,
|
placeholder: '请选择状态',
|
options: MY_PAPER_STATUS_OPTIONS.value,
|
fieldNames: TMS_DIC_FIELD_NAMES,
|
},
|
});
|
reload();
|
});
|
|
async function fetchList(params: Record<string, any>) {
|
const page = await getMyPaperList(params);
|
return {
|
data: {
|
list: Array.isArray(page?.list) ? page.list : [],
|
pagination: page?.pagination || { total: 0 },
|
},
|
};
|
}
|
|
function handleDetail(record: MyPaperListItem) {
|
router.push(`/tms/onlineExam/detail/${record.id}`);
|
}
|
|
async function handleStart(record: MyPaperListItem) {
|
if (starting.value) return;
|
starting.value = true;
|
try {
|
const paper = await startOnlineExam(record.id);
|
if (paper?.autoSubmitted) {
|
createMessage.warning('考试时间已到,已自动交卷');
|
reload();
|
return;
|
}
|
sessionStorage.setItem('tms_online_exam_paper', JSON.stringify(paper));
|
sessionStorage.setItem('tms_online_exam_myPaperId', record.id);
|
router.push('/tms/onlineExam/exam');
|
} catch (e: any) {
|
const msg = e?.message || '开始考试失败';
|
if (String(msg).includes('自动交卷')) {
|
createMessage.warning(msg);
|
reload();
|
} else {
|
createMessage.error(msg);
|
}
|
} finally {
|
starting.value = false;
|
}
|
}
|
|
function getTableActions(record: MyPaperListItem): ActionItem[] {
|
const actions: ActionItem[] = [];
|
if (record.status === 'notStarted') {
|
actions.push({ label: TMS_BTN.startExam, onClick: handleStart.bind(null, record) });
|
} else if (record.status === 'doing') {
|
actions.push({ label: TMS_BTN.continueExam, onClick: handleStart.bind(null, record) });
|
} else if (record.status === 'submitted' && record.canRetake) {
|
actions.push({ label: TMS_BTN.retake, onClick: handleStart.bind(null, record) });
|
}
|
actions.push({ label: TMS_BTN.detail, onClick: handleDetail.bind(null, record) });
|
return actions;
|
}
|
</script>
|
|
<template>
|
<div class="jnpf-content-wrapper">
|
<div class="jnpf-content-wrapper-center">
|
<div class="jnpf-content-wrapper-content">
|
<BasicVxeTable @register="registerTable">
|
<template #tableTitle>
|
<div>
|
<div class="tms-page-header__title">我的试卷</div>
|
<div class="tms-page-header__sub">参加考试或查看成绩;可考时操作列直接开考。</div>
|
</div>
|
</template>
|
<template #status="{ record }">
|
<span :style="{ color: colorOfMyPaperStatus(record.status) }">
|
{{ labelOfMyPaperStatus(record.status) }}
|
</span>
|
</template>
|
<template #passFlag="{ record }">
|
<span :style="{ color: colorOfPassFlag(record.passFlag) }">
|
{{ labelOfPassFlag(record.passFlag) }}
|
</span>
|
</template>
|
<template #action="{ record }">
|
<TableAction :actions="getTableActions(record)" />
|
</template>
|
</BasicVxeTable>
|
</div>
|
</div>
|
</div>
|
</template>
|