|
|
@@ -3,7 +3,7 @@
|
|
|
<v-app-bar dense app class="indigo lighten-5">
|
|
|
<v-row>
|
|
|
<v-col>
|
|
|
- <span class="display-1">基础能力测试</span>
|
|
|
+ <span class="display-1">{{ examInfo.title }}</span>
|
|
|
</v-col>
|
|
|
<v-col class="d-inline-flex justify-end">
|
|
|
<count-down
|
|
|
@@ -30,7 +30,7 @@
|
|
|
class="overflow-auto flex-grow-1 pa-4 d-flex flex-column justify-space-around"
|
|
|
style="box-sizing: border-box;"
|
|
|
>
|
|
|
- <div column class="justify-space-between">
|
|
|
+ <div class="justify-space-between">
|
|
|
<div class="d-flex justify-center">
|
|
|
<h2>单选题</h2>
|
|
|
</div>
|
|
|
@@ -39,14 +39,14 @@
|
|
|
:key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
|
- :disabled="i.answered"
|
|
|
+ :disabled="currentQuestionIndex + 1 !== i.index && i.answered"
|
|
|
:color="currentQuestionIndex + 1 === i.index ? 'secondary' : ''"
|
|
|
@click="onSelectQuestion(i.index)"
|
|
|
>
|
|
|
{{ i.index }}
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
- <div column class="justify-space-between d-inline">
|
|
|
+ <div class="justify-space-between d-inline">
|
|
|
<div class="d-flex justify-center">
|
|
|
<h2>多选题</h2>
|
|
|
</div>
|
|
|
@@ -58,14 +58,14 @@
|
|
|
:key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
|
- :disabled="i.answered"
|
|
|
+ :disabled="currentQuestionIndex + 1 !== i.index && i.answered"
|
|
|
:color="currentQuestionIndex + 1 === i.index ? 'secondary' : ''"
|
|
|
@click="onSelectQuestion(i.index)"
|
|
|
>
|
|
|
{{ i.index }}
|
|
|
</v-btn>
|
|
|
</div>
|
|
|
- <div column class="justify-space-between">
|
|
|
+ <div class="justify-space-between">
|
|
|
<div class="d-flex justify-center">
|
|
|
<h2>代码题</h2>
|
|
|
</div>
|
|
|
@@ -74,7 +74,6 @@
|
|
|
:key="i.index"
|
|
|
class="ml-2 mt-2 pa-0 d-inline"
|
|
|
x-small
|
|
|
- :disabled="i.answered"
|
|
|
:color="currentQuestionIndex + 1 === i.index ? 'secondary' : ''"
|
|
|
@click="onSelectQuestion(i.index)"
|
|
|
>
|
|
|
@@ -140,18 +139,33 @@
|
|
|
<v-main class="indigo lighten-5 pa-0">
|
|
|
<v-container fluid class="pa-2" v-if="currentQuestionIndex >= 0">
|
|
|
<choice-pane
|
|
|
+ ref="choicePane"
|
|
|
v-if="isChoiceProblem"
|
|
|
- v-on:nextQuestion="nextQuestion"
|
|
|
+ @nextQuestion="nextQuestion"
|
|
|
+ @saveChoiceAnswer="saveChoiceAnswer"
|
|
|
:total-question-num="curTypeQuestionNum"
|
|
|
- :question="curChoice"
|
|
|
+ :question="curChoiceQuestion"
|
|
|
></choice-pane>
|
|
|
- <code-pane
|
|
|
- v-else
|
|
|
- v-on:nextQuestion="nextQuestion"
|
|
|
- :question="curCodeQuestion"
|
|
|
- :total-question-num="curTypeQuestionNum"
|
|
|
- ></code-pane>
|
|
|
+ <div v-else>
|
|
|
+ <!-- 用一个不显示的tabs,同时渲染所有的代码题面板,控制代码题的切换,使得代码切换保留已写代码-->
|
|
|
+ <v-tabs v-show="false" v-model="codeIndex">
|
|
|
+ <v-tab v-for="i in codeQuestionNum" :key="i"> {{ i }}</v-tab>
|
|
|
+ </v-tabs>
|
|
|
+ <v-tabs-items v-model="codeIndex">
|
|
|
+ <v-tab-item v-for="i in codeQuestionNum" :key="i">
|
|
|
+ <code-pane
|
|
|
+ :question="codeQuestions[i - 1]"
|
|
|
+ :total-question-num="curTypeQuestionNum"
|
|
|
+ @nextQuestion="nextQuestion"
|
|
|
+ @submitCode="saveSubmittedCode"
|
|
|
+ ></code-pane>
|
|
|
+ </v-tab-item>
|
|
|
+ </v-tabs-items>
|
|
|
+ </div>
|
|
|
</v-container>
|
|
|
+ <v-snackbar v-model="noticeUnfinished">
|
|
|
+ 还有题目未作答
|
|
|
+ </v-snackbar>
|
|
|
</v-main>
|
|
|
</div>
|
|
|
</template>
|
|
|
@@ -165,6 +179,7 @@ import {
|
|
|
ChoiceQuestionSerializer,
|
|
|
CodeQuestionSerializer,
|
|
|
ExamQuestionSerializer,
|
|
|
+ ExamSerializer,
|
|
|
QuestionSerializer
|
|
|
} from '@/api/types'
|
|
|
import { getExamById, getExamQuestions } from '@/api/exam'
|
|
|
@@ -181,9 +196,10 @@ export default Vue.extend({
|
|
|
exitDialog: false,
|
|
|
submitDialog: false,
|
|
|
submitted: false,
|
|
|
- currentTime: new Date().getTime(),
|
|
|
+ currentTime: 0,
|
|
|
+ examInfo: {} as ExamSerializer,
|
|
|
endTime: 0,
|
|
|
- choiceAnswers: [] as Array<{ num: number; answer: string }>, // TODO codeAnswers
|
|
|
+ choiceAnswers: [] as Array<{ index: number; answer: string }>,
|
|
|
examId: 0,
|
|
|
singleChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
|
|
|
multiChoiceQuestions: [] as Array<ChoiceQuestionSerializer>,
|
|
|
@@ -192,7 +208,9 @@ export default Vue.extend({
|
|
|
answeredChoices: [] as Array<{ index: number; answered: boolean }>,
|
|
|
answeredCodes: [] as Array<{ index: number; answered: boolean }>,
|
|
|
answerStatus: [] as Array<{ index: number; answered: boolean }>,
|
|
|
- currentQuestionIndex: -1
|
|
|
+ currentQuestionIndex: -1,
|
|
|
+ codeIndex: -1,
|
|
|
+ noticeUnfinished: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -221,7 +239,10 @@ export default Vue.extend({
|
|
|
choiceQuestionNum(): number {
|
|
|
return this.singleChoiceNum + this.multiChoiceNum
|
|
|
},
|
|
|
- curChoice(): ChoiceQuestionSerializer {
|
|
|
+ totalQuestionNum(): number {
|
|
|
+ return this.choiceQuestionNum + this.codeQuestionNum
|
|
|
+ },
|
|
|
+ curChoiceQuestion(): ChoiceQuestionSerializer {
|
|
|
if (!this.isChoiceProblem) {
|
|
|
return {} as ChoiceQuestionSerializer
|
|
|
}
|
|
|
@@ -232,14 +253,6 @@ export default Vue.extend({
|
|
|
this.currentQuestionIndex - this.singleChoiceNum
|
|
|
]
|
|
|
}
|
|
|
- },
|
|
|
- curCodeQuestion(): CodeQuestionSerializer {
|
|
|
- if (!this.isChoiceProblem) {
|
|
|
- return this.codeQuestions[
|
|
|
- this.currentQuestionIndex - this.choiceQuestionNum
|
|
|
- ]
|
|
|
- }
|
|
|
- return {} as CodeQuestionSerializer
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -252,14 +265,40 @@ export default Vue.extend({
|
|
|
return { index: value.index, answered: value.answer !== '' }
|
|
|
})
|
|
|
}
|
|
|
+ },
|
|
|
+ currentQuestionIndex(val) {
|
|
|
+ if (val > this.choiceQuestionNum) {
|
|
|
+ this.codeIndex = val - this.choiceQuestionNum
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- // 切换题目时,先保存答过的选择题的答案;提交代码后,保存提交的代码题答案
|
|
|
- saveAnswer(answer: string, lang?: string) {},
|
|
|
- onSelectQuestion(index: number) {
|
|
|
+ saveSubmittedCode(code: string, lang: string) {
|
|
|
+ const changedCodeQuestion = this.codeQuestions[this.codeIndex]
|
|
|
+ const changedCodeTuple =
|
|
|
+ changedCodeQuestion.lastCommitCodes?.find((val) => {
|
|
|
+ return val.lang === lang
|
|
|
+ }) ?? {}
|
|
|
+ changedCodeTuple.code = code
|
|
|
+ },
|
|
|
+ saveChoiceAnswer(answer: string | undefined) {
|
|
|
+ if (answer === undefined) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.choiceAnswers[this.currentQuestionIndex].answer = answer
|
|
|
+
|
|
|
+ if (answer !== '') {
|
|
|
+ this.answerStatus[this.currentQuestionIndex].answered = true
|
|
|
+ } else {
|
|
|
+ this.answerStatus[this.currentQuestionIndex].answered = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onSelectQuestion(target: number) {
|
|
|
// this.saveAnswer()
|
|
|
- this.currentQuestionIndex = index - 1
|
|
|
+ this.currentQuestionIndex = target - 1
|
|
|
+ if (!this.isChoiceProblem) {
|
|
|
+ this.codeIndex = target - 1 - this.choiceQuestionNum
|
|
|
+ }
|
|
|
},
|
|
|
leaveExam() {
|
|
|
this.exitDialog = false
|
|
|
@@ -267,42 +306,67 @@ export default Vue.extend({
|
|
|
},
|
|
|
submitAnswer() {
|
|
|
this.submitDialog = false
|
|
|
+
|
|
|
+ // if (
|
|
|
+ // this.answerStatus.find((value) => {
|
|
|
+ // return !value.answered
|
|
|
+ // }) !== undefined
|
|
|
+ // ) {
|
|
|
+ // this.noticeUnfinished = true
|
|
|
+ // return
|
|
|
+ // }
|
|
|
+
|
|
|
+ const answers = [
|
|
|
+ ...this.choiceAnswers.map((value) => {
|
|
|
+ return value.answer
|
|
|
+ })
|
|
|
+ ]
|
|
|
+
|
|
|
+ const codes = this.codeQuestions.map((value) => {
|
|
|
+ const tuples = value.lastCommitCodes ?? []
|
|
|
+ return JSON.stringify(tuples)
|
|
|
+ })
|
|
|
+
|
|
|
+ // TODO post
|
|
|
+ console.log(answers)
|
|
|
+ console.log(codes)
|
|
|
this.$router.back()
|
|
|
},
|
|
|
- nextQuestion(answer: string) {
|
|
|
- // this.saveAnswer(answer)
|
|
|
- this.currentQuestionIndex += 1
|
|
|
- },
|
|
|
- prevQuestion(answer: string) {
|
|
|
- // this.saveAnswer(answer)
|
|
|
- this.currentQuestionIndex -= 1
|
|
|
+ nextQuestion() {
|
|
|
+ // if (this.isChoiceProblem) {
|
|
|
+ // this.saveAnswer(answer.toString())
|
|
|
+ // }
|
|
|
+ do {
|
|
|
+ this.currentQuestionIndex =
|
|
|
+ ++this.currentQuestionIndex % this.totalQuestionNum
|
|
|
+ } while (this.answerStatus[this.currentQuestionIndex].answered)
|
|
|
},
|
|
|
fetchData() {
|
|
|
this.examId = parseInt(this.$route.params.id)
|
|
|
+
|
|
|
getExamById(this.examId).then(({ data }) => {
|
|
|
- this.endTime = Date.parse(data.res.endAt)
|
|
|
- console.log(this.endTime)
|
|
|
+ this.examInfo = data.res ?? {}
|
|
|
+ this.endTime = new Date().getTime() + 100
|
|
|
+ // this.endTime = Date.parse(this.examInfo.endAt ?? '')
|
|
|
+ this.currentTime = new Date().getTime()
|
|
|
})
|
|
|
|
|
|
getExamQuestions(this.examId)
|
|
|
.then(({ data }) => {
|
|
|
- const examQuestionsObject: ExamQuestionSerializer = data.res
|
|
|
+ const examQuestionsObject: ExamQuestionSerializer = data.res ?? {}
|
|
|
|
|
|
- this.singleChoiceQuestions = examQuestionsObject.singleChoiceQuestions?.map(
|
|
|
- (value, index) => {
|
|
|
- return { ...value, id: index + 1 }
|
|
|
- }
|
|
|
- )
|
|
|
- this.multiChoiceQuestions = examQuestionsObject.multiChoiceQuestions?.map(
|
|
|
- (value, index) => {
|
|
|
- return { ...value, id: index + 1 }
|
|
|
- }
|
|
|
- )
|
|
|
- this.codeQuestions = examQuestionsObject.codeQuestions?.map(
|
|
|
- (value, index) => {
|
|
|
- return { ...value, id: index + 1 }
|
|
|
- }
|
|
|
- )
|
|
|
+ this.singleChoiceQuestions =
|
|
|
+ examQuestionsObject.singleChoiceQuestions?.map((value, index) => {
|
|
|
+ return { ...value, index: index + 1 }
|
|
|
+ }) ?? []
|
|
|
+ this.multiChoiceQuestions =
|
|
|
+ examQuestionsObject.multiChoiceQuestions?.map((value, index) => {
|
|
|
+ return { ...value, index: index + 1 }
|
|
|
+ }) ?? []
|
|
|
+ this.codeQuestions =
|
|
|
+ examQuestionsObject.codeQuestions?.map((value, index) => {
|
|
|
+ return { ...value, index: index + 1 }
|
|
|
+ }) ?? []
|
|
|
|
|
|
this.allQuestions = [
|
|
|
...this.singleChoiceQuestions,
|
|
|
@@ -324,6 +388,7 @@ export default Vue.extend({
|
|
|
})
|
|
|
|
|
|
this.currentQuestionIndex = 0 // 表示数据初始化完成
|
|
|
+ this.codeIndex = -1
|
|
|
})
|
|
|
.catch(() => {
|
|
|
console.log('No data')
|