|
@@ -35,12 +35,13 @@
|
|
|
<h2>单选题</h2>
|
|
<h2>单选题</h2>
|
|
|
</div>
|
|
</div>
|
|
|
<v-btn
|
|
<v-btn
|
|
|
- v-for="i in questions"
|
|
|
|
|
- :key="i.id"
|
|
|
|
|
|
|
+ v-for="i in answeredChoices.slice(0, singleChoiceNum)"
|
|
|
|
|
+ :key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
x-small
|
|
|
|
|
+ :disabled="i.answered"
|
|
|
>
|
|
>
|
|
|
- {{ i.id }}
|
|
|
|
|
|
|
+ {{ i.index }}
|
|
|
</v-btn>
|
|
</v-btn>
|
|
|
</div>
|
|
</div>
|
|
|
<div column class="justify-space-between d-inline">
|
|
<div column class="justify-space-between d-inline">
|
|
@@ -48,13 +49,16 @@
|
|
|
<h2>多选题</h2>
|
|
<h2>多选题</h2>
|
|
|
</div>
|
|
</div>
|
|
|
<v-btn
|
|
<v-btn
|
|
|
- v-for="i in 12"
|
|
|
|
|
- :key="i"
|
|
|
|
|
|
|
+ v-for="i in answeredChoices.slice(
|
|
|
|
|
+ singleChoiceNum,
|
|
|
|
|
+ singleChoiceNum + multiChoiceNum
|
|
|
|
|
+ )"
|
|
|
|
|
+ :key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
x-small
|
|
|
- :disabled="questions[i].answered"
|
|
|
|
|
|
|
+ :disabled="i.answered"
|
|
|
>
|
|
>
|
|
|
- {{ questions[i - 1].id }}
|
|
|
|
|
|
|
+ {{ i.index }}
|
|
|
</v-btn>
|
|
</v-btn>
|
|
|
</div>
|
|
</div>
|
|
|
<div column class="justify-space-between">
|
|
<div column class="justify-space-between">
|
|
@@ -62,13 +66,13 @@
|
|
|
<h2>代码题</h2>
|
|
<h2>代码题</h2>
|
|
|
</div>
|
|
</div>
|
|
|
<v-btn
|
|
<v-btn
|
|
|
- v-for="i in 4"
|
|
|
|
|
- :key="i"
|
|
|
|
|
|
|
+ v-for="i in answeredCodes"
|
|
|
|
|
+ :key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
x-small
|
|
|
- :disabled="questions[i].answered"
|
|
|
|
|
|
|
+ :disabled="i.answered"
|
|
|
>
|
|
>
|
|
|
- {{ questions[i - 1].id }}
|
|
|
|
|
|
|
+ {{ i.index }}
|
|
|
</v-btn>
|
|
</v-btn>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -132,10 +136,13 @@
|
|
|
<code-pane
|
|
<code-pane
|
|
|
v-if="!isChoiceProblem"
|
|
v-if="!isChoiceProblem"
|
|
|
v-on:nextQuestion="nextQuestion"
|
|
v-on:nextQuestion="nextQuestion"
|
|
|
|
|
+ :question="curQuestion"
|
|
|
></code-pane>
|
|
></code-pane>
|
|
|
<choice-pane
|
|
<choice-pane
|
|
|
v-if="isChoiceProblem"
|
|
v-if="isChoiceProblem"
|
|
|
v-on:nextQuestion="nextQuestion(answer)"
|
|
v-on:nextQuestion="nextQuestion(answer)"
|
|
|
|
|
+ :total-question-num="multiChoiceNum"
|
|
|
|
|
+ :question="curQuestion"
|
|
|
></choice-pane>
|
|
></choice-pane>
|
|
|
</v-container>
|
|
</v-container>
|
|
|
</v-main>
|
|
</v-main>
|
|
@@ -147,32 +154,74 @@ import Vue from 'vue'
|
|
|
import CodePane from '@/views/exam/components/CodePane.vue'
|
|
import CodePane from '@/views/exam/components/CodePane.vue'
|
|
|
import ChoicePane from '@/views/exam/components/ChoicePane.vue'
|
|
import ChoicePane from '@/views/exam/components/ChoicePane.vue'
|
|
|
import CountDown from '@/views/exam/components/CountDown.vue'
|
|
import CountDown from '@/views/exam/components/CountDown.vue'
|
|
|
-import { ChoiceQuestionSerializer } from '@/api/types'
|
|
|
|
|
-
|
|
|
|
|
-interface OrderedCQuestion {}
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ ChoiceQuestionSerializer,
|
|
|
|
|
+ CodeQuestionSerializer,
|
|
|
|
|
+ ExamQuestionSerializer,
|
|
|
|
|
+ QuestionSerializer
|
|
|
|
|
+} from '@/api/types'
|
|
|
|
|
+import { getExamQuestions } from '@/api/exam'
|
|
|
|
|
|
|
|
export default Vue.extend({
|
|
export default Vue.extend({
|
|
|
name: 'ExamPane',
|
|
name: 'ExamPane',
|
|
|
|
|
+ components: {
|
|
|
|
|
+ CountDown,
|
|
|
|
|
+ CodePane,
|
|
|
|
|
+ ChoicePane
|
|
|
|
|
+ },
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
- isChoiceProblem: true,
|
|
|
|
|
exitDialog: false,
|
|
exitDialog: false,
|
|
|
submitDialog: false,
|
|
submitDialog: false,
|
|
|
- choiceQuestions: [] as Array<ChoiceQuestionSerializer>,
|
|
|
|
|
submitted: false,
|
|
submitted: false,
|
|
|
currentTime: new Date().getTime(),
|
|
currentTime: new Date().getTime(),
|
|
|
- choiceAnswers: [] as Array<String>
|
|
|
|
|
|
|
+ choiceAnswers: [] as Array<{ num: number; answer: string }>, // TODO codeAnswers
|
|
|
|
|
+ examId: 0,
|
|
|
|
|
+ examQuestionsObject: {} as ExamQuestionSerializer,
|
|
|
|
|
+ singleChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
|
|
|
|
|
+ multiChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
|
|
|
|
|
+ codeQuestions: [] as Array<CodeQuestionSerializer>,
|
|
|
|
|
+ allQuestions: [] as Array<QuestionSerializer>,
|
|
|
|
|
+ answeredChoices: [] as Array<{ index: number; answered: boolean }>,
|
|
|
|
|
+ answeredCodes: [] as Array<{ index: number; answered: boolean }>,
|
|
|
|
|
+
|
|
|
|
|
+ currentQuestionIndex: 0
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
- choiceQuestionAnswered(): Array<Boolean> {
|
|
|
|
|
- return this.choiceAnswers.map((value, index) => value !== '')
|
|
|
|
|
|
|
+ isChoiceProblem(): boolean {
|
|
|
|
|
+ return this.currentQuestionIndex < this.choiceQuestionNum
|
|
|
|
|
+ },
|
|
|
|
|
+ isSingleChoice(): boolean {
|
|
|
|
|
+ return this.currentQuestionIndex < this.singleChoiceNum
|
|
|
|
|
+ },
|
|
|
|
|
+ singleChoiceNum(): number {
|
|
|
|
|
+ return this.singleChoiceQuestions.length
|
|
|
|
|
+ },
|
|
|
|
|
+ multiChoiceNum(): number {
|
|
|
|
|
+ return this.multiChoiceQuestions.length
|
|
|
|
|
+ },
|
|
|
|
|
+ codeQuestionNum(): number {
|
|
|
|
|
+ return this.codeQuestions.length
|
|
|
|
|
+ },
|
|
|
|
|
+ choiceQuestionNum(): number {
|
|
|
|
|
+ return this.singleChoiceNum + this.multiChoiceNum
|
|
|
|
|
+ },
|
|
|
|
|
+ curQuestion(): QuestionSerializer {
|
|
|
|
|
+ return this.allQuestions[this.currentQuestionIndex]
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- components: {
|
|
|
|
|
- CountDown,
|
|
|
|
|
- CodePane,
|
|
|
|
|
- ChoicePane
|
|
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ choiceAnswers: {
|
|
|
|
|
+ deep: true,
|
|
|
|
|
+ handler: function(val: Array<{ index: number; answer: string }>) {
|
|
|
|
|
+ this.answeredChoices = val
|
|
|
|
|
+ .slice(0, this.singleChoiceNum + this.multiChoiceNum)
|
|
|
|
|
+ .map((value) => {
|
|
|
|
|
+ return { index: value.index, answered: value.answer !== '' }
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
leaveExam() {
|
|
leaveExam() {
|
|
@@ -184,15 +233,41 @@ export default Vue.extend({
|
|
|
this.$router.back()
|
|
this.$router.back()
|
|
|
},
|
|
},
|
|
|
nextQuestion(answer: String) {
|
|
nextQuestion(answer: String) {
|
|
|
- this.choiceAnswers.push(answer)
|
|
|
|
|
|
|
+ // this.choiceAnswers.push(answer)
|
|
|
this.isChoiceProblem = !this.isChoiceProblem
|
|
this.isChoiceProblem = !this.isChoiceProblem
|
|
|
|
|
+ this.currentQuestionIndex += 1
|
|
|
|
|
+ },
|
|
|
|
|
+ fetchData() {
|
|
|
|
|
+ this.examId = parseInt(this.$route.params.id)
|
|
|
|
|
+ console.log(this.examId)
|
|
|
|
|
+ getExamQuestions(this.examId)
|
|
|
|
|
+ .then(({ data }) => {
|
|
|
|
|
+ this.examQuestionsObject = data.res ?? {}
|
|
|
|
|
+ this.singleChoiceQuestions =
|
|
|
|
|
+ this.examQuestionsObject?.singleChoiceQuestions ?? []
|
|
|
|
|
+ this.multiChoiceQuestions =
|
|
|
|
|
+ this.examQuestionsObject?.multiChoiceQuestions ?? []
|
|
|
|
|
+ this.codeQuestions = this.examQuestionsObject?.codeQuestions ?? []
|
|
|
|
|
+ this.allQuestions = [
|
|
|
|
|
+ ...this.singleChoiceQuestions,
|
|
|
|
|
+ ...this.multiChoiceQuestions,
|
|
|
|
|
+ ...this.codeQuestions
|
|
|
|
|
+ ]
|
|
|
|
|
+ this.choiceAnswers = [
|
|
|
|
|
+ ...this.singleChoiceQuestions,
|
|
|
|
|
+ ...this.multiChoiceQuestions
|
|
|
|
|
+ ].map((value, index) => {
|
|
|
|
|
+ return { num: index + 1, answer: '' }
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(() => {
|
|
|
|
|
+ console.log('No data')
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- beforeMount() {}
|
|
|
|
|
- // beforeRouteLeave(to, from, next) {
|
|
|
|
|
- // this.exitDialog = true
|
|
|
|
|
- //
|
|
|
|
|
- // }
|
|
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.fetchData()
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|