<script lang="ts" setup>
|
import type { PaperEntity } from './types';
|
|
import { onMounted, ref } from 'vue';
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { useMessage } from '@jnpf/hooks';
|
import {
|
Descriptions as ADescriptions,
|
DescriptionsItem as ADescriptionsItem,
|
} from 'ant-design-vue';
|
|
import { getPaperInfo } from '#/api/x/tms/paper';
|
|
import {
|
labelOfSortMode,
|
labelOfStatus,
|
labelOfType,
|
loadPaperDics,
|
} from './constants';
|
|
defineOptions({ name: 'TmsPaperDetail' });
|
|
const route = useRoute();
|
const router = useRouter();
|
const { createMessage } = useMessage();
|
|
const loading = ref(false);
|
const detail = ref<PaperEntity | null>(null);
|
|
onMounted(async () => {
|
await loadPaperDics();
|
await loadData();
|
});
|
|
async function loadData() {
|
const id = String(route.params.id || '');
|
if (!id) {
|
router.replace('/tms/paper');
|
return;
|
}
|
loading.value = true;
|
try {
|
detail.value = await getPaperInfo(id);
|
} catch (e: any) {
|
createMessage.error(e?.message || '加载试卷失败');
|
router.replace('/tms/paper');
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
function goBack() {
|
router.push('/tms/paper');
|
}
|
|
function goEdit() {
|
if (!detail.value?.id || detail.value.bizStatus !== 'closed') return;
|
router.push(`/tms/paper/edit/${detail.value.id}`);
|
}
|
|
function stripHtml(html?: string) {
|
if (!html) return '';
|
return html.replace(/<[^>]+>/g, '').replace(/ /g, ' ').trim();
|
}
|
</script>
|
|
<template>
|
<div class="jnpf-content-wrapper tms-paper-detail-page" v-loading="loading">
|
<div class="jnpf-content-wrapper-center">
|
<div class="jnpf-content-wrapper-content tms-paper-detail-wrap" v-if="detail">
|
<a-card title="试卷详情" :bordered="false">
|
<template #extra>
|
<a-space>
|
<a-button @click="goBack">返回</a-button>
|
<a-button
|
type="primary"
|
:disabled="detail.bizStatus !== 'closed'"
|
@click="goEdit"
|
>
|
编辑
|
</a-button>
|
</a-space>
|
</template>
|
|
<ADescriptions :column="2" bordered size="small">
|
<ADescriptionsItem label="试卷编号">{{ detail.paperNo || '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="试卷名称">{{ detail.paperName }}</ADescriptionsItem>
|
<ADescriptionsItem label="状态">{{ labelOfStatus(detail.bizStatus) }}</ADescriptionsItem>
|
<ADescriptionsItem label="考试时长">{{ detail.durationMin ?? '-' }} 分钟</ADescriptionsItem>
|
<ADescriptionsItem label="试题排序">{{ labelOfSortMode(detail.sortMode) }}</ADescriptionsItem>
|
<ADescriptionsItem label="开考时间">{{ detail.examStart || '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="结束时间">{{ detail.examEnd || '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="成绩公布时间">{{ detail.scorePublishTime || '立即公布' }}</ADescriptionsItem>
|
<ADescriptionsItem label="试卷总分">{{ detail.totalScore ?? '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="合格分数">{{ detail.passScore ?? '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="含主观题">{{ detail.hasSubjective === '1' ? '是' : '否' }}</ADescriptionsItem>
|
<ADescriptionsItem label="创建时间">{{ detail.creatorTime || '-' }}</ADescriptionsItem>
|
<ADescriptionsItem label="备注" :span="2">{{ detail.remark || '-' }}</ADescriptionsItem>
|
</ADescriptions>
|
</a-card>
|
|
<a-card title="组卷内容" :bordered="false" style="margin-top: 12px">
|
<div v-for="sec in detail.sections || []" :key="sec.id" class="section-block">
|
<div class="section-title">
|
{{ sec.sectionName }}
|
<span class="muted">({{ labelOfType(sec.questionType) }} · {{ (sec.questions || []).length }} 题)</span>
|
</div>
|
<a-table
|
size="small"
|
row-key="questionId"
|
:pagination="false"
|
:data-source="sec.questions || []"
|
:columns="[
|
{ title: '序号', width: 60, customRender: ({ index }: any) => index + 1 },
|
{ title: '编号', dataIndex: 'questionNo', width: 90 },
|
{
|
title: '题干',
|
dataIndex: 'stem',
|
customRender: ({ record }: any) => stripHtml(record.stem),
|
},
|
{ title: '题库', dataIndex: 'bankName', width: 140 },
|
{ title: '分值', dataIndex: 'score', width: 80 },
|
]"
|
/>
|
</div>
|
<a-empty v-if="!(detail.sections || []).length" description="暂无组卷内容" />
|
</a-card>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<style scoped>
|
.tms-paper-detail-page {
|
height: 100%;
|
min-height: 0;
|
}
|
|
.tms-paper-detail-wrap {
|
height: 100%;
|
min-height: 0;
|
overflow-x: hidden;
|
overflow-y: auto !important;
|
background: #fff;
|
padding: 16px;
|
box-sizing: border-box;
|
}
|
|
.section-block {
|
margin-bottom: 16px;
|
}
|
.section-title {
|
margin-bottom: 8px;
|
font-weight: 600;
|
}
|
.muted {
|
margin-left: 8px;
|
color: #999;
|
font-weight: 400;
|
font-size: 13px;
|
}
|
</style>
|