<script lang="ts" setup>
|
import { computed, reactive, ref, watch } from 'vue';
|
|
import { useMessage } from '@jnpf/hooks';
|
import { Modal as AModal } from 'ant-design-vue';
|
|
import { submitPersonTaskQuiz } from '#/api/x/tms/personTask';
|
|
export interface QuizQuestion {
|
id?: string;
|
sortNo?: number;
|
question?: string;
|
}
|
|
const props = defineProps<{
|
open: boolean;
|
personTaskId?: string;
|
questions?: QuizQuestion[];
|
}>();
|
|
const emit = defineEmits<{
|
(e: 'update:open', v: boolean): void;
|
(e: 'done', result: { score?: number; passFlag?: string; message?: string }): void;
|
}>();
|
|
const { createMessage } = useMessage();
|
const submitting = ref(false);
|
const answers = reactive<Record<string, string>>({});
|
|
const questionList = computed(() => (props.questions || []).filter((q) => q?.id && q.question));
|
|
watch(
|
() => [props.open, props.questions] as const,
|
() => {
|
Object.keys(answers).forEach((k) => delete answers[k]);
|
for (const q of questionList.value) {
|
if (q.id) answers[q.id] = '';
|
}
|
},
|
{ immediate: true, deep: true },
|
);
|
|
async function handleOk() {
|
if (!props.personTaskId) {
|
createMessage.error('缺少个人任务');
|
return;
|
}
|
for (const q of questionList.value) {
|
if (!q.id || !String(answers[q.id] || '').trim()) {
|
createMessage.warning('请完成全部提问后再提交');
|
return;
|
}
|
}
|
submitting.value = true;
|
try {
|
const result = await submitPersonTaskQuiz(props.personTaskId, {
|
answers: questionList.value.map((q) => ({
|
quizId: q.id!,
|
answer: String(answers[q.id!] || '').trim(),
|
})),
|
});
|
createMessage.success(result.message || '提交成功');
|
emit('done', result);
|
emit('update:open', false);
|
} catch (e: any) {
|
createMessage.error(e?.message || '提交失败');
|
} finally {
|
submitting.value = false;
|
}
|
}
|
|
function handleCancel() {
|
createMessage.warning('请完成提问后再关闭');
|
}
|
</script>
|
|
<template>
|
<AModal
|
:open="open"
|
title="培训提问"
|
:mask-closable="false"
|
:keyboard="false"
|
:closable="false"
|
:confirm-loading="submitting"
|
ok-text="提交答案"
|
cancel-text="暂不关闭"
|
width="640px"
|
@ok="handleOk"
|
@cancel="handleCancel"
|
>
|
<div class="quiz-popup">
|
<div class="quiz-popup__tip">请完成以下提问后才能继续。答案将与参考答案自动比对判分。</div>
|
<div v-for="(q, idx) in questionList" :key="q.id" class="quiz-item">
|
<div class="quiz-item__q">{{ idx + 1 }}. {{ q.question }}</div>
|
<a-textarea
|
v-model:value="answers[q.id!]"
|
:rows="2"
|
:maxlength="500"
|
placeholder="请输入答案"
|
/>
|
</div>
|
<div v-if="!questionList.length" class="quiz-empty">暂无题目</div>
|
</div>
|
</AModal>
|
</template>
|
|
<style scoped>
|
.quiz-popup__tip {
|
margin-bottom: 12px;
|
color: rgba(0, 0, 0, 0.65);
|
font-size: 13px;
|
}
|
|
.quiz-item {
|
margin-bottom: 12px;
|
}
|
|
.quiz-item__q {
|
margin-bottom: 6px;
|
font-weight: 500;
|
}
|
|
.quiz-empty {
|
color: rgba(0, 0, 0, 0.45);
|
text-align: center;
|
padding: 24px 0;
|
}
|
</style>
|