|
|
@@ -1,122 +1,225 @@
|
|
|
<template>
|
|
|
<v-container>
|
|
|
- <v-card>
|
|
|
- <!-- <v-card-title>已选题目</v-card-title>-->
|
|
|
- <!-- <v-list class="px-10 flex">-->
|
|
|
- <!-- <v-list-item-group multiple>-->
|
|
|
- <!-- <v-divider></v-divider>-->
|
|
|
- <!-- <template v-for="question in selectedQuestions">-->
|
|
|
- <!-- <v-list-item :key="question.id" :value="question.id">-->
|
|
|
- <!-- <template v-slot:default="{ active }">-->
|
|
|
- <!-- <v-list-item-action>-->
|
|
|
- <!-- <v-checkbox hide-details :input-value="active"> </v-checkbox>-->
|
|
|
- <!-- </v-list-item-action>-->
|
|
|
- <!-- <v-list-item-content>-->
|
|
|
- <!-- <v-list-item-title class="text-wrap">-->
|
|
|
- <!-- {{ question.stem }}</v-list-item-title-->
|
|
|
- <!-- >-->
|
|
|
- <!-- </v-list-item-content>-->
|
|
|
- <!-- </template>-->
|
|
|
- <!-- </v-list-item>-->
|
|
|
- <!-- <v-divider :key="' ' + question.id"></v-divider>-->
|
|
|
- <!-- </template>-->
|
|
|
- <!-- </v-list-item-group>-->
|
|
|
- <!-- </v-list>-->
|
|
|
- <!-- <v-card-title>题目列表</v-card-title>-->
|
|
|
- <!-- <v-list class="px-10 flex">-->
|
|
|
- <!-- <v-list-item-group v-model="selectedId" multiple>-->
|
|
|
- <!-- <v-divider></v-divider>-->
|
|
|
- <!-- <template v-for="question in questions">-->
|
|
|
- <!-- <v-list-item :key="question.id" :value="question.id">-->
|
|
|
- <!-- <template v-slot:default="{ active }">-->
|
|
|
- <!-- <v-list-item-action>-->
|
|
|
- <!-- <v-checkbox hide-details :input-value="active"> </v-checkbox>-->
|
|
|
- <!-- </v-list-item-action>-->
|
|
|
- <!-- <v-list-item-content>-->
|
|
|
- <!-- <v-list-item-title class="text-wrap">-->
|
|
|
- <!-- {{ question.stem }}</v-list-item-title-->
|
|
|
- <!-- >-->
|
|
|
- <!-- </v-list-item-content>-->
|
|
|
- <!-- </template>-->
|
|
|
- <!-- </v-list-item>-->
|
|
|
- <!-- <v-divider :key="' ' + question.id"></v-divider>-->
|
|
|
- <!-- </template>-->
|
|
|
- <!-- </v-list-item-group>-->
|
|
|
- <!-- <v-card-actions>-->
|
|
|
- <!-- <v-btn color="primary" @click="fetchData">下一页</v-btn>-->
|
|
|
- <!-- </v-card-actions>-->
|
|
|
- <!-- </v-list>-->
|
|
|
- <v-data-table
|
|
|
- v-model="selectedId"
|
|
|
- item-key="id"
|
|
|
- show-select
|
|
|
- :headers="headers"
|
|
|
- :items="questions"
|
|
|
- show-expand
|
|
|
- style="width: 50vw"
|
|
|
- class="text-wrap"
|
|
|
- >
|
|
|
- <template v-slot:expanded-item="{ headers, item }">
|
|
|
- <td :colspan="headers.length">
|
|
|
- {{ item.stem }}
|
|
|
- </td>
|
|
|
- </template>
|
|
|
- </v-data-table>
|
|
|
- </v-card>
|
|
|
+ <v-card-title>已选题目</v-card-title>
|
|
|
+ <v-data-table
|
|
|
+ item-key="id"
|
|
|
+ :headers="selectedHeaders"
|
|
|
+ :items="selectedQuestions"
|
|
|
+ no-data-text="空"
|
|
|
+ >
|
|
|
+ <template v-slot:item.score="{ item }">
|
|
|
+ <div class="d-flex">
|
|
|
+ <span class="align-self-center mx-1">{{ item.score }}</span>
|
|
|
+ <span class="d-flex flex-column">
|
|
|
+ <v-icon small @click="increasePoints(item)">
|
|
|
+ mdi-arrow-up-bold
|
|
|
+ </v-icon>
|
|
|
+ <v-icon small @click="decreasePoints(item)">
|
|
|
+ mdi-arrow-down-bold
|
|
|
+ </v-icon>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-slot:item.actions="{ item }">
|
|
|
+ <v-icon @click="deleteItem(item)">
|
|
|
+ mdi-delete
|
|
|
+ </v-icon>
|
|
|
+ </template>
|
|
|
+ <template v-slot:item.stem="{ item }">
|
|
|
+ <markdown-text :raw="item.stem"></markdown-text>
|
|
|
+ </template>
|
|
|
+ </v-data-table>
|
|
|
+ <v-row class="ma-0 mt-5" justify="center">
|
|
|
+ <v-btn class="primary mx-2" @click="onSubmitManualPaper">确认调整</v-btn>
|
|
|
+ <v-btn class="secondary mx-2" @click="onLeave">返回</v-btn>
|
|
|
+ </v-row>
|
|
|
+ <v-row class="mx-2 mt-5" align="center">
|
|
|
+ <v-col cols="3">
|
|
|
+ <v-text-field v-model="stem" label="根据题目内容查找"></v-text-field>
|
|
|
+ </v-col>
|
|
|
+ <v-col cols="3">
|
|
|
+ <v-text-field v-model="tags" label="标签"></v-text-field>
|
|
|
+ </v-col>
|
|
|
+ <v-col cols="3">
|
|
|
+ <v-text-field v-model="knowledgeName" label="知识点"></v-text-field>
|
|
|
+ </v-col>
|
|
|
+ <v-col cols="1">
|
|
|
+ <v-btn class="primary mb-4 info" @click="onSearch">搜索</v-btn>
|
|
|
+ </v-col>
|
|
|
+ </v-row>
|
|
|
+
|
|
|
+ <v-card-title>试题列表</v-card-title>
|
|
|
+ <v-data-table
|
|
|
+ v-model="selectedQuestions"
|
|
|
+ item-key="id"
|
|
|
+ show-select
|
|
|
+ :headers="headers"
|
|
|
+ :items="questions"
|
|
|
+ show-expand
|
|
|
+ class="text-wrap"
|
|
|
+ :loading="loading"
|
|
|
+ @item-selected="onSelectQuestion"
|
|
|
+ @toggle-select-all="onToggleSelectAll"
|
|
|
+ hide-default-footer
|
|
|
+ :page.sync="pageNum"
|
|
|
+ >
|
|
|
+ <template v-slot:expanded-item="{ headers, item }">
|
|
|
+ <td :colspan="headers.length">
|
|
|
+ <markdown-text :raw="item.stem"></markdown-text>
|
|
|
+ </td>
|
|
|
+ </template>
|
|
|
+ </v-data-table>
|
|
|
+ <v-pagination
|
|
|
+ total-visible="5"
|
|
|
+ class="my-2"
|
|
|
+ :length="Math.ceil(totalNum / pageSize)"
|
|
|
+ v-model="pageNum"
|
|
|
+ @input="changePage"
|
|
|
+ ></v-pagination>
|
|
|
+ <v-snackbar v-model="selectQuestionsSuccess" top color="info">
|
|
|
+ 设置试题成功
|
|
|
+ </v-snackbar>
|
|
|
</v-container>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
import Vue, { PropType } from 'vue'
|
|
|
-import { QuestionSerializer, ID } from '@/api/types'
|
|
|
+import { QuestionSerializer } from '@/api/types'
|
|
|
+import { getQuestionList } from '@/api/question'
|
|
|
+import { questionTypeToText } from '@/utils/common'
|
|
|
+import MarkdownText from '@/views/exam/components/MarkdownText.vue'
|
|
|
+import { addExamPaperQuestions } from '@/api/exam'
|
|
|
+
|
|
|
+interface Question extends QuestionSerializer {
|
|
|
+ typeText: string
|
|
|
+ score: number
|
|
|
+}
|
|
|
|
|
|
export default Vue.extend({
|
|
|
name: 'QuestionList',
|
|
|
- props: {},
|
|
|
+ props: {
|
|
|
+ sampleQuestions: {
|
|
|
+ type: Array as PropType<Array<QuestionSerializer>>
|
|
|
+ },
|
|
|
+ questionAndScore: {
|
|
|
+ type: Object
|
|
|
+ }
|
|
|
+ },
|
|
|
+ components: {
|
|
|
+ MarkdownText
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
- questions: [] as Array<QuestionSerializer>,
|
|
|
- selectedId: [] as Array<ID>,
|
|
|
- selectedQuestions: [] as Array<QuestionSerializer>,
|
|
|
+ questions: [] as Array<Question>,
|
|
|
+ selectedQuestions: [] as Array<Question>,
|
|
|
+ tags: '',
|
|
|
+ knowledgeName: '',
|
|
|
+ stem: '',
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ totalNum: 0,
|
|
|
+ loading: true,
|
|
|
+ selectQuestionsSuccess: false,
|
|
|
headers: [
|
|
|
- { text: '技能点', value: 'skillId' },
|
|
|
- { text: '知识点', value: 'knowledgeId' },
|
|
|
- // { text: '题干', value: 'stem', sortable: false },
|
|
|
- { text: '题干', value: 'data-table-expand' }
|
|
|
+ { text: '题目类型', value: 'typeText' },
|
|
|
+ { text: '关键词', value: 'keyPoints', sortable: false },
|
|
|
+ { text: '知识点', value: 'knowledgeId', sortable: false },
|
|
|
+ { text: '标签', value: 'tags', sortable: false },
|
|
|
+ { text: '', value: 'data-table-expand' }
|
|
|
+ ],
|
|
|
+ selectedHeaders: [
|
|
|
+ { text: '分值', value: 'score', width: 100 },
|
|
|
+ { text: '操作', value: 'actions', sortable: false, width: 100 },
|
|
|
+ { text: '题干', value: 'stem', sortable: false }
|
|
|
]
|
|
|
}
|
|
|
},
|
|
|
- watch: {
|
|
|
- selectedId: {
|
|
|
- deep: true,
|
|
|
- handler: function(newVal: Array<ID>, oldVal: Array<ID>): void {
|
|
|
- if (newVal.length > oldVal.length) {
|
|
|
- const changedId = newVal[newVal.length - 1]
|
|
|
- const changeQuestion = this.questions.find((val) => {
|
|
|
- return val.id === changedId
|
|
|
- })
|
|
|
- if (changeQuestion !== undefined) {
|
|
|
- this.selectedQuestions.push(changeQuestion)
|
|
|
- }
|
|
|
- } else {
|
|
|
- const changeId = oldVal.filter((val) => {
|
|
|
- return !newVal.find((value) => {
|
|
|
- return value === val
|
|
|
- })
|
|
|
- })[0]
|
|
|
- this.selectedQuestions = this.selectedQuestions.filter((val) => {
|
|
|
- return val.id !== changeId
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
created() {
|
|
|
this.fetchData()
|
|
|
},
|
|
|
- mounted() {},
|
|
|
+ mounted() {
|
|
|
+ this.selectedQuestions = this.sampleQuestions.map((val) => {
|
|
|
+ return {
|
|
|
+ ...val,
|
|
|
+ score: this.questionAndScore[val.id] ?? 3,
|
|
|
+ typeText: questionTypeToText(val.type)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
methods: {
|
|
|
- fetchData() {}
|
|
|
+ fetchData() {
|
|
|
+ getQuestionList(
|
|
|
+ { pageSize: this.pageSize, pageNum: this.pageNum },
|
|
|
+ this.stem,
|
|
|
+ this.tags,
|
|
|
+ this.knowledgeName
|
|
|
+ ).then(({ data }) => {
|
|
|
+ this.questions = data.result.questionStemList.map((val) => {
|
|
|
+ return { ...val, typeText: questionTypeToText(val.type), score: 5 }
|
|
|
+ })
|
|
|
+ this.totalNum = data.result.totalNum
|
|
|
+ this.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ deleteItem(item: Question) {
|
|
|
+ let selectedIndex = this.selectedQuestions.indexOf(item)
|
|
|
+ this.selectedQuestions.splice(selectedIndex, 1)
|
|
|
+ },
|
|
|
+ increasePoints(item: Question) {
|
|
|
+ let selectedIndex = this.selectedQuestions.indexOf(item)
|
|
|
+ this.selectedQuestions[selectedIndex].score++
|
|
|
+ },
|
|
|
+ decreasePoints(item: Question) {
|
|
|
+ let selectedIndex = this.selectedQuestions.indexOf(item)
|
|
|
+ if (this.selectedQuestions[selectedIndex].score > 0)
|
|
|
+ this.selectedQuestions[selectedIndex].score--
|
|
|
+ },
|
|
|
+ onSelectQuestion(event: { item: Question; value: boolean }) {
|
|
|
+ if (event.value) {
|
|
|
+ if (
|
|
|
+ this.selectedQuestions.filter((val) => {
|
|
|
+ return val.id === event.item.id
|
|
|
+ }).length === 0
|
|
|
+ ) {
|
|
|
+ this.selectedQuestions.push(event.item)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.selectedQuestions = this.selectedQuestions.filter((val) => {
|
|
|
+ return val.id !== event.item.id
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onToggleSelectAll(event: { items: any[]; value: boolean }) {
|
|
|
+ event.items.forEach((val) => {
|
|
|
+ this.onSelectQuestion({ item: val, value: event.value })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onSubmitManualPaper() {
|
|
|
+ let examId = this.$route.params.examId
|
|
|
+
|
|
|
+ let idAndScore = new Map()
|
|
|
+ this.selectedQuestions.forEach((val) => {
|
|
|
+ idAndScore.set(val.id, val.score)
|
|
|
+ })
|
|
|
+
|
|
|
+ addExamPaperQuestions(examId, Object.fromEntries(idAndScore)).then(() => {
|
|
|
+ this.selectQuestionsSuccess = true
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$router.push({ name: 'teacher-exam-details' })
|
|
|
+ }, 1000)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ changePage() {
|
|
|
+ this.loading = true
|
|
|
+ this.fetchData()
|
|
|
+ },
|
|
|
+ onSearch() {
|
|
|
+ this.pageNum = 1
|
|
|
+ this.fetchData()
|
|
|
+ },
|
|
|
+ onLeave() {
|
|
|
+ this.$emit('leave')
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
</script>
|