Parcourir la source

add ExamQuestionCard.vue

reghao il y a 7 mois
Parent
commit
f0f024a8f0
3 fichiers modifiés avec 333 ajouts et 16 suppressions
  1. 7 0
      src/router/exam.js
  2. 51 16
      src/views/exam/ExamQuestion.vue
  3. 275 0
      src/views/exam/ExamQuestionCard.vue

+ 7 - 0
src/router/exam.js

@@ -15,6 +15,7 @@ const ExamPaperPreview = () => import('views/exam/ExamPaperPreview')
 const ExamScoreIndex = () => import('views/exam/ExamScoreIndex')
 const ExamPaperResult = () => import('views/exam/ExamPaperResult')
 const ExamMarkIndex = () => import('views/exam/ExamMarkIndex')
+const ExamPaperCard = () => import('views/exam/ExamQuestionCard')
 
 export default {
   path: '/exam',
@@ -111,6 +112,12 @@ export default {
       name: 'ExamDashboard',
       component: ExamDashboard,
       meta: { needAuth: true }
+    },
+    {
+      path: '/exam/paper/card',
+      name: 'ExamPaperCard',
+      component: ExamPaperCard,
+      meta: { needAuth: true }
     }
   ]
 }

+ 51 - 16
src/views/exam/ExamQuestion.vue

@@ -274,26 +274,61 @@
         <el-button type="primary" @click="updateQuestion">确 定</el-button>
       </div>
     </el-dialog>
-    <el-dialog title="试题详情" :visible.sync="questionDetailDialog" width="50%" center>
-      <el-card>
-        <el-form :model="questionDetail">
-          <el-form-item label="所属科目" label-width="120px">
+    <el-dialog title="试题详情" :visible.sync="questionDetailDialog" width="70%" center>
+      <el-card :model="questionDetail">
+        <el-descriptions class="margin-top" :column="3" border>
+          <el-descriptions-item>
+            <template slot="label">
+              <i class="el-icon-user"></i>
+              所属科目
+            </template>
             <span> {{ questionDetail.subject }} </span>
-          </el-form-item>
-          <el-form-item label="试题类型" label-width="120px">
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template slot="label">
+              <i class="el-icon-mobile-phone"></i>
+              试题类型
+            </template>
             <span> {{ questionDetail.typeStr }} </span>
-          </el-form-item>
-          <el-form-item label="试题难度" label-width="120px">
+          </el-descriptions-item>
+          <el-descriptions-item>
+            <template slot="label">
+              <i class="el-icon-location-outline"></i>
+              试题难度
+            </template>
             <span> {{ questionDetail.level }} </span>
-          </el-form-item>
-          <el-divider />
-          <el-form-item label="试题内容" label-width="120px">
+          </el-descriptions-item>
+        </el-descriptions>
+        <el-descriptions class="margin-top" :column="1" border>
+          <el-descriptions-item>
+            <template slot="label">
+              <i class="el-icon-user"></i>
+              试题内容
+            </template>
             <span v-html="questionDetail.content" />
-          </el-form-item>
-          <el-form-item label="试题解析" label-width="120px">
+          </el-descriptions-item>
+        </el-descriptions>
+        <el-descriptions class="margin-top" :column="1" border>
+          <el-descriptions-item>
+            <template slot="label">
+              <i class="el-icon-user"></i>
+              试题解析
+            </template>
             <span v-html="questionDetail.analysis" />
-          </el-form-item>
-          <el-divider />
+          </el-descriptions-item>
+        </el-descriptions>
+        <el-divider/>
+        <div>
+          <span v-html="questionDetail.content" />
+          <el-radio-group v-model="radio">
+            <el-radio :label="1">A</el-radio>
+            <el-radio :label="2">B</el-radio>
+            <el-radio :label="3">C</el-radio>
+            <el-radio :label="4">D</el-radio>
+          </el-radio-group>
+        </div>
+        <el-divider/>
+        <el-form :model="questionDetail">
           <el-form-item v-if="questionDetail.type <= 7" label="试题选项" label-width="120px">
             <el-table :data="questionDetail.options" border style="width: 96%;margin-left: 40px;margin-top: 10px">
               <el-table-column label="正确答案" align="center">
@@ -316,7 +351,6 @@
               />
             </el-table>
           </el-form-item>
