Bläddra i källkod

修改作答详情公共组件

lm 1 månad sedan
förälder
incheckning
39691585ff

+ 18 - 33
src/views/targetImprove/components/ImageJumpPreview.vue

@@ -3,39 +3,32 @@
         :style="height ? {minHeight:height, height: height} : ''">
         <div v-if="filePreviewList.includes(previewType)" 
             class="preview_item"
-            :style="filePadding"
-        >
-            <img  
-                @click="HandleImgPreview" 
+            :style="{padding:`0 ${imgPreviewPadding}`}">
+            <img @click="HandleImgPreview" 
                 style="text-align: center;" 
-                v-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)" 
-                :src="fileMessage ? fileMessage.url : ''"
-            />
+                :src="fileMessage ? fileMessage.url : ''"/>
         </div>
         <div style="text-align: center;" v-else-if="previewType == '加载中'">加载中...</div>
         <div style="text-align: center;" v-else>不支持预览 .{{ previewType }}文件</div>
         
-        <!-- 注意:Vue 2 中 el-image-viewer 的关闭事件可能是 'close',具体依 ElementUI 版本而定 -->
         <el-image-viewer
-            v-if="imgVisible"
             :z-index="9999"
+            v-if="imgVisible"
             :url-list="[fileMessage ? fileMessage.url : '']"
             show-progress
-            :on-close="()=>{imgVisible = false}"
-        />
+            :on-close="()=>{imgVisible = false}"/>
 
         <!-- 页面指示器 -->
-        <div class="nav_group" v-if="navTotalPage && navTotalPage > 0" :style="{...navBarWidth, ...navBarLeft}"> 
-            <span 
-                :class="['pre_nav', {'first': currentNavPage === 1}]" 
-                @click="currentNavPage == 1 ? '' : HandlePageJump('reduce')"
-            >
+        <div class="nav_group" 
+            v-if="navTotalPage && navTotalPage > 1" 
+            :style="{width:`calc(100% - ${imgPreviewPadding} + 20px)`,
+                     left: `calc(${imgPreviewPadding} / 2 - 10px)`}"> 
+            <span :class="['pre_nav', {'first': currentNavPage === 1}]" 
+                @click="currentNavPage == 1 ? '' : HandlePageJump('reduce')">
                 <i class="el-icon-arrow-left"></i> <!-- Vue2 常用图标替代 -->
             </span>
-            <span 
-                :class="['next_nav', {'end': currentNavPage === navTotalPage}]" 
-                @click="currentNavPage === navTotalPage ? '' : HandlePageJump('add')"
-            >
+            <span  :class="['next_nav', {'end': currentNavPage === navTotalPage}]" 
+                @click="currentNavPage === navTotalPage ? '' : HandlePageJump('add')">
                 <i class="el-icon-arrow-right"></i>
             </span>
         </div>
@@ -65,17 +58,10 @@ export default {
             type: String,
             default: ''
         },
