| | |
| | | |
| | | import type { MyPaperListItem } from './types'; |
| | | |
| | | import { ref } from 'vue'; |
| | | 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, labelOfMyPaperStatus } from './constants'; |
| | | import { |
| | | MY_PAPER_STATUS_OPTIONS, |
| | | colorOfMyPaperStatus, |
| | | colorOfPassFlag, |
| | | labelOfMyPaperStatus, |
| | | labelOfPassFlag, |
| | | loadOnlineExamDics, |
| | | } from './constants'; |
| | | |
| | | import '#/views/x/tms/shared/page.css'; |
| | | |
| | | defineOptions({ name: 'TmsOnlineExam' }); |
| | | |
| | |
| | | const starting = ref(false); |
| | | |
| | | const columns: BasicColumn[] = [ |
| | | { title: '试卷名称', dataIndex: 'paperName', minWidth: 260 }, |
| | | { 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', |
| | |
| | | { |
| | | title: '考试时间', |
| | | dataIndex: 'examTimeText', |
| | | minWidth: 280, |
| | | minWidth: 260, |
| | | customRender: ({ record }) => (record as MyPaperListItem).examTimeText || '-', |
| | | }, |
| | | { |
| | |
| | | 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] = useVxeTable({ |
| | | const [registerTable, { reload, getForm }] = useVxeTable({ |
| | | api: fetchList, |
| | | columns, |
| | | immediate: true, |
| | | immediate: false, |
| | | rowKey: 'id', |
| | | useSearchForm: true, |
| | | formConfig: { |
| | |
| | | componentProps: { |
| | | allowClear: true, |
| | | placeholder: '请选择状态', |
| | | options: MY_PAPER_STATUS_OPTIONS, |
| | | options: MY_PAPER_STATUS_OPTIONS.value, |
| | | fieldNames: TMS_DIC_FIELD_NAMES, |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | actionColumn: { |
| | | width: 160, |
| | | 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>) { |
| | | return { data: await getMyPaperList(params) }; |
| | | const page = await getMyPaperList(params); |
| | | return { |
| | | data: { |
| | | list: Array.isArray(page?.list) ? page.list : [], |
| | | pagination: page?.pagination || { total: 0 }, |
| | | }, |
| | | }; |
| | | } |
| | | |
| | | function handleDetail(record: MyPaperListItem) { |
| | |
| | | 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) { |
| | | createMessage.error(e?.message || '开始考试失败'); |
| | | 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: '开始考试', onClick: handleStart.bind(null, record) }); |
| | | actions.push({ label: TMS_BTN.startExam, onClick: handleStart.bind(null, record) }); |
| | | } else if (record.status === 'doing') { |
| | | actions.push({ label: '继续考试', onClick: handleStart.bind(null, record) }); |
| | | 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: '查看详情', onClick: handleDetail.bind(null, record) }); |
| | | actions.push({ label: TMS_BTN.detail, onClick: handleDetail.bind(null, record) }); |
| | | return actions; |
| | | } |
| | | </script> |
| | |
| | | <BasicVxeTable @register="registerTable"> |
| | | <template #tableTitle> |
| | | <div> |
| | | <div class="text-base font-medium">我的试卷</div> |
| | | <div class="mt-1 text-gray-400 text-sm">我的试卷,选择试卷参加考试,或者查看考试详情。</div> |
| | | <div class="tms-page-header__title">我的试卷</div> |
| | | <div class="tms-page-header__sub">参加考试或查看成绩;可考时操作列直接开考。</div> |
| | | </div> |
| | | </template> |
| | | <template #status="{ record }"> |
| | |
| | | {{ 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> |