Browse Source

精准ai助学

shilipojs 2 years ago
parent
commit
58323b5870

+ 2 - 1
src/components/MxPaper/mx-question-content.vue

@@ -62,7 +62,8 @@ export default {
     deep: {
       type: Number,
       default: 0
-    }
+    },
+
   },
   computed: {
     disabled() {

+ 5 - 1
src/views/accurateTeaching/accurateAi/microVideo/index.vue

@@ -6,7 +6,7 @@
       ></mx-condition>
     </el-card>
     <el-card class="box-card">
-      <mx-table :prop-defines="propDefines" :rows="rows">
+      <mx-table :prop-defines="propDefines" :rows="rows" v-loading="loading">
         <template #play="{row}">
           <el-button type="text" icon="el-icon-video-camera" @click="handleVideoPlay(row)">
             播放
@@ -39,6 +39,7 @@ export default {
         pageNum: 1,
         pageSize: 20
       },
+      loading:false,
       rows:[],
       propDefines:{
         resourcesName:{
@@ -71,6 +72,7 @@ export default {
       this.videoDialog = true
     },
     getList() {
+      this.loading = true
       getAiSubjectVideos(
         {
           ...this.pageForm,
@@ -82,6 +84,8 @@ export default {
         })
         this.total = res.total
         console.log(res)
+      }).finally(_ => {
+        this.loading = false
       })
     },
     togglePage(){

+ 19 - 4
src/views/accurateTeaching/accurateAi/practise/index.vue

@@ -6,9 +6,9 @@
       ></mx-condition>
     </el-card>
     <el-card class="box-card">
-      <mx-table :prop-defines="propDefines" :rows="rows">
+      <mx-table :prop-defines="propDefines" :rows="rows" v-loading="loading">
         <template #title="{row}">
-          <div v-html="row.title"></div>
+          <mx-question-content :options="questionOptions(row)"></mx-question-content>
         </template>
         <template #temp="{row}">
           <el-button type="text" icon="el-icon-view" @click="questionView(row)">查看详情</el-button>
@@ -22,7 +22,7 @@
       />
     </el-card>
     <el-dialog :title="'来源于'+currentQuestion.knowledgeName" :visible.sync="dialogVisible" v-if="dialogVisible" width="60%">
-      <analysis :questionId="currentQuestion.questionId" :examineeId="currentQuestion.examineeId" :wrongMode="false"
+      <analysis :questionId="currentQuestion.questionId" :examineeType="3" :examineeId="currentQuestion.examineeId" :wrongMode="false"
                 :lockAnswerInSolving="true"></analysis>
     </el-dialog>
   </div>
@@ -32,15 +32,18 @@ import MxSearchGroup from '@/components/MxSearch/mx-search-group'
 import MxCondition from '@/components/MxCondition/mx-condition'
 import { getAiSubjectPapers } from '@/api/webApi/webVideo'
 import analysis from '@/views/evaluating/components/analysis'
+import MxQuestionContent from '@/components/MxPaper/mx-question-content'
 
 export default {
-  components: { MxSearchGroup, MxCondition,analysis},
+  components: { MxSearchGroup, MxCondition,analysis,    MxQuestionContent,
+  },
   data() {
     return {
       pageForm: {
         pageNum: 1,
         pageSize: 16
       },
+      loading:false,
       rows:[],
       dialogVisible:false,
       propDefines:{
@@ -78,12 +81,22 @@ export default {
   methods: {
     handleInvalidQuery() {
 
+    },
+    questionOptions(row) {
+      return {
+        question: row,
+        allowAnswer: false,
+        allowScore: false,
+        examineeType: '',
+        paperOptions: null
+      }
     },
     questionView(row) {
       this.currentQuestion = row;
       this.dialogVisible = true;
     },
     getList() {
+      this.loading = true
       getAiSubjectPapers({
         ...this.pageForm,
         subjectId:this.queryParams.v2Subject
@@ -94,6 +107,8 @@ export default {
         })
         this.total  = res.total
         console.log(res)
+      }).finally(_ => {
+        this.loading = false
       })
     },
     togglePage(){

+ 9 - 2
src/views/accurateTeaching/commonAi/microVideo/index.vue

@@ -10,7 +10,7 @@
         <mx-search-group justify="end" :span="6" v-model="sectionName" placeholder="请输入搜索内容" @search="getList">
         </mx-search-group>
       </div>
-      <div class="video_content" v-if="videoList.length">
+      <div class="video_content" v-if="total" v-loading="loading">
         <el-row :span="24">
           <el-col
             :span="6"
@@ -45,7 +45,7 @@
           @pagination="getList"
         />
       </div>
-      <evaluation-empty v-else/>
+      <evaluation-empty v-if="!total && isSearch"/>
     </el-card>
   </div>
 </template>
@@ -62,12 +62,15 @@ export default {
         pageNum: 1,
         pageSize: 16
       },
+      loading:true,
+      isSearch:false,
       videoList: [],
       sectionName: '',
       queryParams: {
         videoTypeFixed: 0,
         videoCourseFixed: ''
       },
+      total:0,
       requireFields: ['videoCourseFixed']
     }
   },
@@ -87,6 +90,7 @@ export default {
 
     },
     getList() {
+      this.loading = true
       getAiAdStudyVideoList({
         course: this.queryParams.videoCourseFixed,
         sectionName: this.sectionName,
@@ -94,6 +98,9 @@ export default {
       }).then(res => {
         this.videoList = res.rows
         this.total = res.total
+        this.isearch = true
+      }).finally(_ => {
+        this.loading = false
       })
     },
     handleQuery() {

+ 9 - 3
src/views/accurateTeaching/commonAi/practise/index.vue

@@ -5,12 +5,12 @@
                     @invalid="handleInvalidQuery"
       ></mx-condition>
     </el-card>
-    <el-card class="box-card">
+    <el-card class="box-card" v-loading="loading">
       <div slot="header">
         <mx-search-group  justify="end" :span="6" v-model="sectionName" placeholder="请输入搜索内容" @search="getList">
         </mx-search-group>
       </div>
-      <div v-if="queList.length">
+      <div v-if="total">
         <div class="que_item" v-for="(item, index) in queList" :key="item.id">
           <div class="que_content">
             <div class="que-content-title">
@@ -58,7 +58,7 @@
           @pagination="getList"
         />
       </div>
-      <evaluation-empty v-else/>
+      <evaluation-empty v-if="!total && isSearch"/>
     </el-card>
   </div>
 </template>
@@ -75,6 +75,8 @@ export default {
         pageNum: 1,
         pageSize: 10
       },
+      loading:false,
+      isSearch:false,
       queList:[],
       sectionName: '',
       queryParams: {
@@ -95,6 +97,7 @@ export default {
       }
     },
     getList() {
+      this.loading = true
       getAiAdStudyQuestionList({
         subjectId:this.queryParams.v2Subject,
         searchTerm:this.sectionName,
@@ -102,6 +105,9 @@ export default {
       }).then(res => {
         this.total = res.total
         this.queList = res.rows
+        this.isSearch = true
+      }).finally(_ => {
+        this.loading = false
       })
     },
     handleQuery() {

+ 648 - 643
src/views/evaluating/components/analysis.vue

@@ -1,643 +1,648 @@
-<template>
-  <div class="answer_main" id="title">
-    <div class="">
-      <!-- 大题 -->
-      <div style="display: flex; justify-content: flex-start">
-        <div>{{ currentQuestion.seq || 1 }}、</div>
-        <div class="answer_main_title" style="flex: 1" v-html="currentQuestion.title"></div>
-      </div>
-      <!-- 小题 -->
-      <div style="padding-left: 50px" v-if="currentQuestion.subQuestions">
-        <div style="margin-bottom: 15px" v-for="(subItem, ix) in currentQuestion.subQuestions" :key="ix">
-          <div v-html="ix + 1 + '、' + subItem.title"></div>
-          <template v-if="subItem.options&&subItem.options.length">
-            <div style="margin-top: 20px">
-              <div v-for="(itemOpt, idx) in subItem.options" :key="idx">
-                <div style="margin-bottom: 15px" v-html="selectOpt[idx] + ' 、 ' + itemOpt"></div>
-              </div>
-            </div>
-          </template>
-        </div>
-      </div>
-    </div>
-    <div>
-      <template v-if="currentQuestion.typeId == 1">
-        <div style="margin-top: 20px">
-          <div v-for="(itemOpt, idx) in currentQuestion.options" :key="idx">
-            <template v-if="dataDetail.state == 3 || dataDetail.state == 4">
-              <!-- 答题 -->
-              <el-radio style="margin-bottom: 15px" v-model="currentQuestion.answer" :label="selectOpt[idx]" border size="medium">{{ selectOpt[idx] + " 、 "
-                }}<span style="white-space: normal" v-html="itemOpt"></span></el-radio>
-            </template>
-            <template v-else>
-              <!-- 查看 -->
-              <el-radio-group v-model="currentQuestion.answer">
-                <el-radio style="margin-bottom: 15px" :class="{
-                  'is-checked' : currentQuestion.answers[0].includes(selectOpt[idx]),
-                  'is-error': currentQuestion.answer.includes(selectOpt[idx]) && !currentQuestion.answers[0].includes(selectOpt[idx])
-                }" :label="selectOpt[idx]" disabled border size="medium">{{ selectOpt[idx] + " 、 "
-                }}<span style="white-space: normal" v-html="itemOpt"></span></el-radio>
-              </el-radio-group>
-              <!--  currentQuestion.answers[0] == selectOpt[idx] 表示正确答案  红色-->
-              <!-- currentQuestion.answer== selectOpt[idx] && currentQuestion.answers[0]!= selectOpt[idx] 表示当前答案 蓝色-->
-            </template>
-          </div>
-        </div>
-      </template>
-      <template v-if="currentQuestion.typeId == 3">
-        <div style="margin-top: 20px" id="dati">
-          <!-- 遍历客观题的答题项 -->
-          <div v-for="(itemOpt, idx) in currentQuestion.options" :key="idx">
-            <!-- todo 只在state为3和4的时候可以做题 -->
-            <template v-if="
-                (dataDetail.state == 3 ||
-                dataDetail.state == 4 ||
-                dataDetail.state == 7)&& isAnswer
-
-              ">
-              <!-- 答题 -->
-              <el-checkbox-group v-model="currentQuestion.answer" @change="changeCheckbox">
-                <el-checkbox style="margin-bottom: 15px" :label="selectOpt[idx]" border size="medium">{{ selectOpt[idx] + ' 、 '
-                }}<span style="white-space: normal" v-html="itemOpt"></span></el-checkbox>
-              </el-checkbox-group>
-            </template>
-            <template v-else>
-              <!-- 查看 -->
-              <el-checkbox-group v-model="currentQuestion.answer">
-                <el-checkbox v-if="currentQuestion.answer.length" style="margin-bottom: 15px" :class="{
-                  'is-checked' : currentQuestion.answers[0].includes(selectOpt[idx]),
-                  'is-error': currentQuestion.answer.includes(selectOpt[idx]) && !currentQuestion.answers[0].includes(selectOpt[idx])
-                }" :label="selectOpt[idx]" disabled border size="medium">{{ selectOpt[idx] + ' 、 '
-                }}<span style="white-space: normal" v-html="itemOpt"></span></el-checkbox>
-              </el-checkbox-group>
-            </template>
-          </div>
-        </div>
-      </template>
-      <template>
-        <div class="answer_main_btn">
-          <el-button v-if="dataDetail.state == 3 || dataDetail.state == 4" :type="solvingType == 1 ? 'primary' : ''" @click="answerFunc(1)">手动答题
-          </el-button>
-          <el-button v-if="dataDetail.state == 3 || dataDetail.state == 4" :type="solvingType == 2 ? 'primary' : ''" @click="answerFunc(2)"><i class="el-icon-camera-solid"></i>拍照上传
-          </el-button>
-          <el-button v-if="dataDetail.state == 5" :type="solvingType == 3 ? 'primary' : ''" @click="answerFunc(3)">
-            解析
-          </el-button>
-          <el-button v-if="canScore && dataDetail.state == 5" :type="solvingType == 4 ? 'primary' : ''" @click="answerFunc(4)">
-            计分
-          </el-button>
-          <span v-if="dataDetail.state != 3 && dataDetail.state != 4 && showScore" class="font_color_brown">得分:{{ currentQuestion.score || 0 }}分</span>
-        </div>
-        <div class="upload_container" v-loading="loading">
-          <template v-if="solvingType == 1">
-            <el-input type="textarea" :rows="6" placeholder="请输入内容" v-model="currentQuestion.answer">
-            </el-input>
-          </template>
-          <template v-if="solvingType == 2">
-            <!-- 答题图片展示 -->
-            <ul class="el-upload-list el-upload-list--picture-card" v-if="currentQuestion.typeId == 2">
-              <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.cacheFiles" :key="index">
-                <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
-                <span class="el-upload-list__item-actions">
-                  <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
-                    <i class="el-icon-zoom-in"></i>
-                  </span>
-                  <span class="el-upload-list__item-delete" @click="deleteImg(index)" v-if="dataDetail.state == 3 || dataDetail.state == 4"><i class="el-icon-delete"></i></span>
-                </span>
-              </li>
-            </ul>
-            <!-- 上传图片 -->
-            <label class="el-upload el-upload--picture-card" v-if="
-                (dataDetail.state == 3 || dataDetail.state == 4) &&
-                currentQuestion.typeId == 2
-              "><i class="el-icon-plus"></i><input type="file" ref="upFile" name="file" accept="image/*" class="el-upload__input" @change="UploadImage" /></label>
-          </template>
-          <template v-if="solvingType == 3">
-            <!-- 解析 -->
-            <el-row :gutter="24" id="parse">
-              <el-col v-if="currentQuestion.typeId != 1" :span="12">
-                <div style="padding: 30px">
-                  <div v-html="'答:' + (currentQuestion.answer || '')"></div>
-                  <div v-if="currentQuestion.typeId == 2">
-                    <ul class="el-upload-list el-upload-list--picture-card">
-                      <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.attachments" :key="index">
-                        <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
-                        <span class="el-upload-list__item-actions">
-                          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
-                            <i class="el-icon-zoom-in"></i>
-                          </span>
-                        </span>
-                      </li>
-                    </ul>
-                  </div>
-                </div>
-              </el-col>
-              <el-col :span="currentQuestion.typeId == 1 ? 24 : 12">
-                <div>
-                  <div style="padding: 30px" v-html="currentQuestion.parse"></div>
-                </div>
-              </el-col>
-            </el-row>
-          </template>
-          <!-- 记分 -->
-          <template v-if="solvingType == 4">
-            <el-row :gutter="24">
-              <el-col :span="12">
-                <div style="padding: 30px">
-                  <div v-html="'答:' + (currentQuestion.answer || '')"></div>
-                  <div v-if="currentQuestion.typeId == 2">
-                    <ul class="el-upload-list el-upload-list--picture-card">
-                      <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.attachments" :key="index">
-                        <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
-                        <span class="el-upload-list__item-actions">
-                          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
-                            <i class="el-icon-zoom-in"></i>
-                          </span>
-                        </span>
-                      </li>
-                    </ul>
-                  </div>
-                </div>
-              </el-col>
-              <el-col :span="12" class="text-center">
-                <div style="margin-top: 30px">
-                  此题总分{{ currentQuestion.scoreTotal || '--' }}分
-                </div>
-                <div style="margin-top: 30px">
-                  <el-input :disabled="currentQuestion.typeId == 1" class="fenshu" type="number" v-model="score" min="0" :max="currentQuestion.scoreTotal" placeholder="请输入内容" @change="
-                      score > currentQuestion.scoreTotal
-                        ? (score = currentQuestion.scoreTotal)
-                        : (score = Math.floor(score));
-                      score < 0 ? (score = 0) : (score = Math.floor(score));
-                    "></el-input>
-                  <el-input style="width: 50%; margin: 20px 0" type="textarea" :rows="2" placeholder="请输入批阅内容" maxlength="200" v-model="comment" v-if="false">
-                  </el-input>
-                </div>
-
-                <el-button style="margin-top: 30px; margin-bottom: 30px; width: 100px" type="success" round @click="scoreExamineeQuestion">提交
-                </el-button>
-              </el-col>
-            </el-row>
-          </template>
-          <el-dialog :visible.sync="dialogVisible" append-to-body>
-            <img width="100%" :src="dialogImageUrl" alt="" />
-          </el-dialog>
-        </div>
-      </template>
-    </div>
-  </div>
-</template>
-
-<script>
-import {
-  openWrongQuestion,
-  openQuestion,
-  scoreWrongQuestion,
-} from "@/api/webApi/front";
-//import { scoreWrongQuestion } from "@/api/webApi/studentEvaluating";
-export default {
-  // TODO: 和answer页面需要形成重用组件
-  props: {
-    questionId: {
-      type: Number | String,
-      default: 0,
-    },
-    examineeId: {
-      type: Number | String,
-      default: 0,
-    },
-    customerCode: {
-      type: String,
-      default: "", // 错题模式下, 老师如果要查看解析需要传入错题人的customerCode
-    },
-    showScore: {
-      type: Boolean,
-      default: true, // 只读模式下只能查看结果,不能阅卷评分
-    },
-    canScore: {
-      type: Boolean,
-      default: false, // 只读模式下只能查看结果,不能阅卷评分
-    },
-    lockAnswerInSolving: {
-      // 解析时不动答案,方便对比
-      type: Boolean,
-      default: false,
-    },
-    // 错模式使用接口openWrongQuestion,否则使用openQuestion
-    // 错题模式与测评无关,没有当时的答案。 openQuestion是某一次测评的答题状态所以要带examineeId
-    wrongMode: {
-      type: Boolean,
-      default: true,
-    },
-    displayQuestion: {
-      type: Object,
-      default: null,
-    },
-    initSolvingType: {
-      type: Number | String,
-      default: "",
-    },
-  },
-  data() {
-    return {
-      loading: false,
-      selectOpt: ["A", "B", "C", "D", "E", "F", "G"],
-      currentQuestion: {},
-      subjectTime: 0,
-      solvingType: 3,
-      imgFileList: [],
-      dialogImageUrl: "",
-      dialogVisible: false,
-      dataDetail: {
-        state: 5
-      },
-      comment: "",
-      score: 0,
-    };
-  },
-  watch: {
-    "currentQuestion.title": function (value) {
-      if (value) this.$nextTick(() => this.mxGlobal.MathQueue("title"));
-    },
-    solvingType: function (value) {
-      if (value == 3) this.$nextTick(() => this.mxGlobal.MathQueue("parse"));
-    },
-  },
-  created() {
-    if (this.initSolvingType) this.solvingType = this.initSolvingType;
-    if (this.displayQuestion != null) {
-      console.log("displayQuestion", this.displayQuestion);
-      this.currentQuestion = this.displayQuestion;
-      return;
-    }
-    this.getQuestionById();
-  },
-  methods: {
-    getQuestionById() {
-      if (!this.questionId) return;
-      let questionMethod = openQuestion;
-      this.wrongMode ? openWrongQuestion : openQuestion;
-      let methodName = "openQuestion";
-      let questionParams = {
-        questionId: this.questionId,
-        examineeId: this.examineeId,
-      };
-      if (this.wrongMode) {
-        questionMethod = openWrongQuestion;
-        methodName = "openWrongQuestion";
-        questionParams = {
-          questionId: this.questionId,
-          isReview: true, // 如果为true,会返回答案
-        };
-        if (this.customerCode) questionParams.code = this.customerCode;
-      }
-      questionMethod(questionParams).then((rep) => {
-        console.log(
-          methodName + " rep=",
-          rep,
-          this.solvingType,
-          this.initSolvingType
-        );
-        if (rep.code == 200 || rep.code == 0) {
-          // 加一些容错处理,
-          this.currentQuestion = rep.data || {};
-          this.currentQuestion.title = this.currentQuestion.title || "";
-          this.currentQuestion.answers = this.currentQuestion.answers || ["", "",];
-          this.currentQuestion.answer = this.currentQuestion.answer || ''
-          this.comment = this.currentQuestion.comment;
-          if (this.currentQuestion.typeId == 1)
-            this.score = this.currentQuestion.answer == this.currentQuestion.answers[0] ?
-              this.currentQuestion.scoreTotal : 0;
-          else if (this.currentQuestion.typeId == 3) {
-            this.score = this.currentQuestion.answer == this.currentQuestion.answers[0] ?
-              this.currentQuestion.scoreTotal : 0;
-            this.currentQuestion.answer = this.currentQuestion.answer.split(',')
-          }
-          console.log('display question', this.currentQuestion.answers.toString(), this.currentQuestion)
-        } else {
-          this.msgError(rep.msg || methodName + "请求异常");
-        }
-      });
-    },
-    // 答题方式
-    answerFunc(type) {
-      this.solvingType = type;
-    },
-    handlePictureCardPreview(file) {
-      this.dialogImageUrl = file;
-      this.dialogVisible = true;
-    },
-    scoreExamineeQuestion() {
-      if (this.score < 0) {
-        this.msgError("请先打分");
-        return;
-      }
-      var params = {
-        questionId: this.currentQuestion.questionId,
-        score: this.score || 0,
-        comment: this.comment || "",
-        answer: this.currentQuestion.answer.toString(),
-        duration: this.currentQuestion.duration,
-        attachments: this.currentQuestion.attachments,
-      };
-      scoreWrongQuestion(params).then((rep) => {
-        if (rep.code == 200 || rep.code == 0) {
-          this.$emit("scoreWrongCompleted");
-        } else {
-          this.msgError(rep.msg || "scoreWrongQuestion 请求异常");
-        }
-      });
-    },
-  },
-};
-</script>
-
-<style>
-.upload_container img {
-  max-width: 100%;
-}
-</style>
-
-<style scoped lang="scss">
-.btn {
-  background-color: #ffffff;
-  border: 1px solid #dcdfe6;
-  color: #606266;
-  display: inline-block;
-  cursor: pointer;
-}
-
-.font_color_brown {
-  color: #d77616;
-  font-size: 20px;
-  margin-left: 10%;
-}
-
-.color_gblue {
-  background-color: #cfdcd5;
-  color: #ffffff;
-}
-
-.color_blue {
-  background-color: #47c6a2;
-  color: #ffffff;
-}
-
-.color_brown {
-  background-color: #f77e67;
-  color: #ffffff;
-}
-
-.color_gbrown {
-  background-color: #fbd0a6;
-  color: #ffffff;
-}
-
-.color_gray {
-  background-color: #ffcbc1;
-  color: #ffffff;
-}
-
-.answer_title {
-  text-align: center;
-  position: relative;
-
-  img {
-    width: 50px;
-    height: 50px;
-  }
-
-  .answer_title_info {
-    position: absolute;
-    left: 10px;
-    top: 10px;
-    text-align: left;
-
-    span {
-      margin-right: 10px;
-    }
-  }
-
-  .answer_title_name {
-    font-size: 32px;
-    font-weight: 500;
-    margin: 5px 0 15px;
-    padding-bottom: 10px;
-    border-bottom: 1px solid #dbdbdb;
-  }
-}
-
-.answer_main {
-  .answer_main_title {
-    margin-bottom: 30px;
-    word-break: break-all;
-
-    img {
-      max-width: 100%;
-    }
-  }
-
-  .answer_main_btn {
-    margin: 10px 0;
-
-    button {
-      // margin-left: 20px;
-    }
-
-    .question_function_container {
-      position: absolute;
-      top: 0;
-      right: 0;
-      text-align: right;
-      display: flex;
-
-      .question_function_item {
-        margin-left: 20px;
-        padding: 5px 0;
-        cursor: pointer;
-        display: flex;
-
-        span {
-          display: flex;
-          justify-content: center;
-          align-items: center;
-        }
-
-        i,
-        img {
-          margin-right: 5px;
-        }
-
-        .question_function_image {
-          width: 24px;
-          font-size: 24px;
-          color: orange;
-        }
-      }
-    }
-  }
-
-  .upload_container {
-    border: 1px solid #6cd1b5;
-    padding: 10px;
-    border-radius: 8px;
-    min-height: 200px;
-  }
-
-  .answer_footer_btn {
-    display: flex;
-    justify-content: space-between;
-    margin: 15px 0 30px;
-
-    .color_green_a {
-      border: 1px solid #6cd1b5;
-      color: #6cd1b5;
-    }
-
-    .prev_btn {
-      padding: 0;
-      border: 1px solid #dcdfe6;
-      border-radius: 50%;
-      color: #333;
-      width: 35px;
-      height: 35px;
-      line-height: 35px;
-      text-align: center;
-    }
-
-    .next_btn {
-      padding: 0;
-      border: 1px solid #dcdfe6;
-      border-radius: 50%;
-      color: #333;
-      width: 35px;
-      height: 35px;
-      line-height: 35px;
-      text-align: center;
-    }
-
-    .color_green_b {
-      border: 1px solid #6cd1b5;
-      background-color: #6cd1b5;
-      color: #ffffff;
-    }
-  }
-
-  .ft_green {
-    color: #6cd1b5;
-    margin: 30px 0;
-  }
-}
-
-.answer_card {
-  border: 1px solid #dcdfe6;
-  padding-bottom: 15px;
-
-  .card_title {
-    text-align: center;
-    font-size: 20px;
-    padding: 15px;
-  }
-
-  .card_btn_container {
-    padding: 15px 0 15px 15px;
-
-    .card_btn {
-      position: relative;
-      padding: 0;
-      width: 40px;
-      height: 40px;
-      border-radius: 50%;
-      text-align: center;
-      margin-right: 15px;
-      margin-bottom: 15px;
-
-      .ebtn_mblem {
-        position: absolute;
-        top: -5px;
-        right: -5px;
-        width: 20px;
-        height: 20px;
-        line-height: 20px;
-        text-align: center;
-        font-size: 14px;
-        background-color: red;
-        color: #ffffff;
-        border-radius: 50%;
-      }
-    }
-  }
-
-  .card_timer {
-    padding: 25px;
-    text-align: center;
-    color: #fd0303;
-  }
-
-  .card_footer {
-    display: flex;
-    justify-content: space-around;
-  }
-}
-</style>
-<style scoped>
-.el-checkbox.is-bordered.is-checked,
-.el-radio.is-bordered.is-checked {
-  border-color: #47c6a2;
-}
-
-.el-checkbox.is-bordered.is-error,
-.el-radio.is-bordered.is-error {
-  border-color: #f56c6c;
-}
-
-/deep/ .el-radio__input.is-checked .el-radio__inner {
-  border-color: #47c6a2;
-  background: #47c6a2;
-}
-
-.el-radio.is-bordered.is-error /deep/ .el-radio__label {
-  color: #f56c6c;
-}
-
-.el-radio.is-bordered.is-checked /deep/ .el-radio__label {
-  color: #47c6a2;
-}
-
-.fenshu /deep/ .el-input__inner {
-  width: 50%;
-  line-height: 40px;
-  border: none;
-  background: #eee;
-  color: #333;
-  text-align: center;
-}
-
-.el-radio--medium.is-bordered {
-  height: auto;
-  padding-bottom: 8px;
-}
-
-.fenshu:focus-visible {
-  outline: none;
-}
-
-/deep/ .el-textarea__inner {
-  height: 180px;
-}
-
-/deep/ .el-dropdown-link {
-  cursor: pointer;
-  font-size: 16px;
-  color: #333333;
-}
-
-/deep/ .el-icon-warning {
-  font-size: 24px;
-  color: #999999;
-}
-
-.el-checkbox.is-bordered.el-checkbox--medium {
-  height: auto;
-}
-</style>
+<template>
+  <div class="answer_main" id="title">
+    <div class="">
+      <!-- 大题 -->
+      <div style="display: flex; justify-content: flex-start">
+        <div>{{ currentQuestion.seq || 1 }}、</div>
+        <div class="answer_main_title" style="flex: 1" v-html="currentQuestion.title"></div>
+      </div>
+      <!-- 小题 -->
+      <div style="padding-left: 50px" v-if="currentQuestion.subQuestions">
+        <div style="margin-bottom: 15px" v-for="(subItem, ix) in currentQuestion.subQuestions" :key="ix">
+          <div v-html="ix + 1 + '、' + subItem.title"></div>
+          <template v-if="subItem.options&&subItem.options.length">
+            <div style="margin-top: 20px">
+              <div v-for="(itemOpt, idx) in subItem.options" :key="idx">
+                <div style="margin-bottom: 15px" v-html="selectOpt[idx] + ' 、 ' + itemOpt"></div>
+              </div>
+            </div>
+          </template>
+        </div>
+      </div>
+    </div>
+    <div>
+      <template v-if="currentQuestion.typeId == 1">
+        <div style="margin-top: 20px">
+          <div v-for="(itemOpt, idx) in currentQuestion.options" :key="idx">
+            <template v-if="dataDetail.state == 3 || dataDetail.state == 4">
+              <!-- 答题 -->
+              <el-radio style="margin-bottom: 15px" v-model="currentQuestion.answer" :label="selectOpt[idx]" border size="medium">{{ selectOpt[idx] + " 、 "
+                }}<span style="white-space: normal" v-html="itemOpt"></span></el-radio>
+            </template>
+            <template v-else>
+              <!-- 查看 -->
+              <el-radio-group v-model="currentQuestion.answer">
+                <el-radio style="margin-bottom: 15px" :class="{
+                  'is-checked' : currentQuestion.answers[0].includes(selectOpt[idx]),
+                  'is-error': currentQuestion.answer.includes(selectOpt[idx]) && !currentQuestion.answers[0].includes(selectOpt[idx])
+                }" :label="selectOpt[idx]" disabled border size="medium">{{ selectOpt[idx] + " 、 "
+                }}<span style="white-space: normal" v-html="itemOpt"></span></el-radio>
+              </el-radio-group>
+              <!--  currentQuestion.answers[0] == selectOpt[idx] 表示正确答案  红色-->
+              <!-- currentQuestion.answer== selectOpt[idx] && currentQuestion.answers[0]!= selectOpt[idx] 表示当前答案 蓝色-->
+            </template>
+          </div>
+        </div>
+      </template>
+      <template v-if="currentQuestion.typeId == 3">
+        <div style="margin-top: 20px" id="dati">
+          <!-- 遍历客观题的答题项 -->
+          <div v-for="(itemOpt, idx) in currentQuestion.options" :key="idx">
+            <!-- todo 只在state为3和4的时候可以做题 -->
+            <template v-if="
+                (dataDetail.state == 3 ||
+                dataDetail.state == 4 ||
+                dataDetail.state == 7)&& isAnswer
+
+              ">
+              <!-- 答题 -->
+              <el-checkbox-group v-model="currentQuestion.answer" @change="changeCheckbox">
+                <el-checkbox style="margin-bottom: 15px" :label="selectOpt[idx]" border size="medium">{{ selectOpt[idx] + ' 、 '
+                }}<span style="white-space: normal" v-html="itemOpt"></span></el-checkbox>
+              </el-checkbox-group>
+            </template>
+            <template v-else>
+              <!-- 查看 -->
+              <el-checkbox-group v-model="currentQuestion.answer">
+                <el-checkbox v-if="currentQuestion.answer.length" style="margin-bottom: 15px" :class="{
+                  'is-checked' : currentQuestion.answers[0].includes(selectOpt[idx]),
+                  'is-error': currentQuestion.answer.includes(selectOpt[idx]) && !currentQuestion.answers[0].includes(selectOpt[idx])
+                }" :label="selectOpt[idx]" disabled border size="medium">{{ selectOpt[idx] + ' 、 '
+                }}<span style="white-space: normal" v-html="itemOpt"></span></el-checkbox>
+              </el-checkbox-group>
+            </template>
+          </div>
+        </div>
+      </template>
+      <template>
+        <div class="answer_main_btn">
+          <el-button v-if="dataDetail.state == 3 || dataDetail.state == 4" :type="solvingType == 1 ? 'primary' : ''" @click="answerFunc(1)">手动答题
+          </el-button>
+          <el-button v-if="dataDetail.state == 3 || dataDetail.state == 4" :type="solvingType == 2 ? 'primary' : ''" @click="answerFunc(2)"><i class="el-icon-camera-solid"></i>拍照上传
+          </el-button>
+          <el-button v-if="dataDetail.state == 5" :type="solvingType == 3 ? 'primary' : ''" @click="answerFunc(3)">
+            解析
+          </el-button>
+          <el-button v-if="canScore && dataDetail.state == 5" :type="solvingType == 4 ? 'primary' : ''" @click="answerFunc(4)">
+            计分
+          </el-button>
+          <span v-if="dataDetail.state != 3 && dataDetail.state != 4 && showScore" class="font_color_brown">得分:{{ currentQuestion.score || 0 }}分</span>
+        </div>
+        <div class="upload_container" v-loading="loading">
+          <template v-if="solvingType == 1">
+            <el-input type="textarea" :rows="6" placeholder="请输入内容" v-model="currentQuestion.answer">
+            </el-input>
+          </template>
+          <template v-if="solvingType == 2">
+            <!-- 答题图片展示 -->
+            <ul class="el-upload-list el-upload-list--picture-card" v-if="currentQuestion.typeId == 2">
+              <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.cacheFiles" :key="index">
+                <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
+                <span class="el-upload-list__item-actions">
+                  <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
+                    <i class="el-icon-zoom-in"></i>
+                  </span>
+                  <span class="el-upload-list__item-delete" @click="deleteImg(index)" v-if="dataDetail.state == 3 || dataDetail.state == 4"><i class="el-icon-delete"></i></span>
+                </span>
+              </li>
+            </ul>
+            <!-- 上传图片 -->
+            <label class="el-upload el-upload--picture-card" v-if="
+                (dataDetail.state == 3 || dataDetail.state == 4) &&
+                currentQuestion.typeId == 2
+              "><i class="el-icon-plus"></i><input type="file" ref="upFile" name="file" accept="image/*" class="el-upload__input" @change="UploadImage" /></label>
+          </template>
+          <template v-if="solvingType == 3">
+            <!-- 解析 -->
+            <el-row :gutter="24" id="parse">
+              <el-col v-if="currentQuestion.typeId != 1" :span="12">
+                <div style="padding: 30px">
+                  <div v-html="'答:' + (currentQuestion.answer || '')"></div>
+                  <div v-if="currentQuestion.typeId == 2">
+                    <ul class="el-upload-list el-upload-list--picture-card">
+                      <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.attachments" :key="index">
+                        <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
+                        <span class="el-upload-list__item-actions">
+                          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
+                            <i class="el-icon-zoom-in"></i>
+                          </span>
+                        </span>
+                      </li>
+                    </ul>
+                  </div>
+                </div>
+              </el-col>
+              <el-col :span="currentQuestion.typeId == 1 ? 24 : 12">
+                <div>
+                  <div style="padding: 30px" v-html="currentQuestion.parse"></div>
+                </div>
+              </el-col>
+            </el-row>
+          </template>
+          <!-- 记分 -->
+          <template v-if="solvingType == 4">
+            <el-row :gutter="24">
+              <el-col :span="12">
+                <div style="padding: 30px">
+                  <div v-html="'答:' + (currentQuestion.answer || '')"></div>
+                  <div v-if="currentQuestion.typeId == 2">
+                    <ul class="el-upload-list el-upload-list--picture-card">
+                      <li tabindex="0" class="el-upload-list__item is-ready el-list-enter-to" v-for="(img, index) in currentQuestion.attachments" :key="index">
+                        <img :src="img" alt="" class="el-upload-list__item-thumbnail" />
+                        <span class="el-upload-list__item-actions">
+                          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(img)">
+                            <i class="el-icon-zoom-in"></i>
+                          </span>
+                        </span>
+                      </li>
+                    </ul>
+                  </div>
+                </div>
+              </el-col>
+              <el-col :span="12" class="text-center">
+                <div style="margin-top: 30px">
+                  此题总分{{ currentQuestion.scoreTotal || '--' }}分
+                </div>
+                <div style="margin-top: 30px">
+                  <el-input :disabled="currentQuestion.typeId == 1" class="fenshu" type="number" v-model="score" min="0" :max="currentQuestion.scoreTotal" placeholder="请输入内容" @change="
+                      score > currentQuestion.scoreTotal
+                        ? (score = currentQuestion.scoreTotal)
+                        : (score = Math.floor(score));
+                      score < 0 ? (score = 0) : (score = Math.floor(score));
+                    "></el-input>
+                  <el-input style="width: 50%; margin: 20px 0" type="textarea" :rows="2" placeholder="请输入批阅内容" maxlength="200" v-model="comment" v-if="false">
+                  </el-input>
+                </div>
+
+                <el-button style="margin-top: 30px; margin-bottom: 30px; width: 100px" type="success" round @click="scoreExamineeQuestion">提交
+                </el-button>
+              </el-col>
+            </el-row>
+          </template>
+          <el-dialog :visible.sync="dialogVisible" append-to-body>
+            <img width="100%" :src="dialogImageUrl" alt="" />
+          </el-dialog>
+        </div>
+      </template>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  openWrongQuestion,
+  openQuestion,
+  scoreWrongQuestion,
+} from "@/api/webApi/front";
+//import { scoreWrongQuestion } from "@/api/webApi/studentEvaluating";
+export default {
+  // TODO: 和answer页面需要形成重用组件
+  props: {
+    questionId: {
+      type: Number | String,
+      default: 0,
+    },
+    examineeType:{
+      type: Number | String,
+      default: 1,
+    },
+    examineeId: {
+      type: Number | String,
+      default: 0,
+    },
+    customerCode: {
+      type: String,
+      default: "", // 错题模式下, 老师如果要查看解析需要传入错题人的customerCode
+    },
+    showScore: {
+      type: Boolean,
+      default: true, // 只读模式下只能查看结果,不能阅卷评分
+    },
+    canScore: {
+      type: Boolean,
+      default: false, // 只读模式下只能查看结果,不能阅卷评分
+    },
+    lockAnswerInSolving: {
+      // 解析时不动答案,方便对比
+      type: Boolean,
+      default: false,
+    },
+    // 错模式使用接口openWrongQuestion,否则使用openQuestion
+    // 错题模式与测评无关,没有当时的答案。 openQuestion是某一次测评的答题状态所以要带examineeId
+    wrongMode: {
+      type: Boolean,
+      default: true,
+    },
+    displayQuestion: {
+      type: Object,
+      default: null,
+    },
+    initSolvingType: {
+      type: Number | String,
+      default: "",
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      selectOpt: ["A", "B", "C", "D", "E", "F", "G"],
+      currentQuestion: {},
+      subjectTime: 0,
+      solvingType: 3,
+      imgFileList: [],
+      dialogImageUrl: "",
+      dialogVisible: false,
+      dataDetail: {
+        state: 5
+      },
+      comment: "",
+      score: 0,
+    };
+  },
+  watch: {
+    "currentQuestion.title": function (value) {
+      if (value) this.$nextTick(() => this.mxGlobal.MathQueue("title"));
+    },
+    solvingType: function (value) {
+      if (value == 3) this.$nextTick(() => this.mxGlobal.MathQueue("parse"));
+    },
+  },
+  created() {
+    if (this.initSolvingType) this.solvingType = this.initSolvingType;
+    if (this.displayQuestion != null) {
+      console.log("displayQuestion", this.displayQuestion);
+      this.currentQuestion = this.displayQuestion;
+      return;
+    }
+    this.getQuestionById();
+  },
+  methods: {
+    getQuestionById() {
+      if (!this.questionId) return;
+      let questionMethod = openQuestion;
+      this.wrongMode ? openWrongQuestion : openQuestion;
+      let methodName = "openQuestion";
+      let questionParams = {
+        questionId: this.questionId,
+        examineeId: this.examineeId,
+        examineeType:this.examineeType,
+      };
+      if (this.wrongMode) {
+        questionMethod = openWrongQuestion;
+        methodName = "openWrongQuestion";
+        questionParams = {
+          questionId: this.questionId,
+          isReview: true, // 如果为true,会返回答案
+        };
+        if (this.customerCode) questionParams.code = this.customerCode;
+      }
+      questionMethod(questionParams).then((rep) => {
+        console.log(
+          methodName + " rep=",
+          rep,
+          this.solvingType,
+          this.initSolvingType
+        );
+        if (rep.code == 200 || rep.code == 0) {
+          // 加一些容错处理,
+          this.currentQuestion = rep.data || {};
+          this.currentQuestion.title = this.currentQuestion.title || "";
+          this.currentQuestion.answers = this.currentQuestion.answers || ["", "",];
+          this.currentQuestion.answer = this.currentQuestion.answer || ''
+          this.comment = this.currentQuestion.comment;
+          if (this.currentQuestion.typeId == 1)
+            this.score = this.currentQuestion.answer == this.currentQuestion.answers[0] ?
+              this.currentQuestion.scoreTotal : 0;
+          else if (this.currentQuestion.typeId == 3) {
+            this.score = this.currentQuestion.answer == this.currentQuestion.answers[0] ?
+              this.currentQuestion.scoreTotal : 0;
+            this.currentQuestion.answer = this.currentQuestion.answer.split(',')
+          }
+          console.log('display question', this.currentQuestion.answers.toString(), this.currentQuestion)
+        } else {
+          this.msgError(rep.msg || methodName + "请求异常");
+        }
+      });
+    },
+    // 答题方式
+    answerFunc(type) {
+      this.solvingType = type;
+    },
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file;
+      this.dialogVisible = true;
+    },
+    scoreExamineeQuestion() {
+      if (this.score < 0) {
+        this.msgError("请先打分");
+        return;
+      }
+      var params = {
+        questionId: this.currentQuestion.questionId,
+        score: this.score || 0,
+        comment: this.comment || "",
+        answer: this.currentQuestion.answer.toString(),
+        duration: this.currentQuestion.duration,
+        attachments: this.currentQuestion.attachments,
+      };
+      scoreWrongQuestion(params).then((rep) => {
+        if (rep.code == 200 || rep.code == 0) {
+          this.$emit("scoreWrongCompleted");
+        } else {
+          this.msgError(rep.msg || "scoreWrongQuestion 请求异常");
+        }
+      });
+    },
+  },
+};
+</script>
+
+<style>
+.upload_container img {
+  max-width: 100%;
+}
+</style>
+
+<style scoped lang="scss">
+.btn {
+  background-color: #ffffff;
+  border: 1px solid #dcdfe6;
+  color: #606266;
+  display: inline-block;
+  cursor: pointer;
+}
+
+.font_color_brown {
+  color: #d77616;
+  font-size: 20px;
+  margin-left: 10%;
+}
+
+.color_gblue {
+  background-color: #cfdcd5;
+  color: #ffffff;
+}
+
+.color_blue {
+  background-color: #47c6a2;
+  color: #ffffff;
+}
+
+.color_brown {
+  background-color: #f77e67;
+  color: #ffffff;
+}
+
+.color_gbrown {
+  background-color: #fbd0a6;
+  color: #ffffff;
+}
+
+.color_gray {
+  background-color: #ffcbc1;
+  color: #ffffff;
+}
+
+.answer_title {
+  text-align: center;
+  position: relative;
+
+  img {
+    width: 50px;
+    height: 50px;
+  }
+
+  .answer_title_info {
+    position: absolute;
+    left: 10px;
+    top: 10px;
+    text-align: left;
+
+    span {
+      margin-right: 10px;
+    }
+  }
+
+  .answer_title_name {
+    font-size: 32px;
+    font-weight: 500;
+    margin: 5px 0 15px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid #dbdbdb;
+  }
+}
+
+.answer_main {
+  .answer_main_title {
+    margin-bottom: 30px;
+    word-break: break-all;
+
+    img {
+      max-width: 100%;
+    }
+  }
+
+  .answer_main_btn {
+    margin: 10px 0;
+
+    button {
+      // margin-left: 20px;
+    }
+
+    .question_function_container {
+      position: absolute;
+      top: 0;
+      right: 0;
+      text-align: right;
+      display: flex;
+
+      .question_function_item {
+        margin-left: 20px;
+        padding: 5px 0;
+        cursor: pointer;
+        display: flex;
+
+        span {
+          display: flex;
+          justify-content: center;
+          align-items: center;
+        }
+
+        i,
+        img {
+          margin-right: 5px;
+        }
+
+        .question_function_image {
+          width: 24px;
+          font-size: 24px;
+          color: orange;
+        }
+      }
+    }
+  }
+
+  .upload_container {
+    border: 1px solid #6cd1b5;
+    padding: 10px;
+    border-radius: 8px;
+    min-height: 200px;
+  }
+
+  .answer_footer_btn {
+    display: flex;
+    justify-content: space-between;
+    margin: 15px 0 30px;
+
+    .color_green_a {
+      border: 1px solid #6cd1b5;
+      color: #6cd1b5;
+    }
+
+    .prev_btn {
+      padding: 0;
+      border: 1px solid #dcdfe6;
+      border-radius: 50%;
+      color: #333;
+      width: 35px;
+      height: 35px;
+      line-height: 35px;
+      text-align: center;
+    }
+
+    .next_btn {
+      padding: 0;
+      border: 1px solid #dcdfe6;
+      border-radius: 50%;
+      color: #333;
+      width: 35px;
+      height: 35px;
+      line-height: 35px;
+      text-align: center;
+    }
+
+    .color_green_b {
+      border: 1px solid #6cd1b5;
+      background-color: #6cd1b5;
+      color: #ffffff;
+    }
+  }
+
+  .ft_green {
+    color: #6cd1b5;
+    margin: 30px 0;
+  }
+}
+
+.answer_card {
+  border: 1px solid #dcdfe6;
+  padding-bottom: 15px;
+
+  .card_title {
+    text-align: center;
+    font-size: 20px;
+    padding: 15px;
+  }
+
+  .card_btn_container {
+    padding: 15px 0 15px 15px;
+
+    .card_btn {
+      position: relative;
+      padding: 0;
+      width: 40px;
+      height: 40px;
+      border-radius: 50%;
+      text-align: center;
+      margin-right: 15px;
+      margin-bottom: 15px;
+
+      .ebtn_mblem {
+        position: absolute;
+        top: -5px;
+        right: -5px;
+        width: 20px;
+        height: 20px;
+        line-height: 20px;
+        text-align: center;
+        font-size: 14px;
+        background-color: red;
+        color: #ffffff;
+        border-radius: 50%;
+      }
+    }
+  }
+
+  .card_timer {
+    padding: 25px;
+    text-align: center;
+    color: #fd0303;
+  }
+
+  .card_footer {
+    display: flex;
+    justify-content: space-around;
+  }
+}
+</style>
+<style scoped>
+.el-checkbox.is-bordered.is-checked,
+.el-radio.is-bordered.is-checked {
+  border-color: #47c6a2;
+}
+
+.el-checkbox.is-bordered.is-error,
+.el-radio.is-bordered.is-error {
+  border-color: #f56c6c;
+}
+
+/deep/ .el-radio__input.is-checked .el-radio__inner {
+  border-color: #47c6a2;
+  background: #47c6a2;
+}
+
+.el-radio.is-bordered.is-error /deep/ .el-radio__label {
+  color: #f56c6c;
+}
+
+.el-radio.is-bordered.is-checked /deep/ .el-radio__label {
+  color: #47c6a2;
+}
+
+.fenshu /deep/ .el-input__inner {
+  width: 50%;
+  line-height: 40px;
+  border: none;
+  background: #eee;
+  color: #333;
+  text-align: center;
+}
+
+.el-radio--medium.is-bordered {
+  height: auto;
+  padding-bottom: 8px;
+}
+
+.fenshu:focus-visible {
+  outline: none;
+}
+
+/deep/ .el-textarea__inner {
+  height: 180px;
+}
+
+/deep/ .el-dropdown-link {
+  cursor: pointer;
+  font-size: 16px;
+  color: #333333;
+}
+
+/deep/ .el-icon-warning {
+  font-size: 24px;
+  color: #999999;
+}
+
+.el-checkbox.is-bordered.el-checkbox--medium {
+  height: auto;
+}
+</style>