-        filePadding: {
-            type: Object,
-            default: () => ({})
-        },
-        navBarWidth: {
-            type: Object,
-            default: () => ({})
-        },
-        navBarLeft: {
-            type: Object,
-            default: () => ({})
+
+        imgPreviewPadding:{ 
+            type:String,
+            required:true
         },
         navTotalPage: {
             type: Number,
@@ -90,7 +76,7 @@ export default {
     // 2. 将 ref 转换为 data
     data() {
         return {
-            filePreviewList: ['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv'],
+            filePreviewList: ['gif','jpeg','jpg','png','svg','webp'],
             imgVisible: false,
             previewType: '加载中'
         }
@@ -168,7 +154,6 @@ export default {
     flex-direction: column;
     justify-content: center;
     align-items: center;
-
     img{
         max-height: 100%;
         max-width: 100%;

+ 4 - 9
src/views/targetImprove/practice/practiceResults/practiceDetail.vue

@@ -84,13 +84,8 @@
                                     :analysis="item.parse"/>
 
                     <!-- 作答详情区域 -->
-                     <!-- isObjective :是否是客观题(1是 0否) -->
-                      <!-- isJudge :是否是判断题 (1是 0否) -->
-                    <studentAnswerDetail v-if="item?.operationType == 'stuAnswerDetail'" 
-                        :studentAnswer="item.studentAnswer" 
-                        :answerType="item.isObjective ? (item.isJudge ? 'img' : 'online') : 'img'"
-                        :answerOptionNum="item.optionsNum"
-                        :rightAnswer="item.answer"
+                    <StudentAnswerDetail v-if="item?.operationType == 'stuAnswerDetail'" 
+                        :studentAnswerInfo="item"
                         :answerImg="(item.studentAnswer?.split(',')?.map(img=>({name:img,url:img})) || [])"
                     />
                 </li>
@@ -114,14 +109,14 @@ import deteaiIconLight from '@/assets/practiceResult/todo_list_light.svg'
 
 
 import AnswerAnalysis from './answerAnalysis.vue'
-import studentAnswerDetail from './studentAnswerDetail.vue';
+import StudentAnswerDetail from './studentAnswerDetail.vue';
 
 export default ({
     name:'PracticeDetail',
     components: {
         TopBackNav,
         AnswerAnalysis,
-        studentAnswerDetail
+        StudentAnswerDetail
     },
     inject: ['openAiRobot'],//注入Ai机器人组件调用方法
     props:{

+ 65 - 32
src/views/targetImprove/practice/practiceResults/studentAnswerDetail.vue

@@ -2,29 +2,33 @@
     <div class="stu_answer_detail">
         <div class="title">【作 答】</div>
         <div class="desc">
-            <el-radio-group 
-                v-if="answerType == 'online'"
-            >
+            <!-- 选项形式 -->
+            <el-radio-group  v-if="answerType == 'choice'">
               <el-radio 
                 v-for="radioItem in optionList" 
                     :key="radioItem" 
                     :label="radioItem"
                     :class="{ 
-                         'is-correct-radio is-checked':  rightAnswer.split('').includes(radioItem), 
-                        'is-wrong-radio is-checked': studentAnswer.split('').includes(radioItem) && !(rightAnswer.split('').includes(radioItem))
+                         'is_correct_radio is_checked':  answerStr.split('').includes(radioItem), 
+                        'is_wrong_radio is_checked': studentAnswerInfo.studentAnswer.split('').includes(radioItem) && !(answerStr.split('').includes(radioItem))
                     }"
                 >{{ radioItem }}</el-radio>
             </el-radio-group>
 
+            <!-- 图片形式 -->
             <ImageJumpPreview 
                 v-if="answerType == 'img' && answerImg?.length > 0"
-                :fileMessage="answerImg[currentNavPage - 1]" height="400px"
-                :filePadding="{padding:`0 ${imgPreviewPadding}`}"
-                :navBarWidth="{width:`calc(100% - ${imgPreviewPadding} + 20px)`}"
-                :navBarLeft="{left: `calc(${imgPreviewPadding} / 2 - 10px)`}"
+                :fileMessage="answerImg[currentNavPage - 1]" 
+                height="400px"
+                :imgPreviewPadding="imgPreviewPadding"
                 :navTotalPage="answerImg.length"
                 :currentNavPage.sync="currentNavPage"
             ></ImageJumpPreview>
+
+            <!-- 判断题形式 √ ×-->
+            <span v-if="answerType == 'judge'" style="font-size: 14px;color: #666;">
+                {{  studentAnswerInfo.studentAnswer== '×' ? '错' : (studentAnswerInfo.studentAnswer== '√' ? '对' : '') }}
+            </span>
         </div>
     </div>
 </template>   
@@ -33,6 +37,15 @@
 <script>
 import ImageJumpPreview from '../../components/ImageJumpPreview.vue'
 import {numToCapitalLetter} from '../../utils/numberToExcelCapitalLetter.js'
+/*
+interface StudentAnswerInfo {
+    isObjective:Number, //  是否是客观题(1是 0否)
+    isJudge:Number,  // 是否是判断题 (1是 0否)
+    studentAnswer:String,   //学生的答案
+    optionsNum:Number,  //  选项数量(只有 answerType 为 choice 的时候才会用到)
+    answer:String    //正确答案
+}
+*/
 
 export default ({
     name:'StudentAnswerDetail',
@@ -40,41 +53,59 @@ export default ({
         ImageJumpPreview,
     },
     props:{
-       
-        answerType:{     //答题方式  //线上答题(勾选选项)和上传图片的方式   online \ img
-            type:String
-        },
-
-        /** 【勾选选项】 答题用到的参数 */
-        answerOptionNum:{   // 选项数量(只有 props.answerType 为 online 的时候才会用到)
-            type:Number   
-        },
-        studentAnswer:{   //学生的答案
-            type:String,
-        },
-        rightAnswer:{  //正确答案
-            type:String,
-        },
-        /** 【拍照/传图】 答题用到的参数 */
+        studentAnswerInfo:{
+            type:Object,
+            required:true
+        },  
+        /** 【拍照/传图】 img   用到的参数 */
         answerImg:{
-            type:Array,  //Object[]  name:'',url:''
+            type:Array,  // {name:'',url:''}[]
         }
     },
     data(){
         return {
             imgPreviewPadding:'70px',
             currentNavPage:1,
+  
+            
         }
     },
     computed:{
+        answerType(){
+            //答题方式  //【线上答题(勾选选项)】choice 、 【上传图片的方式】 img   、判断题 文本 对/错
+            if(this.studentAnswerInfo.isObjective === 1){
+                if(this.studentAnswerInfo.isJudge === 1){
+                    return 'judge'
+                }else{
+                    return 'choice'
+                }
+            }else{
+                return 'img'
+            }
+        },
+
         // 答案的选项列表
         optionList(){
             // 选项数量转换成大写字母列表
             let options = []
-            for(let i=0;i<this.answerOptionNum;i++){
+            for(let i=0;i<this.studentAnswerInfo.optionsNum;i++){
                 options[i]  = numToCapitalLetter(i)
             }
             return options
+        },
+
+        // 过滤掉HTML标签,只保留 A-G 大写字母后的正确答案
+        answerStr(){
+            let ans = this.studentAnswerInfo.answer || '';
+            console.log("打印正确答案",this.studentAnswerInfo.answer);
+    
+            // 1. 移除全部HTML标签
+            ans = ans.replace(/<[^>]*>/g, '');
+            // 2. 只保留 A‑G 大写英文字母,【这里必须是英文半角减号 A-G】
+            ans = ans.replace(/[^A-G]/gi, '');
+            ans = ans.toUpperCase().trim();
+            console.log("打印过滤后的正确答案",ans);
+            return ans;
         }
     },
     methods: {},
@@ -91,6 +122,8 @@ export default ({
  .stu_answer_detail{
     padding: 16px;
     display: flex;
+    border-top: 1px solid #DCDFE6;
+    align-items: center;
     gap:10px;
     .title {
         text-align: right;
@@ -100,19 +133,19 @@ export default ({
     }
     .desc{
         flex: 1 1;
-        line-height: 24px;
+        // line-height: 24px;
     }
 
     
     // 2. 错误选项样式(红色)
-    ::v-deep .is-wrong-radio {
+    ::v-deep .is_wrong_radio {
             position: relative !important;
         // 圆圈边框
         .el-radio__inner {
             border-color: #F56C6C !important;
         }
         // 选中状态(圆点填充)
-        &.is-checked .el-radio__inner {
+        &.is_checked .el-radio__inner {
             position: relative !important;
             background-color: none;
             &::after{
@@ -131,14 +164,14 @@ export default ({
     }
 
     // 正确选项样式 蓝色
-    ::v-deep .is-correct-radio {
+    ::v-deep .is_correct_radio {
             position: relative !important;
         // 圆圈边框
         .el-radio__inner {
             border-color: #2E64FA !important;
         }
         // 选中状态(圆点填充)
-        &.is-checked .el-radio__inner {
+        &.is_checked .el-radio__inner {
             position: relative !important;
             background-color: none;