feat:更新考试模块
This commit is contained in:
@@ -164,7 +164,7 @@ const generateClick = async () => {
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await fetch('/study-api/library/knowledge', {
|
||||
const response = await fetch('/study-api/agent/knowledge', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
import { Delete, Edit, Picture, Document, Aim } from '@element-plus/icons-vue'
|
||||
import { useLibraryStore } from '@/stores/library.ts'
|
||||
import { usePracticeStore } from '@/stores/practice.ts'
|
||||
import { useQuestionStore } from '@/stores/question.ts'
|
||||
import type { ILibraryFile } from '@/types/library.ts'
|
||||
import LibraryFilter from '@/components/Library/LibraryFilter.vue'
|
||||
import { computed } from 'vue'
|
||||
@@ -38,6 +39,7 @@ import { ElLoading, ElMessage } from 'element-plus'
|
||||
|
||||
const libraryStore = useLibraryStore()
|
||||
const practiceStore = usePracticeStore()
|
||||
const questionStore = useQuestionStore()
|
||||
|
||||
const filterLibraryFileList = computed(() => {
|
||||
const subject = libraryStore.selectedSubject
|
||||
@@ -62,12 +64,12 @@ const trainClick = async (file: ILibraryFile) => {
|
||||
await generateQuestion()
|
||||
practiceStore.hasStart = true
|
||||
practiceStore.hasSubmit = false
|
||||
practiceStore.checkList = []
|
||||
questionStore.checkList = []
|
||||
}
|
||||
|
||||
const generateQuestion = async () => {
|
||||
practiceStore.questionContent = ''
|
||||
practiceStore.hasGenerateQuestion = false
|
||||
questionStore.questionContent = ''
|
||||
questionStore.hasGenerateQuestion = false
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
@@ -76,7 +78,7 @@ const generateQuestion = async () => {
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await fetch('/study-api/library/question', {
|
||||
const response = await fetch('/study-api/agent/question', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@@ -96,13 +98,13 @@ const generateQuestion = async () => {
|
||||
while (true) {
|
||||
const { value, done } = await reader.read()
|
||||
if (done) break
|
||||
practiceStore.questionContent += decoder.decode(value, { stream: true })
|
||||
questionStore.questionContent += decoder.decode(value, { stream: true })
|
||||
}
|
||||
|
||||
ElMessage.success('生成完成')
|
||||
practiceStore.hasGenerateQuestion = true
|
||||
questionStore.hasGenerateQuestion = true
|
||||
|
||||
practiceStore.questionList = JSON.parse(practiceStore.questionContent)
|
||||
questionStore.questionList = JSON.parse(questionStore.questionContent)
|
||||
libraryStore.fileTrainDialogVisible = true
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
|
||||
@@ -2,177 +2,14 @@
|
||||
<el-dialog v-model="libraryStore.fileTrainDialogVisible"
|
||||
:title="libraryStore.currentFile.name" width="80%" center destroy-on-close
|
||||
class="train-dialog common-dialog">
|
||||
<div class="question-list">
|
||||
<div v-for="(q, idx) in practiceStore.questionList" :key="q.id" class="question-card">
|
||||
<div class="q-header">
|
||||
<el-tag :type="q.type === 'single' ? 'primary' : 'warning'" effect="dark">
|
||||
{{ q.type === 'single' ? '单选' : '多选' }}
|
||||
</el-tag>
|
||||
<span class="q-num">第{{ idx + 1 }}题</span>
|
||||
</div>
|
||||
|
||||
<div class="q-stem">{{ q.question }}</div>
|
||||
|
||||
<div class="q-options">
|
||||
<el-radio-group v-if="q.type === 'single'" v-model="q.select[0]">
|
||||
<el-radio v-for="(opt, oi) in q.options" :key="oi" :value="optLetter(oi)">
|
||||
{{ optLetter(oi) }}. {{ opt }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<!-- 多选 -->
|
||||
<el-checkbox-group v-if="q.type === 'multiple'" v-model="q.select">
|
||||
<el-checkbox v-for="(opt, oi) in q.options" :key="oi" :value="optLetter(oi)">
|
||||
{{ optLetter(oi) }}. {{ opt }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
|
||||
<div v-if="practiceStore.checkList.length > 0" class="q-check">
|
||||
<span style="font-weight: bold;"
|
||||
:style="{color: practiceStore.checkList[idx].isCorrect ? 'green' : 'red'}">
|
||||
正确答案 {{ practiceStore.checkList[idx].answer.join('、') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!practiceStore.hasSubmit" class="question-action">
|
||||
<el-button type="success" @click="submitAnswerClick">提交答案</el-button>
|
||||
</div>
|
||||
<question-list />
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePracticeStore } from '@/stores/practice.ts'
|
||||
import QuestionList from '@/components/question/QuestionList.vue'
|
||||
import { useLibraryStore } from '@/stores/library.ts'
|
||||
import { useMistakeStore } from '@/stores/mistake.ts'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getMistakeList, isAnswerCorrect, optLetter } from '@/utils/practiceUtil.ts'
|
||||
import type { IMistake } from '@/types/mistake.ts'
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const libraryStore = useLibraryStore()
|
||||
const mistakeStore = useMistakeStore()
|
||||
|
||||
const submitAnswerClick = async () => {
|
||||
if (practiceStore.questionList.find((item) => item.select.length === 0)) {
|
||||
ElMessage.error('还有未完成的题目')
|
||||
} else {
|
||||
practiceStore.hasSubmit = true
|
||||
practiceStore.checkList = practiceStore.questionList.map((q) => ({
|
||||
id: q.id,
|
||||
answer: q.answer,
|
||||
select: q.select,
|
||||
isCorrect: isAnswerCorrect(q.answer, q.select)
|
||||
}))
|
||||
await addPracticeRecord()
|
||||
await addMistakeList()
|
||||
|
||||
const { totalCount, correctCount, wrongCount } = practiceStore.currentRecord
|
||||
await ElMessageBox.alert(
|
||||
`共 ${totalCount} 题 · 正确 ${correctCount} · 错误 ${wrongCount}`,
|
||||
'训练结果',
|
||||
{
|
||||
confirmButtonText: '确认'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const addPracticeRecord = async () => {
|
||||
const totalCount = practiceStore.checkList.length
|
||||
const correctCount = practiceStore.checkList.filter((c) => c.isCorrect).length
|
||||
|
||||
practiceStore.currentRecord = {
|
||||
libraryFileId: libraryStore.currentFile.id,
|
||||
totalCount,
|
||||
correctCount,
|
||||
wrongCount: totalCount - correctCount
|
||||
}
|
||||
await practiceStore.addRecord()
|
||||
}
|
||||
|
||||
const addMistakeList = async () => {
|
||||
const mistakeList = getMistakeList(practiceStore.questionList, practiceStore.checkList)
|
||||
mistakeStore.currentMistakes = []
|
||||
mistakeList.forEach((item) => {
|
||||
const mistake:IMistake = {
|
||||
answer: item.answer,
|
||||
module: libraryStore.currentFile.module,
|
||||
name: libraryStore.currentFile.name,
|
||||
options: item.options,
|
||||
question: item.question,
|
||||
subject: libraryStore.currentFile.subject,
|
||||
type: item.type
|
||||
}
|
||||
mistakeStore.currentMistakes.push(mistake)
|
||||
})
|
||||
await mistakeStore.addMistakeList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.train-dialog {
|
||||
.el-dialog__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.question-list {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.question-card {
|
||||
padding: 10px 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
border-bottom: 1px solid lightgray;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.q-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.q-num {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.q-stem {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.q-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.q-check {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.question-action {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
114
src/components/exam/ExamDialog.vue
Normal file
114
src/components/exam/ExamDialog.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<el-dialog v-model="examStore.dialogVisible" title="考试配置" width="30%" center destroy-on-close>
|
||||
<el-form ref="examFormRef" :model="examStore.config" :rules="rules" label-width="auto">
|
||||
<el-form-item label="考试学科" prop="subject">
|
||||
<el-select
|
||||
v-model="examStore.config.subject"
|
||||
placeholder="请选择考试学科"
|
||||
>
|
||||
<el-option
|
||||
v-for="(item, index) in subjectList"
|
||||
:key="index" :label="item" :value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="题目数量" prop="total">
|
||||
<el-input-number
|
||||
v-model="examStore.config.total"
|
||||
:min="10"
|
||||
:max="50"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="examStore.dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmClick(examFormRef)">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElInputNumber, ElLoading, ElMessage, ElOption, ElSelect, type FormInstance } from 'element-plus'
|
||||
import { useExamStore } from '@/stores/exam.ts'
|
||||
import { useLibraryStore } from '@/stores/library.ts'
|
||||
import { useQuestionStore } from '@/stores/question.ts'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const examStore = useExamStore()
|
||||
const libraryStore = useLibraryStore()
|
||||
const questionStore = useQuestionStore()
|
||||
|
||||
const examFormRef = ref<FormInstance>()
|
||||
|
||||
const subjectList = computed(() => {
|
||||
return [...new Set(libraryStore.fileList.map((item) => item.subject))]
|
||||
})
|
||||
|
||||
const rules = {
|
||||
subject: [
|
||||
{ required: true, message: '请选择考试学科', trigger: 'blur' }
|
||||
],
|
||||
total: [
|
||||
{ required: true, message: '请选择题目数量', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
const confirmClick = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return
|
||||
await formEl.validate(async (valid, fields) => {
|
||||
if (valid) {
|
||||
await generateExam()
|
||||
} else {
|
||||
ElMessage.error('请先输入信息')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const generateExam = async () => {
|
||||
questionStore.questionList = []
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '题库生成中 请等待',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await fetch('/study-api/agent/exam', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subject: examStore.config.subject,
|
||||
total: examStore.config.total
|
||||
})
|
||||
})
|
||||
|
||||
if (!response.body) {
|
||||
throw new Error('未获取到响应流')
|
||||
}
|
||||
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder('utf-8')
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read()
|
||||
if (done) break
|
||||
questionStore.questionContent += decoder.decode(value, { stream: true })
|
||||
}
|
||||
|
||||
ElMessage.success('生成完成')
|
||||
|
||||
questionStore.questionList = JSON.parse(questionStore.questionContent)
|
||||
examStore.dialogVisible = false
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
ElMessage.error('生成失败 请联系管理员')
|
||||
} finally {
|
||||
loading.close()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
177
src/components/question/QuestionList.vue
Normal file
177
src/components/question/QuestionList.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div class="question-container">
|
||||
<div class="question-list">
|
||||
<div v-for="(q, idx) in questionStore.questionList" :key="q.id" class="question-card">
|
||||
<div class="q-header">
|
||||
<el-tag :type="q.type === 'single' ? 'primary' : 'warning'" effect="dark">
|
||||
{{ q.type === 'single' ? '单选' : '多选' }}
|
||||
</el-tag>
|
||||
<span class="q-num">第{{ idx + 1 }}题</span>
|
||||
</div>
|
||||
|
||||
<div class="q-stem">{{ q.question }}</div>
|
||||
|
||||
<div class="q-options">
|
||||
<el-radio-group v-if="q.type === 'single'" v-model="q.select[0]">
|
||||
<el-radio v-for="(opt, oi) in q.options" :key="oi" :value="optLetter(oi)">
|
||||
{{ optLetter(oi) }}. {{ opt }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<!-- 多选 -->
|
||||
<el-checkbox-group v-if="q.type === 'multiple'" v-model="q.select">
|
||||
<el-checkbox v-for="(opt, oi) in q.options" :key="oi" :value="optLetter(oi)">
|
||||
{{ optLetter(oi) }}. {{ opt }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
|
||||
<div v-if="questionStore.checkList.length > 0" class="q-check">
|
||||
<span style="font-weight: bold;"
|
||||
:style="{color: questionStore.checkList[idx].isCorrect ? 'green' : 'red'}">
|
||||
正确答案 {{ questionStore.checkList[idx].answer.join('、') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!questionStore.hasSubmit" class="question-action">
|
||||
<el-button type="success" @click="submitAnswerClick">提交答案</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { usePracticeStore } from '@/stores/practice.ts'
|
||||
import { useLibraryStore } from '@/stores/library.ts'
|
||||
import { useMistakeStore } from '@/stores/mistake.ts'
|
||||
import { useQuestionStore } from '@/stores/question.ts'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getMistakeList, isAnswerCorrect, optLetter } from '@/utils/practiceUtil.ts'
|
||||
import type { IMistake } from '@/types/mistake.ts'
|
||||
|
||||
const practiceStore = usePracticeStore()
|
||||
const libraryStore = useLibraryStore()
|
||||
const mistakeStore = useMistakeStore()
|
||||
const questionStore = useQuestionStore()
|
||||
|
||||
const submitAnswerClick = async () => {
|
||||
if (questionStore.questionList.find((item) => item.select.length === 0)) {
|
||||
ElMessage.error('还有未完成的题目')
|
||||
} else {
|
||||
practiceStore.hasSubmit = true
|
||||
questionStore.checkList = questionStore.questionList.map((q) => ({
|
||||
id: q.id,
|
||||
answer: q.answer,
|
||||
select: q.select,
|
||||
isCorrect: isAnswerCorrect(q.answer, q.select)
|
||||
}))
|
||||
await addPracticeRecord()
|
||||
await addMistakeList()
|
||||
|
||||
const { totalCount, correctCount, wrongCount } = practiceStore.currentRecord
|
||||
await ElMessageBox.alert(
|
||||
`共 ${totalCount} 题 · 正确 ${correctCount} · 错误 ${wrongCount}`,
|
||||
'训练结果',
|
||||
{
|
||||
confirmButtonText: '确认'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const addPracticeRecord = async () => {
|
||||
const totalCount = questionStore.checkList.length
|
||||
const correctCount = questionStore.checkList.filter((c) => c.isCorrect).length
|
||||
|
||||
practiceStore.currentRecord = {
|
||||
libraryFileId: libraryStore.currentFile.id,
|
||||
totalCount,
|
||||
correctCount,
|
||||
wrongCount: totalCount - correctCount
|
||||
}
|
||||
await practiceStore.addRecord()
|
||||
}
|
||||
|
||||
const addMistakeList = async () => {
|
||||
const mistakeList = getMistakeList(questionStore.questionList, questionStore.checkList)
|
||||
mistakeStore.currentMistakes = []
|
||||
mistakeList.forEach((item) => {
|
||||
const mistake:IMistake = {
|
||||
answer: item.answer,
|
||||
module: libraryStore.currentFile.module,
|
||||
name: libraryStore.currentFile.name,
|
||||
options: item.options,
|
||||
question: item.question,
|
||||
subject: libraryStore.currentFile.subject,
|
||||
type: item.type
|
||||
}
|
||||
mistakeStore.currentMistakes.push(mistake)
|
||||
})
|
||||
await mistakeStore.addMistakeList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.question-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
.question-list {
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.question-card {
|
||||
padding: 10px 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
border-bottom: 1px solid lightgray;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.q-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.q-num {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.q-stem {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.q-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.q-check {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.question-action {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
19
src/stores/exam.ts
Normal file
19
src/stores/exam.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { IExamConfig } from '@/types/exam.ts'
|
||||
|
||||
export const useExamStore = defineStore('exam', {
|
||||
state: () => ({
|
||||
hasStart: false,
|
||||
hasSubmit: false,
|
||||
dialogVisible: false,
|
||||
config: {} as IExamConfig
|
||||
}),
|
||||
actions: {
|
||||
getEmptyConfig(): IExamConfig {
|
||||
return {
|
||||
subject: '',
|
||||
total: 50
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,18 +1,13 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { addPracticeRecordApi, queryPracticeRecordApi } from '@/apis/practice.ts'
|
||||
import type { IPracticeCheck, IPracticeRecord } from '@/types/practice.ts'
|
||||
import type { IQuestion } from '@/types/question.ts'
|
||||
import type { IPracticeRecord } from '@/types/practice.ts'
|
||||
|
||||
export const usePracticeStore = defineStore('practice', {
|
||||
state: () => ({
|
||||
hasStart: false,
|
||||
hasSubmit: false,
|
||||
libraryFileId: 0,
|
||||
hasGenerateQuestion: false,
|
||||
questionContent: '',
|
||||
questionList: [] as IQuestion[],
|
||||
recordList: [] as IPracticeRecord[],
|
||||
checkList: [] as IPracticeCheck[],
|
||||
currentRecord: {} as IPracticeRecord
|
||||
}),
|
||||
actions: {
|
||||
|
||||
15
src/stores/question.ts
Normal file
15
src/stores/question.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { IPracticeCheck, IPracticeRecord } from '@/types/practice.ts'
|
||||
import type { IQuestion } from '@/types/question.ts'
|
||||
|
||||
export const useQuestionStore = defineStore('question', {
|
||||
state: () => ({
|
||||
hasStart: false,
|
||||
hasSubmit: false,
|
||||
hasGenerateQuestion: false,
|
||||
questionContent: '',
|
||||
questionList: [] as IQuestion[],
|
||||
recordList: [] as IPracticeRecord[],
|
||||
checkList: [] as IPracticeCheck[]
|
||||
})
|
||||
})
|
||||
4
src/types/exam.ts
Normal file
4
src/types/exam.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface IExamConfig {
|
||||
subject: string;
|
||||
total: number;
|
||||
}
|
||||
@@ -1,11 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>考试中心</h2>
|
||||
<p style="color:#94a3b8;margin-top:8px;">按学科进行综合检验,模拟真实考试环境</p>
|
||||
<el-divider />
|
||||
<el-empty description="考试页面 - 待开发" />
|
||||
<div class="exam-view common-view">
|
||||
<div class="view-header">
|
||||
<div class="view-content">
|
||||
<h2 class="view-title">考试中心</h2>
|
||||
<p class="view-subtitle">按学科进行综合检验,模拟真实考试环境</p>
|
||||
</div>
|
||||
<el-button type="primary" :icon="Aim" @click="examClick">开始考试</el-button>
|
||||
</div>
|
||||
|
||||
<question-list v-if="questionStore.questionList.length > 0"/>
|
||||
|
||||
<exam-dialog />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import QuestionList from '@/components/question/QuestionList.vue'
|
||||
import ExamDialog from '@/components/exam/ExamDialog.vue'
|
||||
import { Aim } from '@element-plus/icons-vue'
|
||||
import { useExamStore } from '@/stores/exam.ts'
|
||||
import { useQuestionStore } from '@/stores/question.ts'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
const examStore = useExamStore()
|
||||
const questionStore = useQuestionStore()
|
||||
|
||||
onMounted(() => {
|
||||
questionStore.questionList = []
|
||||
})
|
||||
|
||||
const examClick = () => {
|
||||
questionStore.questionList = []
|
||||
examStore.config = examStore.getEmptyConfig()
|
||||
examStore.dialogVisible = true
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user