Jelajahi Sumber

添加答题操作 答题详情的拍照图片展示

lm 3 hari lalu
induk
melakukan
5db96e1cd1

+ 181 - 0
src/views/targetImprove/components/ImageJumpPreview.vue

@@ -0,0 +1,181 @@
+<template>
+    <div class="watcher_file" 
+        :style="height ? {minHeight:height, height: height} : ''">
+        <div v-if="filePreviewList.includes(previewType)" 
+            class="preview_item"
+            :style="filePadding"
+        >
+            <img  
+                @click="HandleImgPreview" 
+                style="text-align: center;" 
+                v-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)" 
+                :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"
+            :url-list="[fileMessage ? fileMessage.url : '']"
+            show-progress
+            @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')"
+            >
+                <i class="el-icon-arrow-left"></i> <!-- Vue2 常用图标替代 -->
+            </span>
+            <span 
+                :class="['next_nav', {'end': currentNavPage === navTotalPage}]" 
+                @click="currentNavPage === navTotalPage ? '' : HandlePageJump('add')"
+            >
+                <i class="el-icon-arrow-right"></i>
+            </span>
+        </div>
+    </div>
+</template>
+
+<script>
+
+// interface FileMsg {
+//     name:String,
+//     url:String
+// }
+
+export default {
+    name: 'ImageJumpPreview',
+    // 1. 将 defineModel 的 prop 提取到这里,父组件需使用 :current-nav-page.sync="xxx"
+    props: {
+        fileMessage: {
+            required: true,
+            type: Object
+        },
+        height: {
+            type: String,
+            default: ''
+        },
+        filePadding: {
+            type: Object,
+            default: () => ({})
+        },
+        navBarWidth: {
+            type: Object,
+            default: () => ({})
+        },
+        navBarLeft: {
+            type: Object,
+            default: () => ({})
+        },
+        navTotalPage: {
+            type: Number,
+            default: 0
+        },
+        // 对应原 Vue3 中的 defineModel('currentNavPage')
+        currentNavPage: {
+            type: Number,
+            default: 1
+        }
+    },
+    // 2. 将 ref 转换为 data
+    data() {
+        return {
+            filePreviewList: ['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv'],
+            imgVisible: false,
+            previewType: '加载中'
+        }
+    },
+    // 3. 将 watch 转换为选项式侦听器
+    watch: {
+        fileMessage: {
+            handler(newVal) {
+                if (newVal && newVal.name) {
+                    let suffixName = newVal.name.split('.').pop();
+                    if (suffixName) {
+                        this.previewType = suffixName;
+                    }
+                }
+            },
+            immediate: true, // 建议加上 immediate,确保初始化时也能解析类型
+            deep: true
+        }
+    },
+    methods: {
+        HandleImgPreview() {
+            this.imgVisible = true;
+        },
+        async HandlePageJump(type) {
+            let newPage = this.currentNavPage;
+            switch(type) {
+                case 'add':
+                    newPage += 1;
+                    break;
+                case 'reduce':
+                    newPage -= 1;
+                    break;
+            }
+            
+            // 触发 .sync 更新
+            this.$emit('update:currentNavPage', newPage);
+            
+            // 等待 DOM 更新后触发业务事件
+            await this.$nextTick();
+            this.$emit('imgNavChange', newPage);
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.watcher_file{
+    position: relative;
+    width: 100%;
+    min-height: 100%;
+}
+
+.nav_group{
+    position: absolute;
+    width: calc(100% - 40px - 50px);
+    display: flex;
+    justify-content: space-between;
+    bottom: 50%;
+    left: 40px;
+    
+    .pre_nav,
+    .next_nav{
+        line-height: 1;
+        border-radius: 20px;
+        padding: 10px;
+        background-color: #415058;
+        color: white;
+        cursor: pointer;
+    }
+    .first,
+    .end{
+        background-color: #c3c8d0;
+    }
+}
+
+.preview_item{
+    min-height: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+
+    img{
+        max-height: 100%;
+        max-width: 100%;
+    }
+
+    .preview_main{
+        position: relative;
+        min-height: 100%;
+        border-radius: 8px;
+    }
+}
+</style>

+ 3 - 0
src/views/targetImprove/practice/practiceResults/answerAnalysis.vue

@@ -77,7 +77,9 @@ export default ({
             font-weight: 600;
             font-weight: 600;
         }
         }
         .knowledge_tags {
         .knowledge_tags {
+            flex: 1 1;
             display: flex;
             display: flex;
+            flex-wrap: wrap;
             gap: 10px;
             gap: 10px;
             .tag_item {
             .tag_item {
                 box-sizing: border-box;
                 box-sizing: border-box;
@@ -102,6 +104,7 @@ export default ({
             font-weight: 600;
             font-weight: 600;
         }
         }
         .desc{
         .desc{
+            flex: 1 1;
             line-height: 24px;
             line-height: 24px;
         }
         }
     }
     }

+ 28 - 5
src/views/targetImprove/practice/practiceResults/studentAnswerDetail.vue

@@ -17,18 +17,34 @@
                     }"
                     }"
                 >{{ radioItem.label }}</el-radio>
                 >{{ radioItem.label }}</el-radio>
             </el-radio-group>
             </el-radio-group>
+
+
+            <ImageJumpPreview 
+                :fileMessage="fileMessage" height="400px"
+                :filePadding="{padding:`0 ${imgPreviewPadding}`}"
+                :navBarWidth="{width:`calc(100% - ${imgPreviewPadding} + 20px)`}"
+                :navBarLeft="{left: `calc(${imgPreviewPadding} / 2 - 10px)`}"
+                :navTotalPage="5"
+                v-model:currentNavPage="currentNavPage"
+            ></ImageJumpPreview>
+
+
         </div>
         </div>
     </div>
     </div>
 </template>   
 </template>   
 
 
 
 
 <script>
 <script>
+import ImageJumpPreview from '../../components/ImageJumpPreview.vue'
+
 export default ({
 export default ({
     name:'StudentAnswerDetail',
     name:'StudentAnswerDetail',
-    components: {},
+    components: {
+        ImageJumpPreview,
+    },
     data(){
     data(){
         return {
         return {
-            answerType:'online',  //答题方式  //线上答题和上传图片 online \ photo
+            answerType:'photo',  //答题方式  //线上答题和上传图片 online \ photo
             studentAnswerVal:'D',
             studentAnswerVal:'D',
             rightAnswerValue:'B',
             rightAnswerValue:'B',
             defaultRightAnswerValue:'B',
             defaultRightAnswerValue:'B',
@@ -49,7 +65,14 @@ export default ({
                     label:'D',
                     label:'D',
                     value:'D'
                     value:'D'
                 },
                 },
-            ]
+            ],
+            fileMessage:{
+                name:'24-b5fa-0ddc8797a6c0.png',
+                url:'https://jtzx001.oss-accelerate.aliyuncs.com/huijiaoyan_test/20260805_50007/05171802_60fcf6dd-4276-4d24-b5fa-0ddc8797a6c0.png'
+            },
+            imgPreviewPadding:'70px',
+            currentNavPage:1
+
         }
         }
     },
     },
     methods: {},
     methods: {},
@@ -74,10 +97,10 @@ export default ({
         font-weight: 600;
         font-weight: 600;
     }
     }
     .desc{
     .desc{
+        flex: 1 1;
         line-height: 24px;
         line-height: 24px;
     }
     }
 
 
-
     
     
     // 2. 错误选项样式(红色)
     // 2. 错误选项样式(红色)
     ::v-deep .is-wrong-radio {
     ::v-deep .is-wrong-radio {
@@ -105,6 +128,7 @@ export default ({
         }
         }
     }
     }
 
 
+    // 正确选项样式 蓝色
     ::v-deep .is-correct-radio {
     ::v-deep .is-correct-radio {
             position: relative !important;
             position: relative !important;
         // 圆圈边框
         // 圆圈边框
@@ -130,6 +154,5 @@ export default ({
             }
             }
         }
         }
     }
     }
-
 }
 }
 </style>
 </style>