shmily1213 1 месяц назад
Родитель
Сommit
a878d068c1

+ 3 - 1
src/main.ts

@@ -57,7 +57,9 @@ export function createApp() {
         statusBarHeight: { default: 0 }
         statusBarHeight: { default: 0 }
       },
       },
       tabs: {
       tabs: {
-        activeStyle: { default: () => ({ color: 'var(--primary-color)' }) }
+        activeStyle: { default: () => ({ color: 'var(--primary-color)' }) },
+        autoScroll: { default: true }, // current 改变时是否自动滚动到中间
+        animationEnabled: { default: true } // 滚动时是否带有动画
       },
       },
       steps: {
       steps: {
         activeColor: { default: 'var(--primary-color)' }
         activeColor: { default: 'var(--primary-color)' }

+ 1 - 1
src/pagesStudy/pages/exam-start/components/exam-stats-card.vue

@@ -47,7 +47,7 @@
                         'is-correct': isViewMode && qs.isCorrect,
                         'is-correct': isViewMode && qs.isCorrect,
                         'is-incorrect': isViewMode && !qs.isCorrect,
                         'is-incorrect': isViewMode && !qs.isCorrect,
                       }">
                       }">
-                      <text class="z-1 font-bold text-32">{{ qs.index + 1 }}</text>
+                      <text class="z-1 font-bold text-32">{{ qs.virtualIndex + 1 }}</text>
                       <ie-image v-if="qs.isMark" src="/pagesStudy/static/image/icon-mark-active.png"
                       <ie-image v-if="qs.isMark" src="/pagesStudy/static/image/icon-mark-active.png"
                         custom-class="absolute -top-12 left-14 w-28 h-28 z-1" mode="aspectFill" />
                         custom-class="absolute -top-12 left-14 w-28 h-28 z-1" mode="aspectFill" />
                     </view>
                     </view>

+ 44 - 24
src/pagesStudy/pages/exam-start/components/question-item.vue

@@ -7,16 +7,16 @@
       <question-parse :question="question" />
       <question-parse :question="question" />
     </template>
     </template>
     <view v-else class="mt-20">
     <view v-else class="mt-20">
-      <scroll-view class="w-full h-fit sticky top-0 py-10 z-1" scroll-x :scroll-into-view="scrollIntoView"
-        :scroll-left="scrollLeft">
-        <view class="flex items-center px-20 gap-x-20">
-          <view class="px-40 py-8 rounded-full" :id="`sub_question_${getNo(index)}`"
-            :class="[index === question.activeSubIndex ? 'bg-[#EBF9FF] text-primary font-bold' : 'bg-back']"
-            v-for="(subQuestion, index) in question.subQuestions" @click="setSubQuestionIndex(index)">
+      <uv-tabs ref="tabRef" :current="question.activeSubIndex" :autoScroll="autoScroll" keyName="label"
+        :animationEnabled="false" :itemStyle="tabItemStyle" :list="tabs" :scrollable="true" lineHeight="0"
+        @change="handleTabChange">
+        <template #default="{ item, index }">
+          <view class="px-40 py-8 rounded-full"
+            :class="[index === question.activeSubIndex ? 'bg-[#EBF9FF] text-primary' : 'bg-back']">
             {{ getNo(index) }}
             {{ getNo(index) }}
           </view>
           </view>
-        </view>
-      </scroll-view>
+        </template>
+      </uv-tabs>
       <view v-if="question.subQuestions[question.activeSubIndex]" class="mt-20">
       <view v-if="question.subQuestions[question.activeSubIndex]" class="mt-20">
         <question-item :question="question.subQuestions[question.activeSubIndex]" />
         <question-item :question="question.subQuestions[question.activeSubIndex]" />
       </view>
       </view>
@@ -33,36 +33,56 @@ import { useExam } from '@/composables/useExam';
 import { Study, Transfer } from '@/types';
 import { Study, Transfer } from '@/types';
 import { EXAM_DATA, EXAM_PAGE_OPTIONS, EXAM_AUTO_SUBMIT } from '@/types/injectionSymbols';
 import { EXAM_DATA, EXAM_PAGE_OPTIONS, EXAM_AUTO_SUBMIT } from '@/types/injectionSymbols';
 
 
