|
|
@@ -1,7 +1,7 @@
|
|
|
<template>
|
|
|
<div class="answerTheResult">
|
|
|
<div class="atr_detail">
|
|
|
- <div class="atr_d_btn">查看详细</div>
|
|
|
+ <div class="atr_d_btn" @click="lookDetail()">查看详细</div>
|
|
|
<div class="atr_d_msg">
|
|
|
<div>参与人数</div>
|
|
|
<span
|
|
|
@@ -13,7 +13,7 @@
|
|
|
|
|
|
<div class="atr_d_msg" v-if="workDetail && workDetail.type === '45'">
|
|
|
<div>正确率</div>
|
|
|
- <span>{{choiceQuestionList[workIndex].accuracyRate}}%({{choiceQuestionList[workIndex].yes}}/{{choiceQuestionList[workIndex].all}})</span>
|
|
|
+ <span v-if="choiceQuestionListData[workIndex]">{{choiceQuestionListData[workIndex].accuracyRate}}%({{choiceQuestionListData[workIndex].yes}}/{{choiceQuestionListData[workIndex].all}})</span>
|
|
|
</div>
|
|
|
|
|
|
<div class="atr_d_msg" v-if="choiceQuestionAnswer">
|
|
|
@@ -21,9 +21,9 @@
|
|
|
<span style="color: #03ae2b">{{ choiceQuestionAnswer }}</span>
|
|
|
</div>
|
|
|
|
|
|
- <span class="atr_d_line"></span>
|
|
|
+ <span class="atr_d_line" v-if="props.unsubmittedStudents && props.unsubmittedStudents?.length > 0"></span>
|
|
|
|
|
|
- <div class="no_submit">
|
|
|
+ <div class="no_submit" v-if="props.unsubmittedStudents && props.unsubmittedStudents?.length > 0">
|
|
|
<div>未提交人员</div>
|
|
|
<img
|
|
|
@click="showNoSubmitDetail = !showNoSubmitDetail"
|
|
|
@@ -34,7 +34,7 @@
|
|
|
|
|
|
<div
|
|
|
class="no_submitList"
|
|
|
- v-if="props.unsubmittedStudents?.length > 0"
|
|
|
+ v-if="props.unsubmittedStudents && props.unsubmittedStudents?.length > 0"
|
|
|
:class="{ no_submitList_active: showNoSubmitDetail }"
|
|
|
>
|
|
|
<div
|
|
|
@@ -51,18 +51,19 @@
|
|
|
v-if="
|
|
|
workDetail &&
|
|
|
workDetail.type === '45' &&
|
|
|
- choiceQuestionList[workIndex] &&
|
|
|
- choiceQuestionList[workIndex].choiceUser
|
|
|
+ choiceQuestionListData[workIndex] &&
|
|
|
+ choiceQuestionListData[workIndex].choiceUser
|
|
|
"
|
|
|
>
|
|
|
|
|
|
<div class="atr_t45a_title">
|
|
|
- <span>{{ workIndex+1 }}、{{ choiceQuestionList[workIndex].type=='1'?'单选题':'多选题' }}:</span>
|
|
|
- <span>{{ choiceQuestionList[workIndex].teststitle }}</span>
|
|
|
+ <span>{{ workIndex+1 }}、{{ choiceQuestionListData[workIndex].type=='1'?'单选题':'多选题' }}:</span>
|
|
|
+ <span>{{ choiceQuestionListData[workIndex].teststitle }}</span>
|
|
|
+ <img @click="previewImage(choiceQuestionListData[workIndex].timuList[0].src)" :src="choiceQuestionListData[workIndex].timuList[0].src" v-if="choiceQuestionListData[workIndex].timuList.length>0">
|
|
|
</div>
|
|
|
|
|
|
<template
|
|
|
- v-for="(op, idx) in choiceQuestionList[workIndex].choiceUser"
|
|
|
+ v-for="(op, idx) in choiceQuestionListData[workIndex].choiceUser"
|
|
|
:key="`${workIndex}_${idx}`"
|
|
|
>
|
|
|
<div class="atr_t45a_item">
|
|
|
@@ -81,7 +82,7 @@
|
|
|
<span v-if="op.isAnswer">正确</span>
|
|
|
</div>
|
|
|
<img
|
|
|
- @click="op.show = !op.show"
|
|
|
+ @click="changeShow(op, idx)"
|
|
|
:class="{ show_active: !op.show }"
|
|
|
src="../../../assets/img/arrow_up.png"
|
|
|
/>
|
|
|
@@ -101,384 +102,270 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
- <div class="nextAndUpBtn">
|
|
|
+ <div class="nextAndUpBtn" v-if="choiceQuestionListData.length>1">
|
|
|
<span :class="{no_active:workIndex==0}" @click="changeWorkIndex(0)">上一题</span>
|
|
|
- <span :class="{no_active:choiceQuestionList.length-1<=workIndex}" @click="changeWorkIndex(1)">下一题</span>
|
|
|
+ <span :class="{no_active:choiceQuestionListData.length-1<=workIndex}" @click="changeWorkIndex(1)">下一题</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 预览放大(带缩放/拖拽/旋转/工具栏) -->
|
|
|
- <Teleport to="body">
|
|
|
- <div v-if="previewVisible" class="image-preview" @click.self="closePreview" @wheel.prevent="onWheel">
|
|
|
- <div class="image-preview__toolbar">
|
|
|
- <button @click.stop="zoomOut">-</button>
|
|
|
- <button @click.stop="zoomIn">+</button>
|
|
|
- <button @click.stop="resetTransform">重置</button>
|
|
|
- <button @click.stop="rotateLeft">⟲</button>
|
|
|
- <button @click.stop="rotateRight">⟳</button>
|
|
|
- <button @click.stop="toggleFit">{{ fitMode ? '实际大小' : '适应屏幕' }}</button>
|
|
|
- <button @click.stop="closePreview">关闭</button>
|
|
|
- </div>
|
|
|
- <div class="image-preview__stage"
|
|
|
- @mousedown="onDragStart"
|
|
|
- @mousemove="onDragMove"
|
|
|
- @mouseup="onDragEnd"
|
|
|
- @mouseleave="onDragEnd"
|
|
|
- @dblclick.stop="toggleZoom">
|
|
|
- <!-- 预览中的 Loading 状态 -->
|
|
|
- <div v-if="previewImageLoading" class="preview-loading">
|
|
|
- <div class="loading-spinner"></div>
|
|
|
- <div class="loading-text">图片加载中...</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <img
|
|
|
- v-show="!previewImageLoading"
|
|
|
- :src="imageUrl"
|
|
|
- alt="预览"
|
|
|
- class="image-preview__img"
|
|
|
- :style="imgStyle"
|
|
|
- draggable="false"
|
|
|
- @load="onPreviewImageLoad"
|
|
|
- @error="onPreviewImageError"
|
|
|
- />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </Teleport>
|
|
|
+ <previewImageTool ref="previewImageToolRef"/>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
-import { ref, computed, watch } from "vue";
|
|
|
-import api from "../../../services/course";
|
|
|
-
|
|
|
+import { ref, computed, watch, defineExpose } from 'vue'
|
|
|
+import previewImageTool from '@/views/components/tool/previewImageTool.vue'
|
|
|
+import api from '../../../services/course'
|
|
|
interface Props {
|
|
|
workArray?: object[] | null;
|
|
|
unsubmittedStudents?: object[] | null;
|
|
|
workId?: string | null;
|
|
|
+ slideIndex?:number
|
|
|
}
|
|
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
|
- workArray: () => [],
|
|
|
- unsubmittedStudents: () => [],
|
|
|
- workId: "",
|
|
|
-});
|
|
|
+ workArray: () => [],
|
|
|
+ unsubmittedStudents: () => [],
|
|
|
+ workId: '',
|
|
|
+ slideIndex: 0
|
|
|
+})
|
|
|
+
|
|
|
+const emit = defineEmits<{
|
|
|
+ (e: 'openChoiceQuestionDetail', v: number): void
|
|
|
+}>()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 已提交的作业数量
|
|
|
const workArrayLength = computed(() => {
|
|
|
- let _result = 0;
|
|
|
- if (props.workArray) {
|
|
|
- _result = props.workArray.length;
|
|
|
- }
|
|
|
- return _result;
|
|
|
-});
|
|
|
+ let _result = 0
|
|
|
+ if (props.workArray) {
|
|
|
+ _result = props.workArray.length
|
|
|
+ }
|
|
|
+ return _result
|
|
|
+})
|
|
|
// 未提交的作业数量
|
|
|
const unsubmittedStudentsLength = computed(() => {
|
|
|
- let _result = 0;
|
|
|
- if (props.unsubmittedStudents) {
|
|
|
- _result = props.unsubmittedStudents.length;
|
|
|
- }
|
|
|
- return _result;
|
|
|
-});
|
|
|
+ let _result = 0
|
|
|
+ if (props.unsubmittedStudents) {
|
|
|
+ _result = props.unsubmittedStudents.length
|
|
|
+ }
|
|
|
+ return _result
|
|
|
+})
|
|
|
|
|
|
// 选项序号
|
|
|
const serialNumber = ref<string[]>([
|
|
|
- "A",
|
|
|
- "B",
|
|
|
- "C",
|
|
|
- "D",
|
|
|
- "E",
|
|
|
- "F",
|
|
|
- "G",
|
|
|
- "H",
|
|
|
- "I",
|
|
|
- "J",
|
|
|
- "K",
|
|
|
- "L",
|
|
|
- "M",
|
|
|
- "N",
|
|
|
- "O",
|
|
|
- "P",
|
|
|
- "Q",
|
|
|
- "R",
|
|
|
- "S",
|
|
|
- "T",
|
|
|
- "U",
|
|
|
- "V",
|
|
|
- "W",
|
|
|
- "X",
|
|
|
- "Y",
|
|
|
- "Z",
|
|
|
-]);
|
|
|
+ 'A',
|
|
|
+ 'B',
|
|
|
+ 'C',
|
|
|
+ 'D',
|
|
|
+ 'E',
|
|
|
+ 'F',
|
|
|
+ 'G',
|
|
|
+ 'H',
|
|
|
+ 'I',
|
|
|
+ 'J',
|
|
|
+ 'K',
|
|
|
+ 'L',
|
|
|
+ 'M',
|
|
|
+ 'N',
|
|
|
+ 'O',
|
|
|
+ 'P',
|
|
|
+ 'Q',
|
|
|
+ 'R',
|
|
|
+ 'S',
|
|
|
+ 'T',
|
|
|
+ 'U',
|
|
|
+ 'V',
|
|
|
+ 'W',
|
|
|
+ 'X',
|
|
|
+ 'Y',
|
|
|
+ 'Z',
|
|
|
+])
|
|
|
|
|
|
// 第几题
|
|
|
-const workIndex = ref<number>(0);
|
|
|
+const workIndex = ref<number>(0)
|
|
|
|
|
|
// 是否显示未提交人员
|
|
|
-const showNoSubmitDetail = ref<boolean>(false);
|
|
|
+const showNoSubmitDetail = ref<boolean>(false)
|
|
|
|
|
|
// 作业详细
|
|
|
-const workDetail = ref<any>({});
|
|
|
+const workDetail = ref<any>({})
|
|
|
|
|
|
// 获取作业详细
|
|
|
const getWorkDetail = async () => {
|
|
|
- if (props.workId) {
|
|
|
- const _res = await api.getWorkDetail({ id: props.workId });
|
|
|
- const _data = _res[0][0];
|
|
|
- if (_data) {
|
|
|
- _data.json = JSON.parse(_data.json);
|
|
|
- workDetail.value = _data;
|
|
|
- }
|
|
|
- }
|
|
|
-};
|
|
|
+ if (props.workId) {
|
|
|
+ const _res = await api.getWorkDetail({ id: props.workId })
|
|
|
+ const _data = _res[0][0]
|
|
|
+ if (_data) {
|
|
|
+ _data.json = JSON.parse(_data.json)
|
|
|
+ workDetail.value = _data
|
|
|
+ choiceQuestionListData.value = choiceQuestionList()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
// 选择题题目数组
|
|
|
-const choiceQuestionList = computed(() => {
|
|
|
- let _result: any[] = [];
|
|
|
- if (workDetail.value && workDetail.value.type == "45") {
|
|
|
- let _workData = workDetail.value.json.testJson;
|
|
|
- _workData.forEach((item: any, index: number) => {
|
|
|
- // 修复 props.workArray 可能为 null 的问题
|
|
|
- item.choiceUser = [];
|
|
|
- item.yes = 0;
|
|
|
- item.no = 0;
|
|
|
- item.checkList.forEach((op: any, oidx: number) =>
|
|
|
- item.choiceUser.push({
|
|
|
- option: op,
|
|
|
- user: [],
|
|
|
- show: false,
|
|
|
- isAnswer: Array.isArray(item.answer)
|
|
|
- ? item.answer.includes(oidx)
|
|
|
- : item.answer === oidx,
|
|
|
- })
|
|
|
- );
|
|
|
- });
|
|
|
- (props.workArray ?? []).forEach(
|
|
|
- (studentWork: any, studentIndex: number) => {
|
|
|
- let _studentContent: any = JSON.parse(
|
|
|
- decodeURIComponent(studentWork.content)
|
|
|
- ).testJson;
|
|
|
- _studentContent.forEach((test: any, testIndex: number) => {
|
|
|
- if (test.userAnswer || test.userAnswer == 0) {
|
|
|
- if (Array.isArray(test.userAnswer)) {
|
|
|
- test.userAnswer.forEach((ch: number) => {
|
|
|
- _workData[testIndex].choiceUser[ch].user.push(studentWork.name);
|
|
|
- });
|
|
|
- if (
|
|
|
- JSON.stringify(
|
|
|
- test.userAnswer.sort((a: number, b: number) => a - b)
|
|
|
- ) == JSON.stringify(_workData[testIndex].answer)
|
|
|
- ) {
|
|
|
- _workData[testIndex].yes += 1;
|
|
|
- } else {
|
|
|
- _workData[testIndex].no += 1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- _workData[testIndex].choiceUser[test.userAnswer].user.push(
|
|
|
- studentWork.name
|
|
|
- );
|
|
|
- if (test.userAnswer == _workData[testIndex].answer) {
|
|
|
- _workData[testIndex].yes += 1;
|
|
|
- } else {
|
|
|
- _workData[testIndex].no += 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- _workData.forEach((item:any)=>{
|
|
|
- item.all = item.yes + item.no;
|
|
|
- if (item.all === 0) {
|
|
|
- item.accuracyRate = 0;
|
|
|
- } else {
|
|
|
- let rate = (item.yes / item.all) * 100;
|
|
|
- item.accuracyRate = Number.isInteger(rate) ? rate : Number(rate.toFixed(2));
|
|
|
- }
|
|
|
- })
|
|
|
+const choiceQuestionList = () => {
|
|
|
+ let _result: any[] = []
|
|
|
+ if (workDetail.value && workDetail.value.type === '45') {
|
|
|
+ const _workData = workDetail.value.json.testJson
|
|
|
+ _workData.forEach((item: any, index: number) => {
|
|
|
+ // 修复 props.workArray 可能为 null 的问题
|
|
|
+ item.choiceUser = []
|
|
|
+ item.yes = 0
|
|
|
+ item.no = 0
|
|
|
+ item.checkList.forEach((op: any, oidx: number) =>
|
|
|
+ item.choiceUser.push({
|
|
|
+ index: serialNumber.value[oidx],
|
|
|
+ option: op,
|
|
|
+ user: [],
|
|
|
+ show: false,
|
|
|
+ isAnswer: Array.isArray(item.answer)
|
|
|
+ ? item.answer.includes(oidx)
|
|
|
+ : item.answer === oidx,
|
|
|
+ })
|
|
|
+ )
|
|
|
+ });
|
|
|
+ (props.workArray ?? []).forEach(
|
|
|
+ (studentWork: any, studentIndex: number) => {
|
|
|
+ const _studentContent: any = JSON.parse(
|
|
|
+ decodeURIComponent(studentWork.content)
|
|
|
+ ).testJson
|
|
|
+ _studentContent.forEach((test: any, testIndex: number) => {
|
|
|
+ if (test.userAnswer || test.userAnswer === 0) {
|
|
|
+ if (Array.isArray(test.userAnswer)) {
|
|
|
+ test.userAnswer.forEach((ch: number) => {
|
|
|
+ _workData[testIndex].choiceUser[ch].user.push(studentWork.name)
|
|
|
+ })
|
|
|
+ if (
|
|
|
+ JSON.stringify(
|
|
|
+ test.userAnswer.sort((a: number, b: number) => a - b)
|
|
|
+ ) === JSON.stringify(_workData[testIndex].answer)
|
|
|
+ ) {
|
|
|
+ _workData[testIndex].yes += 1
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ _workData[testIndex].no += 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ _workData[testIndex].choiceUser[test.userAnswer].user.push(
|
|
|
+ studentWork.name
|
|
|
+ )
|
|
|
+ if (test.userAnswer === _workData[testIndex].answer) {
|
|
|
+ _workData[testIndex].yes += 1
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ _workData[testIndex].no += 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ _workData.forEach((item:any) => {
|
|
|
+ item.all = item.yes + item.no
|
|
|
+ if (item.all === 0) {
|
|
|
+ item.accuracyRate = 0
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ const rate = (item.yes / item.all) * 100
|
|
|
+ item.accuracyRate = Number.isInteger(rate) ? rate : Number(rate.toFixed(2))
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ _result = _workData
|
|
|
+ }
|
|
|
|
|
|
- _result = _workData;
|
|
|
- }
|
|
|
+ return _result
|
|
|
+}
|
|
|
|
|
|
- return _result;
|
|
|
-});
|
|
|
+
|
|
|
+const choiceQuestionListData = ref<any[]>([])
|
|
|
|
|
|
// 选择题题目正确答案
|
|
|
const choiceQuestionAnswer = computed(() => {
|
|
|
- let _result = "";
|
|
|
- if (
|
|
|
- workDetail.value &&
|
|
|
- workDetail.value.type == "45" &&
|
|
|
+ let _result = ''
|
|
|
+ if (
|
|
|
+ workDetail.value &&
|
|
|
+ workDetail.value.type === '45' &&
|
|
|
workDetail.value.json.testJson[workIndex.value]
|
|
|
- ) {
|
|
|
- let _answer = workDetail.value.json.testJson[workIndex.value].answer;
|
|
|
- if (Array.isArray(_answer)) {
|
|
|
- _result = _answer.map((i: any) => serialNumber.value[i]).join("、");
|
|
|
- } else {
|
|
|
- _result = serialNumber.value[_answer];
|
|
|
- }
|
|
|
- }
|
|
|
+ ) {
|
|
|
+ const _answer = workDetail.value.json.testJson[workIndex.value].answer
|
|
|
+ if (Array.isArray(_answer)) {
|
|
|
+ _result = _answer.map((i: any) => serialNumber.value[i]).join('、')
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ _result = [serialNumber.value[_answer]].join('、')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return _result
|
|
|
+})
|
|
|
|
|
|
- return _result;
|
|
|
-});
|
|
|
|
|
|
// //当前题目正确率
|
|
|
// const choiceQuestionAccuracyRate = computed
|
|
|
|
|
|
// 监听作业Id
|
|
|
watch(
|
|
|
- () => props.workId,
|
|
|
- (newVal, oldVal) => {
|
|
|
- console.log("props.workId变化", { newVal, oldVal });
|
|
|
- if (newVal && newVal !== oldVal) {
|
|
|
- getWorkDetail();
|
|
|
- }
|
|
|
- },
|
|
|
- { immediate: true }
|
|
|
-);
|
|
|
-
|
|
|
-//切换题目
|
|
|
-const changeWorkIndex = (type:number) =>{
|
|
|
- if(type===0){
|
|
|
- if(workIndex.value==0)return;
|
|
|
- workIndex.value-=1;
|
|
|
- }else if(type===1){
|
|
|
- if(choiceQuestionList.value.length-1<=workIndex.value)return
|
|
|
- workIndex.value+=1;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-const imageUrl = ref<string>('')
|
|
|
-// Loading 状态
|
|
|
-const imageLoading = ref(false)
|
|
|
-const previewImageLoading = ref(false)
|
|
|
-
|
|
|
-const previewImage = (url:string)=>{
|
|
|
- imageUrl.value = url;
|
|
|
- previewVisible.value = true
|
|
|
-}
|
|
|
-
|
|
|
-// 监听图片URL变化,重置loading状态
|
|
|
-watch(imageUrl, (newUrl) => {
|
|
|
- if (newUrl) {
|
|
|
- imageLoading.value = true
|
|
|
- previewImageLoading.value = true
|
|
|
+ () => props.workId,
|
|
|
+ (newVal, oldVal) => {
|
|
|
+ console.log('props.workId变化', { newVal, oldVal })
|
|
|
+ if (newVal && newVal !== oldVal) {
|
|
|
+ getWorkDetail()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { immediate: true }
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+// 监听已提交的作业
|
|
|
+watch(() => props.workArray, (newVal, oldVal) => {
|
|
|
+ if (newVal && newVal !== oldVal) {
|
|
|
+ choiceQuestionListData.value = choiceQuestionList()
|
|
|
+ // choiceQuestionAnswerData.value = choiceQuestionAnswer()
|
|
|
}
|
|
|
-})
|
|
|
+}, { immediate: true })
|
|
|
|
|
|
-const previewVisible = ref(false)
|
|
|
-const scale = ref(1)
|
|
|
-const rotate = ref(0)
|
|
|
-const offsetX = ref(0)
|
|
|
-const offsetY = ref(0)
|
|
|
-const dragging = ref(false)
|
|
|
-const lastX = ref(0)
|
|
|
-const lastY = ref(0)
|
|
|
-const fitMode = ref(true)
|
|
|
-
|
|
|
-const imgStyle = computed(() => {
|
|
|
- const t = `translate(${offsetX.value}px, ${offsetY.value}px) rotate(${rotate.value}deg) scale(${scale.value})`
|
|
|
- return {
|
|
|
- transform: t
|
|
|
+// 切换题目
|
|
|
+const changeWorkIndex = (type:number) => {
|
|
|
+ if (type === 0) {
|
|
|
+ if (workIndex.value === 0) return
|
|
|
+ workIndex.value -= 1
|
|
|
+ }
|
|
|
+ else if (type === 1) {
|
|
|
+ if (choiceQuestionListData.value.length - 1 <= workIndex.value) return
|
|
|
+ workIndex.value += 1
|
|
|
}
|
|
|
-})
|
|
|
-
|
|
|
-// 图片加载事件处理
|
|
|
-const onImageLoad = () => {
|
|
|
- imageLoading.value = false
|
|
|
-}
|
|
|
-
|
|
|
-const onImageError = () => {
|
|
|
- imageLoading.value = false
|
|
|
- console.error('图片加载失败')
|
|
|
-}
|
|
|
-
|
|
|
-const onPreviewImageLoad = () => {
|
|
|
- previewImageLoading.value = false
|
|
|
-}
|
|
|
-
|
|
|
-const onPreviewImageError = () => {
|
|
|
- previewImageLoading.value = false
|
|
|
- console.error('预览图片加载失败')
|
|
|
-}
|
|
|
-
|
|
|
-const openPreview = () => {
|
|
|
- if (imageLoading.value) return // 如果主图片还在加载,不允许打开预览
|
|
|
- previewVisible.value = true
|
|
|
- previewImageLoading.value = true // 预览时重新显示loading
|
|
|
- nextTickFit()
|
|
|
}
|
|
|
|
|
|
-const closePreview = () => {
|
|
|
- previewVisible.value = false
|
|
|
+// 切换题目展示所有人选项
|
|
|
+const changeShow = (op: any, idx: number) => {
|
|
|
+ choiceQuestionListData.value[workIndex.value].choiceUser[idx].show = !choiceQuestionListData.value[workIndex.value].choiceUser[idx].show
|
|
|
}
|
|
|
|
|
|
-const zoomStep = 0.2
|
|
|
-const minScale = 0.2
|
|
|
-const maxScale = 6
|
|
|
-
|
|
|
-const zoomIn = () => {
|
|
|
- fitMode.value = false; scale.value = Math.min(maxScale, +(scale.value + zoomStep).toFixed(2))
|
|
|
-}
|
|
|
-const zoomOut = () => {
|
|
|
- fitMode.value = false; scale.value = Math.max(minScale, +(scale.value - zoomStep).toFixed(2))
|
|
|
-}
|
|
|
-const resetTransform = () => {
|
|
|
- scale.value = 1; rotate.value = 0; offsetX.value = 0; offsetY.value = 0; fitMode.value = true; nextTickFit()
|
|
|
-}
|
|
|
-const rotateLeft = () => {
|
|
|
- rotate.value = (rotate.value - 90) % 360
|
|
|
-}
|
|
|
-const rotateRight = () => {
|
|
|
- rotate.value = (rotate.value + 90) % 360
|
|
|
+const lookDetail = () => {
|
|
|
+ // emit('openChoiceQuestionDetail', props.slideIndex)
|
|
|
}
|
|
|
|
|
|
-const toggleZoom = () => {
|
|
|
- fitMode.value = false
|
|
|
- scale.value = scale.value >= 1.8 ? 1 : 2
|
|
|
+const previewImageToolRef = ref<any>(null)
|
|
|
+const previewImage = (url:string) => {
|
|
|
+ previewImageToolRef.value.previewImage(url)
|
|
|
}
|
|
|
|
|
|
-const toggleFit = () => {
|
|
|
- fitMode.value = !fitMode.value
|
|
|
- nextTickFit()
|
|
|
-}
|
|
|
|
|
|
-const nextTickFit = () => {
|
|
|
- // 适应屏幕时复位位置与缩放
|
|
|
- if (fitMode.value) {
|
|
|
- scale.value = 1
|
|
|
- offsetX.value = 0
|
|
|
- offsetY.value = 0
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const onWheel = (e: WheelEvent) => {
|
|
|
- if (e.deltaY > 0) zoomOut()
|
|
|
- else zoomIn()
|
|
|
-}
|
|
|
+defineExpose({
|
|
|
+ workDetail,
|
|
|
+ choiceQuestionListData,
|
|
|
+ workIndex,
|
|
|
+ workArray: props.workArray
|
|
|
+})
|
|
|
|
|
|
-const onDragStart = (e: MouseEvent) => {
|
|
|
- dragging.value = true
|
|
|
- lastX.value = e.clientX
|
|
|
- lastY.value = e.clientY
|
|
|
-}
|
|
|
-const onDragMove = (e: MouseEvent) => {
|
|
|
- if (!dragging.value) return
|
|
|
- const dx = e.clientX - lastX.value
|
|
|
- const dy = e.clientY - lastY.value
|
|
|
- lastX.value = e.clientX
|
|
|
- lastY.value = e.clientY
|
|
|
- offsetX.value += dx
|
|
|
- offsetY.value += dy
|
|
|
-}
|
|
|
-const onDragEnd = () => {
|
|
|
- dragging.value = false
|
|
|
-}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
@@ -583,6 +470,14 @@ const onDragEnd = () => {
|
|
|
margin-top: 20px;
|
|
|
font-size: 14px;
|
|
|
font-weight: 600;
|
|
|
+ img{
|
|
|
+ width: auto;
|
|
|
+ max-width: 100%;
|
|
|
+ height: auto;
|
|
|
+ object-fit: cover;
|
|
|
+ cursor: pointer;
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
}
|
|
|
.atr_t45a_item {
|
|
|
width: 100%;
|