瀏覽代碼

修复子题bug

shmily1213 2 周之前
父節點
當前提交
2d1de8944f

+ 77 - 59
src/composables/useExam.ts

@@ -65,14 +65,9 @@ export const useExam = () => {
   const subQuestionIndex = ref<number>(0);
   // 包含状态的问题列表
   const stateQuestionList = computed(() => {
-    function parseQuestion(qs: Study.Question, parentIndex: number) {
+    function parseQuestion(qs: Study.Question) {
       if (qs.subQuestions && qs.subQuestions.length > 0) {
         qs.subQuestions.forEach((item, index) => {
-          // item.isSubQuestion = true;
-          // item.parentId = qs.id;
-          // item.parentTypeId = qs.typeId;
-          // item.subIndex = index;
-          // item.parentIndex = parentIndex;
           item.isDone = isDone(item);
         });
       } else {
@@ -85,13 +80,21 @@ export const useExam = () => {
     }
     console.log('重新计算')
     return questionList.value.map((item, index) => {
-      return parseQuestion(item, index)
+      return parseQuestion(item)
       // return {
       //   ...item,
       //   // isDone: isDone(item)
       // };
     });
   });
+  const flatQuestionList = computed(() => {
+    return questionList.value.flatMap(item => {
+      if (item.subQuestions && item.subQuestions.length > 0) {
+        return item.subQuestions.flat();
+      }
+      return item;
+    });
+  });
   const groupedQuestionList = computed(() => {
     // 状态:已做、未做、是否不会、是否标记,整体按照题型分组
     const state = questionTypeOrder.map(type => {
@@ -103,41 +106,30 @@ export const useExam = () => {
         }[]
       }
     });
-    let offset = 0;
-    function addQuestion(qs: Study.Question, index: number) {
-      if (qs.subQuestions && qs.subQuestions.length > 0) {
-        qs.subQuestions.forEach((subQs, subIndex) => {
-          offset++;
-          addQuestion(subQs, index + subIndex);
+    const arr: Study.Question[] = [];
+    flatQuestionList.value.forEach((qs, index) => {
+      let group;
+      if (qs.isSubQuestion) {
+        group = state.find(item => item.type === qs.parentTypeId);
+      } else {
+        group = state.find(item => item.type === qs.typeId);
+      }
+      if (group) {
+        group.list.push({
+          question: qs,
+          index
         });
       } else {
-        let group;
-        if (qs.isSubQuestion) {
-          group = state.find(item => item.type === qs.parentTypeId);
-        } else {
-          group = state.find(item => item.type === qs.typeId);
-        }
-        if (group) {
-          group.list.push({
+        state.push({
+          type: qs.typeId,
+          list: [{
             question: qs,
             index
-          });
-        } else {
-          state.push({
-            type: qs.typeId,
-            list: [{
-              question: qs,
-              index
-            }]
-          });
-        }
+          }]
+        });
       }
-    }
-    console.log(stateQuestionList.value.length)
-    for (let i = 0; i <= stateQuestionList.value.length - 1; i++) {
-      const qs = stateQuestionList.value[i];
-      addQuestion(qs, i + offset);
-    }
+    });
+    console.log('group data', arr)
     return state;
   });
   const isAllDone = computed(() => {
@@ -301,11 +293,43 @@ export const useExam = () => {
     examDuration.value = duration;
     practiceDuration.value = duration;
   }
+  const processArray = (arr: Study.Question[]) => {
+    let offset = 0;
+    return arr.map((item: Study.Question, index: number) => {
+      const result = {
+        ...item,
+        index: index
+      };
+      // 如果有子节点,处理子节点并计算subIndex
+      if (item.subQuestions && Array.isArray(item.subQuestions) && item.subQuestions.length > 0) {
+        // 为当前节点设置offset
+        result.offset = offset;
+        result.subQuestions = item.subQuestions.map((child, childIndex) => ({
+          ...child,
+          subIndex: childIndex,
+          isSubQuestion: true,
+          parentId: item.id,
+          parentTypeId: item.typeId,
+          parentIndex: index,
+          index: index,
+          virtualIndex: index + result.offset + childIndex
+        }));
+        // 更新offset,累加当前节点的子节点数量
+        offset += (item.subQuestions.length - 1);
+      } else {
+        // 如果没有子节点,设置offset为当前累计值
+        result.offset = offset;
+        result.isSubQuestion = false;
+        result.virtualIndex = result.index + offset;
+      }
+      return result;
+    });
+  }
   const setQuestionList = (list: Study.ExamineeQuestion[]) => {
     const orders = ['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'];
     // 数据预处理
     // 1、给每个项目补充额外字段
-    const transerQuestion = (item: Study.ExamineeQuestion): Study.Question => {
+    const transerQuestion = (item: Study.ExamineeQuestion, index: number): Study.Question => {
       return {
         ...item,
         // 处理没有题型的大题,统一作为阅读题
@@ -321,28 +345,14 @@ export const useExam = () => {
           } as Study.QuestionOption
         }) || [],
         isDone: false,
-        isCorrect: isQuestionCorrect(item)
+        isCorrect: isQuestionCorrect(item),
+        offset: 0,
+        index: index,
+        virtualIndex: 0
       } as Study.Question
     }
-    const parseQuestion = (qs: Study.Question, parentIndex: number) => {
-      if (qs.subQuestions && qs.subQuestions.length > 0) {
-        qs.subQuestions.forEach((item, index) => {
-          item.isSubQuestion = true;
-          item.parentId = qs.id;
-          item.parentTypeId = qs.typeId;
-          item.subIndex = index;
-          item.parentIndex = parentIndex;
-          // item.isDone = isDone(item);
-        });
-      } else {
-        qs.isSubQuestion = false;
-        // qs.isDone = isDone(qs);
-      }
-      return qs;
-    }
-    const arr: Study.Question[] = list.map((item, index) => {
-      return parseQuestion(transerQuestion(item), index);
-    });
+    console.log(list.map((item, index) => transerQuestion(item, index)), 777)
+    const arr: Study.Question[] = processArray(list.map((item, index) => transerQuestion(item, index)));
     questionList.value = arr;
   }
   const reset = () => {
@@ -370,6 +380,7 @@ export const useExam = () => {
     interval = null;
   }
   const setSubQuestionIndex = (index: number) => {
+    console.log(index, 1000)
     subQuestionIndex.value = index;
   }
   watch(() => currentIndex.value, (val) => {
@@ -378,7 +389,13 @@ export const useExam = () => {
     immediate: false
   });
   watch([() => currentIndex.value, () => subQuestionIndex.value], (val) => {
-    virtualCurrentIndex.value = val[0] + val[1];
+    const qs = questionList.value[val[0]];
+    setTimeout(() => {
+      console.log(qs, val[1], 999)
+      console.log(11111, flatQuestionList.value[virtualCurrentIndex.value])
+    }, 500);
+    virtualCurrentIndex.value = qs.index + qs.offset + val[1];
+
   }, {
     immediate: false
   });
@@ -386,6 +403,7 @@ export const useExam = () => {
     questionList,
     groupedQuestionList,
     stateQuestionList,
+    flatQuestionList,
     favoriteList,
     notKnowList,
     markList,

+ 42 - 31
src/pagesStudy/pages/exam-start/components/question-item.vue

@@ -47,7 +47,7 @@
       </view>
       <!-- 阅卷模式下显示答案 -->
       <template v-if="readonly">
-        <view class="answer-wrap mt-40 rounded-8 pt-60 pb-40 flex items-center text-center relative">
+        <view v-if="question.subQuestions.length === 0" class="answer-wrap mt-40 rounded-8 pt-60 pb-40 flex items-center text-center relative">
           <ie-image v-if="question.isCorrect" src="/pagesStudy/static/image/icon-answer-correct.png"
             class="absolute top-0 left-1/2 -translate-x-1/2 w-222 h-64" />
           <ie-image v-else src="/pagesStudy/static/image/icon-answer-incorrect.png"
@@ -64,7 +64,7 @@
             <view class="mt-4 text-26">我的答案</view>
           </view>
           <view v-if="isOnlySubjective" class="text-left mt-10 px-20">
-            <uv-parse :content="'正确答案:' + question.answer2"></uv-parse>
+            <uv-parse :content="'参考答案:' + question.answer2"></uv-parse>
           </view>
         </view>
       </template>
@@ -81,13 +81,14 @@
           <view class="px-40 py-8 rounded-full"
             :class="[subIndex === subQuestionIndex ? 'bg-[#EBF9FF] text-primary font-bold' : 'bg-back']"
             v-for="(subQuestion, subIndex) in question.subQuestions" @click="changeSubQuestion(subIndex)">
-            {{ index + subIndex + 1 }}
+            {{ question.index + question.offset + subIndex + 1 }}
           </view>
         </view>
       </scroll-view>
       <view v-if="subQuestion">
-        <question-item :question="subQuestion" :readonly="readonly" :is-sub-question="true" :index="index"
-          :total="question.subQuestions.length" @select="handleSelectOption" @notKnow="handleSelectNotKnow" />
+        <question-item :question="subQuestion" :parent-question="question" :readonly="readonly" :is-sub-question="true"
+          :index="index" :total="question.subQuestions.length" @select="handleSelectOption"
+          @notKnow="handleSelectNotKnow" />
       </view>
     </view>
   </view>
@@ -101,6 +102,7 @@ import { NEXT_QUESTION, PREV_QUESTION, NEXT_QUESTION_QUICKLY, PREV_QUESTION_QUIC
 const { questionTypeDesc, isOptionCorrect } = useExam();
 const props = defineProps<{
   question: Study.Question;
+  parentQuestion?: Study.Question;
   readonly?: boolean;
   isSubQuestion?: boolean;
   index: number;
@@ -132,7 +134,9 @@ const getStyleClass = (option: Study.QuestionOption) => {
     return isSelected(option) ? 'question-option-selected' : '';
   }
   let customClass = '';
-  const { answers, answer1, answer2 } = props.question;
+  let { answers, answer1 } = props.question;
+  answers = answers?.filter(item => item !== ' ') || [];
+  answer1 = answer1 || ''
   if ([EnumQuestionType.SINGLE_CHOICE, EnumQuestionType.JUDGMENT].includes(props.question.typeId)) {
     if (answer1.includes(option.no)) {
       customClass = 'question-option-correct';
@@ -157,17 +161,7 @@ const getStyleClass = (option: Study.QuestionOption) => {
   // console.log(props.question, option)
   return customClass;
 };
-// const isOptionCorrect = (option: Study.QuestionOption) => {
-//   const { answers, answer1, answer2 } = props.question;
-//   if ([EnumQuestionType.SINGLE_CHOICE, EnumQuestionType.JUDGMENT].includes(props.question.typeId)) {
-//     return answer1.includes(option.no);
-//   } else if ([EnumQuestionType.MULTIPLE_CHOICE].includes(props.question.typeId)) {
-//     return answer1.includes(option.no);
-//   } else if (props.question.typeId === EnumQuestionType.SUBJECTIVE) {
-//     return answers.includes(option.no);
-//   }
-//   return false;
-// }
+
 const isOptionIncorrect = (option: Study.QuestionOption) => {
   const { answers, answer1 } = props.question;
   return answers.includes(option.no) && !answer1.includes(option.no);
@@ -218,10 +212,14 @@ const handleSelect = (option: Study.QuestionOption) => {
       props.question.answers.push(option.no);
     }
   }
-  
-  props.question.isNotKnow = false;
-  checkIsDone();
 
+  props.question.isNotKnow = false;
+  checkIsDone(props.question);
+  if (props.question.isSubQuestion) {
+    // 同时检查父题是否已完成
+    checkIsDone(props.parentQuestion);
+  }
+  console.log(333)
   if (props.isSubQuestion) {
     emit('select', props.question);
   } else {
@@ -229,11 +227,14 @@ const handleSelect = (option: Study.QuestionOption) => {
   }
 }
 
-const checkIsDone = () => {
-  if (props.question.subQuestions && props.question.subQuestions.length > 0) {
-    props.question.isDone = props.question.subQuestions.every(q => q.answers.length > 0 || q.isNotKnow);
+const checkIsDone = (question?: Study.Question) => {
+  if (!question) {
+    return;
+  }
+  if (question?.subQuestions && question?.subQuestions.length > 0) {
+    question.isDone = question.subQuestions.every(q => q.answers.length > 0 || q.isNotKnow);
   } else {
-    props.question.isDone = props.question.answers.length > 0 || props.question.isNotKnow;
+    question.isDone = question.answers.length > 0 || question.isNotKnow;
   }
 }
 // 子题选中方法
@@ -245,15 +246,25 @@ const handleSelectNotKnow = () => {
 }
 // 查找是否有子题没有做,有的话就自动滚动到目标处
 const findNotDoneSubQuestion = () => {
-  const notDoneSubQuestion = props.question.subQuestions.find(q => !q.isDone);
-  if (notDoneSubQuestion) {
-    if (notDoneSubQuestion.subIndex !== undefined) {
-      changeSubQuestion(notDoneSubQuestion.subIndex);
-    }
-  } else {
-    // 否则切换到下一题
+  console.log(props)
+  if (props.question.subQuestions.length - 1 === props.subQuestionIndex) {
     changeQuestion();
+  } else {
+    changeSubQuestion((props.subQuestionIndex ?? 0) + 1);
   }
+  // const notDoneSubQuestion = props.question.subQuestions.find(q => !q.isDone);
+  // if (notDoneSubQuestion) {
+  //   if (notDoneSubQuestion.subIndex !== undefined) {
+  //     changeSubQuestion(notDoneSubQuestion.subIndex);
+  //   }
+  // } else {
+  //   // 是否当前是最后一个子题
+  //   if (props.question.subQuestions.length - 1 === props.subQuestionIndex) {
+  //     changeQuestion();
+  //   } else {
+  //     changeSubQuestion(props.subQuestionIndex ?? 0 + 1);
+  //   }
+  // }
 }
 const changeSubQuestion = (index: number) => {
   emit('changeSubQuestion', index);

+ 45 - 15
src/pagesStudy/pages/exam-start/exam-start.vue

@@ -124,7 +124,7 @@ import { NEXT_QUESTION, PREV_QUESTION, NEXT_QUESTION_QUICKLY, PREV_QUESTION_QUIC
 const userStore = useUserStore();
 // import { Examinee, ExamPaper, ExamPaperSubmit } from '@/types/study';
 const { prevData, transferBack, transferTo } = useTransferPage();
-const { setQuestionList, questionList, groupedQuestionList, questionTypeDesc,
+const { setQuestionList, questionList, flatQuestionList, groupedQuestionList, questionTypeDesc,
   currentIndex, totalCount, virtualCurrentIndex, virtualTotalCount, subQuestionIndex, setSubQuestionIndex,
   doneCount,
   notDoneCount, isAllDone, nextQuestion, prevQuestion, nextQuestionQuickly, prevQuestionQuickly, swiperDuration,
@@ -226,6 +226,7 @@ const currentQuestion = computed(() => {
   return qs || {};
 });
 const hanadleNavigate = (question: Study.Question, index: number) => {
+  console.log(question, index)
   if (question.isSubQuestion) {
     changeIndex(question.parentIndex || 0);
     setTimeout(() => {
@@ -382,14 +383,26 @@ const handleSubmit = (tempSave: boolean = false) => {
       isDone: tempSave ? isAllDone.value : true,
       duration: practiceDuration.value
     } as Study.ExamPaperSubmit;
-    console.log(params, 123)
+    console.log('提交试卷参数', params)
     commitExamineePaper(params);
     if (isExam.value) {
-      setTimeout(async () => {
+      if (!tempSave) {
+        setTimeout(async () => {
+          uni.$ie.hideLoading();
+          await nextTick();
+          transferTo('/pagesStudy/pages/simulation-analysis/simulation-analysis', {
+            data: {
+              examineeId: examineeId.value
+            },
+            type: 'redirectTo'
+          });
+        }, 2500);
+      } else {
         uni.$ie.hideLoading();
-        await nextTick();
-        uni.navigateBack();
-      }, !tempSave ? 2500 : 0);
+        nextTick(() => {
+          transferBack();
+        });
+      }
     } else {
       setTimeout(async () => {
         uni.$ie.hideLoading();
@@ -409,6 +422,7 @@ const handleSubmit = (tempSave: boolean = false) => {
 }
 
 const handleChangeSubQuestion = (index: number) => {
+  console.log(index, 111)
   setSubQuestionIndex(index);
 }
 const handleChangeQuestion = (question: Study.Question) => {
@@ -425,9 +439,11 @@ const handleChangeQuestion = (question: Study.Question) => {
       return;
     }
   } else {
-    if (question.isDone) {
-      nextQuestion?.();
-    }
+    console.log(question, 222)
+    // if (question.isDone) {
+    //   nextQuestion?.();
+    // }
+    nextQuestion?.();
   }
 }
 /**
@@ -439,8 +455,9 @@ const restoreQuestion = (savedQuestion: Study.ExamineeQuestion[], fullQuestion:
   if (!savedQuestion) {
     return fullQuestion;
   }
-  for (const item of fullQuestion) {
-    const savedQs = savedQuestion.find(q => q.id === item.id);
+  for (let index = 0; index < fullQuestion.length; index++) {
+    const item = fullQuestion[index];
+    const savedQs = savedQuestion[index]
     if (savedQs) {
       if (savedQs.answers) {
         item.answers = savedQs.answers.filter(ans => ans.trim());
@@ -452,6 +469,7 @@ const restoreQuestion = (savedQuestion: Study.ExamineeQuestion[], fullQuestion:
       item.isNotKnow = savedQs.isNotKnow;
       item.parse = savedQs.parse;
       if (item.subQuestions) {
+        console.log('对比', JSON.parse(JSON.stringify(savedQs.subQuestions)), JSON.parse(JSON.stringify(item.subQuestions)))
         restoreQuestion(savedQs.subQuestions, item.subQuestions);
       }
     }
@@ -502,13 +520,25 @@ const combinePaperData = async (examinee: Study.Examinee, paperType: EnumPaperTy
     });
     paperData.value = res.data;
     paperData.value.questions = restoreQuestion(examinee.questions, res.data.questions);
+    console.log('初始化数据', paperData.value.questions)
     setQuestionList(paperData.value.questions);
     setDuration(examinee.duration || 0);
     await nextTick();
-    // TODO:子题跳转
-    const questionIndex = prevData.value.questionId ? paperData.value.questions.findIndex(item => item.id === prevData.value.questionId) : 0;
-    changeIndex(questionIndex);
-    console.log(groupedQuestionList.value, 123)
+    const targetQuestion = flatQuestionList.value.find(item => item.id === prevData.value.questionId);
+    if (targetQuestion) {
+      changeIndex(targetQuestion.index);
+    } else {
+      changeIndex(0);
+    }
+    setTimeout(() => {
+      if (targetQuestion?.isSubQuestion) {
+        console.log(targetQuestion.subIndex, 888)
+        setSubQuestionIndex(targetQuestion.subIndex || 0);
+      }
+    }, 50);
+    // const questionIndex = prevData.value.questionId ? paperData.value.questions.findIndex(item => item.id === prevData.value.questionId) : 0;
+    // changeIndex(questionIndex);
+    console.log(groupedQuestionList.value, 123, flatQuestionList.value)
     await new Promise(resolve => setTimeout(resolve, 50));
     await nextTick();
     isReady.value = true;

+ 7 - 7
src/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail.vue

@@ -1,7 +1,7 @@
 <template>
   <ie-page bg-color="#F6F8FA" :fix-height="true">
     <ie-navbar :title="pageTitle" />
-    <view class="relative z-3 pt-30 pb-20 mx-30">
+    <view v-if="examineeData" class="relative z-3 pt-30 pb-20 mx-30">
       <view class="bg-white rounded-15 px-20 pb-1">
         <rate-chart :value="rightRate" />
         <view class="h-1 bg-[#E6E6E6] my-20"></view>
@@ -48,13 +48,13 @@ const { prevData, transferTo } = useTransferPage<Transfer.PracticeResult, {}>();
 
 
 const rightRate = computed(() => {
-  const { totalCount = 0, wrongCount = 0 } = examineeData.value;
+  const { totalCount = 0, wrongCount = 0 } = examineeData.value || {};
   return Math.round((totalCount - wrongCount) / totalCount * 100) || 0;
 });
 const paperName = computed(() => {
   return '知识点练习-' + prevData.value.name;
 });
-const examineeData = ref<Study.Examinee>({} as Study.Examinee);
+const examineeData = ref<Study.Examinee>();
 const pageTitle = computed(() => {
   // return prevData.value.directed ? '定向练习结果' : '全量练习结果';
   return '练习结果';
@@ -73,7 +73,7 @@ const formatTime = (time: number) => {
     return `${minutes}分${seconds}秒`;
   }
 };
-const handleDetail = (item: Study.ExamineeQuestion) => {
+const handleDetail = (item: Study.Question) => {
   console.log(item, examineeData)
   transferTo('/pagesStudy/pages/exam-start/exam-start', {
     data: {
@@ -82,13 +82,13 @@ const handleDetail = (item: Study.ExamineeQuestion) => {
       readonly: true,
       questionId: item.id,
       simulationInfo: {
-        examineeId: examineeData.value.examineeId,
+        examineeId: examineeData.value?.examineeId,
       }
     }
   });
 }
 const handleStartPractice = () => {
-  const { knowledgeId } = examineeData.value;
+  const { knowledgeId } = examineeData.value || {};
   transferTo('/pagesStudy/pages/exam-start/exam-start', {
     data: {
       name: paperName.value,
@@ -108,7 +108,7 @@ const handleViewAnalysis = () => {
       paperType: EnumPaperType.SIMULATED,
       readonly: true,
       simulationInfo: {
-        examineeId: examineeData.value.examineeId,
+        examineeId: examineeData.value?.examineeId,
       }
     }
   });

+ 48 - 46
src/pagesStudy/pages/simulation-analysis/components/exam-stat.vue

@@ -38,10 +38,10 @@
       </view>
     </view>
     <view class="mt-30 grid grid-cols-5 gap-x-10 gap-y-30 place-items-center">
-      <view class="question-item" v-for="item in questionList" :key="item.id"
-        :class="[item.isNotAnswer ? 'is-unanswered' : (item.isRight ? 'is-correct' : 'is-incorrect')]"
+      <view class="question-item" v-for="item in flatQuestionList" :key="item.id"
+        :class="[item.isNotAnswer ? 'is-unanswered' : (item.isCorrect ? 'is-correct' : 'is-incorrect')]"
         @click="handleDetail(item)">
-        <view class="text-36 font-bold">{{ item.originalIndex }}</view>
+        <view class="text-36 font-bold">{{ item.virtualIndex + 1 }}</view>
       </view>
     </view>
   </view>
@@ -52,9 +52,9 @@ import { useTransferPage } from '@/hooks/useTransferPage';
 import { useExam } from '@/composables/useExam';
 import { Study } from '@/types';
 const { transferTo } = useTransferPage();
-const { isQuestionCorrect } = useExam();
+const { isQuestionCorrect, questionList, setQuestionList, flatQuestionList } = useExam();
 const emit = defineEmits<{
-  (e: 'detail', item: Study.ExamineeQuestion): void;
+  (e: 'detail', item: Study.Question): void;
 }>();
 const props = defineProps<{
   data: Study.Examinee;
@@ -72,48 +72,48 @@ const stats = computed(() => {
   return props.data.stats || {};
 });
 const totalQuestions = computed(() => {
-  return (props.data.questions || []).length;
+  return (flatQuestionList.value || []).length;
 });
 const filterTypes = ref<('correct' | 'incorrect' | 'unanswered')[]>(['correct', 'incorrect', 'unanswered']);
-const questionList = computed(() => {
-  const list: QuestionItem[] = [];
-  let offset = 0;
-  (props.data.questions || []).forEach((item, index) => {
-    if (item.subQuestions && item.subQuestions.length > 0) {
-      item.subQuestions.forEach((subItem, subIndex) => {
-        offset++;
-        list.push({
-          ...subItem,
-          originalIndex: index + subIndex + 1, // 保存原始序号
-          isRight: isQuestionCorrect(subItem),
-          isNotAnswer: !subItem.answers.filter(item => item !== ' ').length
-        });
-      });
-    } else {
-      list.push({
-        ...item,
-        originalIndex: index + offset + 1, // 保存原始序号
-        isRight: isQuestionCorrect(item),
-        isNotAnswer: !item.answers.filter(item => item !== ' ').length
-      });
-    }
-  });
-  return list.filter((item: QuestionItem) => {
-    // 判断是否答对
-    if (item.isRight && filterTypes.value.includes('correct')) {
-      return true;
-    }
-    // 判断是否答错(答了但是错了)
-    if (!item.isRight && !item.isNotAnswer && filterTypes.value.includes('incorrect')) {
-      return true;
-    }
-    // 判断是否未答
-    if (item.isNotAnswer && filterTypes.value.includes('unanswered')) {
-      return true;
-    }
-    return false;
-  });
-});
+// const questionList = computed(() => {
+//   const list: QuestionItem[] = [];
+//   let offset = 0;
+//   (props.data.questions || []).forEach((item, index) => {
+//     if (item.subQuestions && item.subQuestions.length > 0) {
+//       item.subQuestions.forEach((subItem, subIndex) => {
+//         offset++;
+//         list.push({
+//           ...subItem,
+//           originalIndex: index + subIndex + 1, // 保存原始序号
+//           isRight: isQuestionCorrect(subItem),
+//           isNotAnswer: !subItem.answers.filter(item => item !== ' ').length
+//         });
+//       });
+//     } else {
+//       list.push({
+//         ...item,
+//         originalIndex: index + offset + 1, // 保存原始序号
+//         isRight: isQuestionCorrect(item),
+//         isNotAnswer: !item.answers.filter(item => item !== ' ').length
+//       });
+//     }
+//   });
+//   return list.filter((item: QuestionItem) => {
+//     // 判断是否答对
+//     if (item.isRight && filterTypes.value.includes('correct')) {
+//       return true;
+//     }
+//     // 判断是否答错(答了但是错了)
+//     if (!item.isRight && !item.isNotAnswer && filterTypes.value.includes('incorrect')) {
+//       return true;
+//     }
+//     // 判断是否未答
+//     if (item.isNotAnswer && filterTypes.value.includes('unanswered')) {
+//       return true;
+//     }
+//     return false;
+//   });
+// });
 
 const handleFilter = (type: 'correct' | 'incorrect' | 'unanswered') => {
   if (filterTypes.value.includes(type)) {
@@ -123,9 +123,11 @@ const handleFilter = (type: 'correct' | 'incorrect' | 'unanswered') => {
   }
   console.log(filterTypes.value)
 }
-const handleDetail = (item: Study.ExamineeQuestion) => {
+const handleDetail = (item: Study.Question) => {
+  console.log(item, flatQuestionList.value)
   emit('detail', item);
 }
+setQuestionList(props.data.questions);
 </script>
 <style lang="scss" scoped>
 .question-item {

+ 5 - 2
src/pagesStudy/pages/simulation-analysis/components/score-stat.vue

@@ -1,5 +1,5 @@
 <template>
-  <view class="shadow-card sticky bottom-20 px-16 py-20 bg-white rounded-15 mt-20">
+  <view class="shadow-card sticky bottom-20 px-16 py-26 bg-white rounded-15 mt-20">
     <view class="text-30 text-fore-title font-bold">得分分布</view>
     <view class="mt-20 mx-10 flex items-center bg-back rounded-10 py-30">
       <view class="flex-1 text-center">
@@ -11,7 +11,7 @@
         <view class="mt-5 text-28 text-fore-light">平均分</view>
       </view>
       <view class="flex-1 text-center">
-        <view class="text-40 text-fore-title font-bold">{{ stats.hitRate }}%</view>
+        <view class="text-40 text-fore-title font-bold">{{ hitRate }}%</view>
         <view class="mt-5 text-28 text-fore-light">击败考生</view>
       </view>
     </view>
@@ -26,5 +26,8 @@ const props = defineProps<{
 const stats = computed(() => {
   return props.data.stats || {};
 });
+const hitRate = computed(() => {
+  return stats.value.hitRate === 100 ? 99 : stats.value.hitRate;
+});
 </script>
 <style lang="scss" scoped></style>

+ 6 - 6
src/pagesStudy/pages/simulation-analysis/simulation-analysis.vue

@@ -5,7 +5,7 @@
       <ie-image :is-oss="true" src="/study-bg11.png" custom-class="w-full h-[545rpx] absolute top-0 left-0 z-0" />
       <ie-image :is-oss="true" src="/study-bg12.png" custom-class="w-308 h-302 absolute top-57 right-14 z-1" />
       <ie-image :is-oss="true" src="/study-title4.png" custom-class="w-282 h-64 absolute top-126 left-72 z-2" />
-      <view class="relative z-3 pt-244 pb-20 mx-30">
+      <view v-if="examineeData" class="relative z-3 pt-244 pb-20 mx-30">
         <view class="bg-white rounded-15 px-20 pb-1">
           <rate-chart :value="rightRate" />
           <view class="h-1 bg-[#E6E6E6] my-20"></view>
@@ -43,12 +43,12 @@ import { useTransferPage } from '@/hooks/useTransferPage';
 import { Study } from '@/types';
 import { EnumPaperType, EnumQuestionType } from '@/common/enum';
 const { prevData, transferTo } = useTransferPage();
-const examineeData = ref<Study.Examinee>({} as Study.Examinee);
+const examineeData = ref<Study.Examinee>();
 const paperName = computed(() => {
-  return '模拟考试-' + examineeData.value.subjectName;
+  return '模拟考试-' + examineeData.value?.subjectName;
 });
 const rightRate = computed(() => {
-  const { totalCount = 0, wrongCount = 0 } = examineeData.value;
+  const { totalCount = 0, wrongCount = 0 } = examineeData.value || {};
   return Math.round((totalCount - wrongCount) / totalCount * 100) || 0;
 });
 
@@ -66,7 +66,7 @@ const formatTime = (time: number) => {
     return `${minutes}分${seconds}秒`;
   }
 };
-const handleDetail = (item: Study.ExamineeQuestion) => {
+const handleDetail = (item: Study.Question) => {
   transferTo('/pagesStudy/pages/exam-start/exam-start', {
     data: {
       name: paperName.value,
@@ -74,7 +74,7 @@ const handleDetail = (item: Study.ExamineeQuestion) => {
       questionId: item.id,
       paperType: EnumPaperType.SIMULATED,
       simulationInfo: {
-        examineeId: examineeData.value.examineeId
+        examineeId: examineeData.value?.examineeId
       }
     }
   });

+ 7 - 1
src/types/study.ts

@@ -99,6 +99,7 @@ export interface QuestionState {
   isDone?: boolean;
   isMark?: boolean;
   isNotKnow?: boolean;
+  isNotAnswer?: boolean;
   isFavorite?: boolean;
   isCorrect?: boolean;
   progress?: number;
@@ -204,11 +205,16 @@ export interface Question extends QuestionState {
   parse?: string;
   subQuestions: Question[];
   //
+  index: number; // 索引
+  offset: number; // 偏移量
+  isSubQuestion?: boolean; // 是否是子题
+  //
   parentIndex?: number; // 父题索引
   parentId?: number; // 父题ID
   parentTypeId?: number; // 父题类型
-  isSubQuestion?: boolean; // 是否是子题
   subIndex?: number; // 子题索引
+  //
+  virtualIndex: number; // 虚拟索引
   showParse?: boolean; // 是否显示解析
 }