+const props = defineProps<{
+  question: Study.Question;
+}>();
 const examPageOptions = inject(EXAM_PAGE_OPTIONS) || {} as Transfer.ExamAnalysisPageOptions;
 const examPageOptions = inject(EXAM_PAGE_OPTIONS) || {} as Transfer.ExamAnalysisPageOptions;
 const examData = inject(EXAM_DATA) || {} as ReturnType<typeof useExam>;
 const examData = inject(EXAM_DATA) || {} as ReturnType<typeof useExam>;
-const { subQuestionIndex, setSubQuestionIndex } = examData;
+const { subQuestionIndex, setSubQuestionIndex, currentIndex } = examData;
 const examAutoSubmit = inject(EXAM_AUTO_SUBMIT);
 const examAutoSubmit = inject(EXAM_AUTO_SUBMIT);
 
 
 const scrollIntoView = ref('')
 const scrollIntoView = ref('')
 const scrollLeft = ref(0);
 const scrollLeft = ref(0);
-
-watch(subQuestionIndex, (val) => {
-  scrollIntoView.value = '';
-  nextTick(() => {
-    scrollIntoView.value = `sub_question_${val}`;
-    if (props.question.subQuestions && props.question.subQuestions.length > 0) {
-      if (props.question.subQuestions[0].subIndex === val) {
-        scrollLeft.value = -1;
-        setTimeout(() => {
-          scrollLeft.value = 0;
-        }, 0);
-      }
+const autoScroll = ref(false);
+const tabRef = ref();
+const tabs = computed(() => {
+  return props.question.subQuestions.map((item, index) => {
+    return {
+      label: props.question.index + props.question.offset + index + 1,
+      value: item.subIndex
     }
     }
   });
   });
+});
+const tabItemStyle = {
+  padding: '0 5px',
+};
+
+watch(() => props.question.activeSubIndex, (val) => {
+  if (currentIndex.value === props.question.index) {
+    autoScroll.value = true;
+  }
+}, {
+  immediate: false
+});
+watch(() => currentIndex.value, (val) => {
+  if (currentIndex.value === props.question.index) {
+    setTimeout(() => {
+      nextTick(() => {
+        tabRef.value?.init();
+      });
+    }, 0);
+  } else {
+    autoScroll.value = false;
+  }
 }, {
 }, {
   immediate: false
   immediate: false
 });
 });
 
 
-const props = defineProps<{
-  question: Study.Question;
-}>();
 const getNo = (subIndex: number) => {
 const getNo = (subIndex: number) => {
   return props.question.index + props.question.offset + subIndex + 1;
   return props.question.index + props.question.offset + subIndex + 1;
 }
 }
+const handleTabChange = (e: any) => {
+  setSubQuestionIndex(e.index);
+}
 </script>
 </script>
 <style lang="scss" scoped></style>
 <style lang="scss" scoped></style>

+ 2 - 2
src/uni_modules/uv-tabs/components/uv-tabs/uv-tabs.vue

@@ -6,7 +6,7 @@
 				<scroll-view
 				<scroll-view
 					:scroll-x="scrollable"
 					:scroll-x="scrollable"
 					:scroll-left="scrollLeft"
 					:scroll-left="scrollLeft"
-					scroll-with-animation
+					:scroll-with-animation="animationEnabled"
 					class="uv-tabs__wrapper__scroll-view"
 					class="uv-tabs__wrapper__scroll-view"
 					:show-scrollbar="false"
 					:show-scrollbar="false"
 					ref="uv-tabs__wrapper__scroll-view"
 					ref="uv-tabs__wrapper__scroll-view"
@@ -138,7 +138,7 @@
 				immediate: true,
 				immediate: true,
 				handler (newValue, oldValue) {
 				handler (newValue, oldValue) {
 					// 内外部值不相等时,才尝试移动滑块
 					// 内外部值不相等时,才尝试移动滑块
-					if (newValue !== this.innerCurrent) {
+					if (this.autoScroll && newValue !== this.innerCurrent) {
 						this.innerCurrent = newValue
 						this.innerCurrent = newValue
 						this.$nextTick(() => {
 						this.$nextTick(() => {
 							this.resize()
 							this.resize()