-
           <div v-if="questionDetail.children">
             <div v-for="item in questionDetail.children">
               <el-form :model="item">
@@ -442,6 +476,7 @@ export default {
   name: 'ExamQuestion',
   data() {
     return {
+      radio: '',
       // 屏幕宽度, 为了控制分页条的大小
       screenWidth: document.body.clientWidth,
       currentPage: 1,

+ 275 - 0
src/views/exam/ExamQuestionCard.vue

@@ -0,0 +1,275 @@
+<template>
+  <el-container>
+    <el-header height="220">
+      <el-row style="margin-top: 10px">
+        <el-button type="primary" icon="el-icon-upload" style="float: right; padding: 3px 0" plain @click="onSubmitPaper">
+          提交试卷
+        </el-button>
+      </el-row>
+    </el-header>
+    <el-main v-if="questionMap !== null">
+      <!-- 回答试题区域 -->
+      <div v-for="(values, key) in questionMap" :key="key">
+        <div v-if="key === '1'">
+          <h1>单项选择题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+            <el-radio-group
+              v-model="selectRadioArr[index1]"
+              @change="(val) => {
+                onRadioChange(val, item1)
+              }"
+            >
+              <el-radio :label="1">A</el-radio>
+              <el-radio :label="2">B</el-radio>
+              <el-radio :label="3">C</el-radio>
+              <el-radio :label="4">D</el-radio>
+            </el-radio-group>
+          </div>
+          <el-divider />
+        </div>
+        <div v-else-if="key === '2' || key === '3'">
+          <h1>多项选择题/不定项选择题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+            <el-checkbox-group
+              v-model="checkList"
+              @change="(val) => {
+                onCheckboxChange(val, item1)
+              }"
+            >
+              <el-checkbox label="1">A</el-checkbox>
+              <el-checkbox label="2">B</el-checkbox>
+              <el-checkbox label="3">C</el-checkbox>
+              <el-checkbox label="4">D</el-checkbox>
+            </el-checkbox-group>
+          </div>
+          <el-divider />
+        </div>
+        <div v-else-if="key === '4'">
+          <h1>判断题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+            <el-radio-group
+              v-model="judgeRadioArr[item1.pos]"
+              @change="(val) => {
+                onRadioChange(val, item1)
+              }"
+            >
+              <el-radio :label="1">正确</el-radio>
+              <el-radio :label="2">错误</el-radio>
+            </el-radio-group>
+          </div>
+          <el-divider />
+        </div>
+        <div v-else-if="key === '5'">
+          <h1>填空题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+            <el-input
+              v-model="inputContent"
+              type="text"
+              placeholder="请输入答案"
+              style="width: 20%; padding-right: 2px"
+              @blur="(val) => {
+                onInputBlur(val, item1)
+              }"
+            />
+          </div>
+          <el-divider />
+        </div>
+        <div v-else-if="key === '6'">
+          <h1>问答题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+            <editor id="tinymce" v-model="editorContent" :init="init" style="width: 50%" />
+          </div>
+          <el-divider />
+        </div>
+        <div v-else-if="key === '8'">
+          <h1>组合题</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+          </div>
+          <el-divider />
+        </div>
+        <div v-else>
+          <h1>未知试题类型</h1>
+          <div v-for="(item1, index1) in values" :key="index1">
+            <span v-html="item1.questionContent" />
+          </div>
+          <el-divider />
+        </div>
+      </div>
+    </el-main>
+  </el-container>
+</template>
+
+<script>
+import tinymce from 'tinymce/tinymce'
+import 'tinymce/themes/silver/theme'
+import 'tinymce/plugins/image'
+import 'tinymce/plugins/code'
+import 'tinymce/skins/content/default/content.css'
+import 'tinymce/themes/silver/theme.min.js'
+import 'tinymce/icons/default/icons'
+import Editor from '@tinymce/tinymce-vue'
+
+import { getPaper } from '@/api/exam'
+
+export default {
+  name: 'ExamQuestionCard',
+  components: { Editor },
+  data() {
+    return {
+      radioMap: new Map(),
+      // 单选题
+      selectRadioArr: [],
+      // 判断题
+      judgeRadioArr: [],
+      radio: '',
+      radio1: '',
+      checkList: [],
+      inputContent: '',
+      editorContent: '',
+      // 屏幕宽度, 为了控制分页条的大小
+      screenWidth: document.body.clientWidth,
+      // **********************************************************************
+      init: {
+        language_url: '/tinymce/zh_CN.js',
+        language: 'zh_CN',
+        skin_url: '/tinymce/skins/ui/oxide',
+        height: 300,
+        external_plugins: {
+          'mathjax': '/tinymce/mathjax/plugin.min.js'
+        },
+        mathjax: {
+          lib: '/tinymce/mathjax/tex-mml-chtml.js'
+        },
+        plugins: 'image code',
+        toolbar: 'mathjax bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | code | removeformat',
+        branding: false,
+        init_instance_callback: (editor) => {
+          editor.on('focus', (e) => {
+            this.$message.info('editor focus')
+          })
+          editor.on('blur', (e) => {
+            var content = editor.getContent()
+            this.onEditorBlur(content)
+            // this.$message.info('editor lost focus')
+          })
+        }
+      },
+      // **********************************************************************
+      // 试题类型
+      questionTypeList: [
+        { id: 1, name: '单选题' },
+        { id: 2, name: '多选题' },
+        { id: 3, name: '不定项选择题' },
+        { id: 4, name: '判断题' },
+        { id: 5, name: '填空题' },
+        { id: 6, name: '问答题' },
+        { id: 7, name: '理解题' },
+        { id: 8, name: '組题' }
+      ],
+      examInfo: null,
+      questionMap: null,
+      answerList: [
+        {
+          questionId: '',
+          answer: []
+        }
+      ],
+      answerMap: new Map()
+    }
+  },
+  created() {
+    document.title = '试卷详情'
+
+    const paperId = 3
+    this.getPaperDetail(paperId)
+  },
+  methods: {
+    renderByMathjax() {
+      // tinymce 的 mathjax 插件生成的 latex 格式公式放在 className 为 math-tex 的 span 标签内
+      const className = 'math-tex'
+      this.$nextTick(function() {
+        if (this.MathJax.isMathjaxConfig) {
+          this.MathJax.initMathjaxConfig()
+        }
+        this.MathJax.MathQueue1(className)
+      })
+    },
+    getPaperDetail(paperId) {
+      getPaper(paperId).then((resp) => {
+        if (resp.code === 0) {
+          const respData = resp.data
+          /* this.examInfo.paperId = respData.paperId
+          this.examInfo.name = respData.name
+          this.examInfo.description = respData.description
+          this.examInfo.duration = respData.duration
+          this.examInfo.totalScore = respData.totalScore*/
+
+          this.questionMap = respData.questionMap
+          for (var key in this.questionMap) {
+            for (var item of this.questionMap[key]) {
+              this.answerMap.set(item.questionId, {
+                questionId: item.questionId,
+                answers: []
+              })
+            }
+          }
+          /* this.questionList = respData.questions
+          // 重置问题的顺序 单选 ->  -> 判断 -> 简答
+          this.questionList = this.questionList.sort(function(a, b) {
+            return a.questionType - b.questionType
+          })*/
+          this.renderByMathjax()
+        } else {
+          this.$message.error(resp.msg)
+        }
+      })
+    },
+    onSubmitPaper() {
+      this.$confirm('当前试题暂未做完, 是否继续提交o(╥﹏╥)o ?', 'Tips', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.$notify({
+          title: 'Tips',
+          message: '试卷已提交, 继续加油! *^▽^*',
+          type: 'success',
+          duration: 2000
+        })
+      }).catch(() => {
+        this.$notify({
+          title: 'Tips',
+          message: '提交已取消',
+          type: 'info',
+          duration: 2000
+        })
+      })
+    },
+    onRadioChange(val, item) {
+      this.$message.info('change event: ' + val + ' -> ' + item.questionId)
+      this.$set(this.radioMap, item.questionId, val)
+      this.selectRadioArr[item.pos - 1] = val
+      this.answerMap.get(item.questionId).answers[0] = val
+      console.log(this.answerMap)
+    },
+    onCheckboxChange(val, item) {
+      this.$message.info('change event: ' + val + ' -> ' + item.questionId)
+    },
+    onInputBlur(val, item) {
+      this.$message.info('blur event: ' + val + ' -> ' + item.questionId)
+    },
+    onEditorBlur(val) {
+      this.$message.info('editor blur -> ' + this.editorContent)
+    }
+  }
+}
+</script>
+
+<style>
+</style>