Pārlūkot izejas kodu

feat(课程): 添加获取课程应用信息接口并优化课程列表交互

重构课程列表页面,使用新的fetchSubjectAppInfo接口获取数据
优化滚动定位逻辑,使用uni.createSelectorQuery替代getBoundingClientRect
调整课程卡片布局和进度显示,移除无用代码
whj 4 dienas atpakaļ
vecāks
revīzija
4a68a0315e

+ 16 - 25
pages/card/index.uvue

@@ -23,38 +23,28 @@ async function getDataList() {
 }
 function handleSelect(categoryId: string) {
   activeCategory.value = categoryId
-  //找到第一个元素上categoryId属性与categoryId相同的元素
-  const element = categoryRefs.value.find((item: any) => {
-    return item.dataset.category === categoryId
-  })
-  if (element) {
-    const rect = element.getBoundingClientRect()
-    console.log(rect)
-    if (cardsScrollView.value) {
+  uni.createSelectorQuery().select(`.category-${categoryId}`).boundingClientRect().exec((rect) => {
+    if (cardsScrollView.value && rect[0]) {
       cardsScrollView.value.scrollTo({
-        top: rect.top - 70, // 减去顶部偏移
+        top: rect[0].top - 70, // 减去顶部偏移
         animated: true
       })
     }
-  }
+  })
 }
 
-function onScroll(e: any) {
-  const scrollTop = e.detail.scrollTop
-  // 遍历所有分类,检查哪个分类在可视区域
-  for (const category of categories.value) {
-    const element = categoryRefs.value.find((item: any) => {
-      return item.dataset.category === category.id
-    })
-    if (element) {
-      const rect = element.getBoundingClientRect()
+async function onScroll(e: any) {
+  categories.value.forEach(async (category) => {
+    const selector = `.category-${category.id}`
+    await uni.createSelectorQuery().selectAll(selector).boundingClientRect().exec((rects) => {
       // 检查元素是否在可视区域内
-      if (rect.top <= 150 && rect.bottom >= 150) {
-        activeCategory.value = category.id
-        break
+      for (const rect of rects[0]) {
+        if (rect.top <= 150 && rect.bottom >= 150) {
+          activeCategory.value = category.id
+        }
       }
-    }
-  }
+    })
+  })
 }
 onMounted(async () => {
   await getDataList()
@@ -90,7 +80,8 @@ onMounted(async () => {
         <scroll-view direction="vertical" :show-scrollbar="false" class="cards" ref="cardsScrollView"
           @scroll="onScroll">
           <view class="grid grid-cols-5 gap-4">
-            <view class="card" v-for="card in cards" :key="card.id" :data-category="card.catalogId" ref="categoryRefs">
+            <view class="card" v-for="card in cards" :key="card.id" :class="`category-${card.catalogId}`"
+              ref="categoryRefs">
               <image v-if="card.userCardId" :src="config.baseUrl + card.iconPath" class="w-full h-full" />
               <image v-else src="https://oss.xiaoxiongcode.com/static/home/21.png" class="w-full h-full" />
               <view class="card-title">{{ card.cardName }}</view>

+ 38 - 10
pages/catalog/index.uvue

@@ -1,7 +1,8 @@
 <script lang="ts" setup>
 import { ref, onMounted } from 'vue'
-import { fetchSubjectConfigInfo } from '@/services/subject/info'
+import { fetchSubjectAppInfo } from '@/services/subject/info'
 import type { SubjectCatalogResult } from '@/services/subject/catalog'
+import type { SubjectCourseResult } from '@/services/subject/course'
 import Lock from '@/components/lock.uvue'
 import Progress from './components/progress.uvue'
 import Back from '@/components/back.uvue'
@@ -14,11 +15,13 @@ const isLoading = ref(true)
 const visible = ref<boolean>(false)
 const dataList = ref<SubjectCatalogResult[]>([])
 const catalog = ref<SubjectCatalogResult>()
+const courseList = ref<SubjectCourseResult>()
 async function getDataList() {
   const id = dict.getValueByLabelMapByType('index_subject_id')['物理']
-  const res = await fetchSubjectConfigInfo({ id })
+  const res = await fetchSubjectAppInfo({ id })
   dataList.value = res.catalogList || []
   catalog.value = res?.catalogList?.[0]
+  courseList.value = res?.courseList || []
 }
 onMounted(async () => {
   try {
@@ -29,10 +32,9 @@ onMounted(async () => {
     isLoading.value = false
   }
 })
-function handleSelect(item: SubjectCatalogResult) {
-  catalog.value = item
-  visible.value = false
-}
+const cardsScrollView = ref<any>(null)
+const categoryRefs = ref<any>()
+
 function handleDetail(item: SubjectCatalogResult) {
   // if (!item.payFlag && !item.trialPlay) {
   //   uni.showToast({
@@ -48,6 +50,31 @@ function handleDetail(item: SubjectCatalogResult) {
     }
   });
 }
+function handleSelect(val: SubjectCatalogResult) {
+  catalog.value = val
+  visible.value = false
+  uni.createSelectorQuery().select(`.category-${val.id}`).boundingClientRect().exec((rect) => {
+    if (cardsScrollView.value && rect[0]) {
+      cardsScrollView.value.scrollTo({
+        left: rect[0].left - 215, // 减去顶部偏移
+        animated: true
+      })
+    }
+  })
+}
+async function onScroll(e: any) {
+  dataList.value.forEach(async (category) => {
+    const selector = `.category-${category.id}`
+    await uni.createSelectorQuery().selectAll(selector).boundingClientRect().exec((rects) => {
+      // 检查元素是否在可视区域内
+      for (const rect of rects[0]) {
+        if (rect.left <= 215) {
+          catalog.value = category
+        }
+      }
+    })
+  })
+}
 </script>
 
 <template>
@@ -69,9 +96,10 @@ function handleDetail(item: SubjectCatalogResult) {
       <cl-icon name="arrow-left-right-line" color="primary"></cl-icon>
     </view>
     <view class="boxs">
-      <scroll-view class="scroll-view_H" direction="horizontal" :show-scrollbar="false">
-        <view class="scroll-view-item_H bg-[white]" v-for="course in catalog?.courseList || []" :key="course.id"
-          @tap="handleDetail(course)">
+      <scroll-view class="scroll-view_H" direction="horizontal" :show-scrollbar="false" ref="cardsScrollView"
+        @scroll="onScroll">
+        <view class="scroll-view-item_H bg-[white]" v-for="course in courseList || []"
+          :class="`category-${course.catalogId}`" :key="course.id" @tap="handleDetail(course)" ref="categoryRefs">
           <cl-image :src="config.baseUrl + course?.fileList?.[0]?.url" mode="heightFix"
             class="!w-full !h-[26vh] mb-[2px] rounded-xl"></cl-image>
           <text class="text-[16px] font-bold">{{
@@ -79,7 +107,7 @@ function handleDetail(item: SubjectCatalogResult) {
           <text class="text-[14px] text-[#666]">{{
             course.assistantTitle }}</text>
           <view>
-            <Progress :num="2" :percentage="course.sortNum" />
+            <Progress :num="2" :percentage="course.courseUserProgress?.mainProgress || 0" />
           </view>
           <Lock v-if="!course.trialPlay && !course.payFlag" :record="course" />
         </view>

+ 1 - 6
pages/index/components/physics.uvue

@@ -17,11 +17,6 @@ function handleView(url) {
           :value="user.info.value?.studyCourseNum" :show-text="false" :strokeWidth="16"
           :pt="{ outer: { className: '!rounded-full' }, inner: { className: '!rounded-full' } }"></cl-progress>
 
-        <view class="text-[12px] w-[100px] rounded-full text-black font-bold text-center check
-               to-pink-500 h-[20px] ">
-          今日打卡
-        </view>
-
       </view>
     </view>
     <view class="flex-1 flex flex-col items-center justify-between gap-2 bg1 py-3">
@@ -35,7 +30,7 @@ function handleView(url) {
     </view>
     <view class="flex-1 flex flex-col items-center justify-between gap-1 bg3 py-3">
       <cl-image src="https://oss.xiaoxiongcode.com/static/home/18.png" mode="widthFix" width="35%" height="auto" />
-      <text class="text-[14px]">学习报告</text>
+      <text class="text-[14px]">AI问答</text>
     </view>
   </view>
   <view class="content" @tap="handleView('/pages/catalog/index')">

+ 3 - 0
services/subject/info.ts

@@ -34,6 +34,9 @@ export interface SubjectInfoResult {
 export function fetchSubjectConfigInfo(parameter: any) {
     return useGet(`/subject/info/config/info/${parameter.id}`) as Promise<SubjectInfoResult>
 }
+export function fetchSubjectAppInfo(parameter: any) {
+    return useGet(`/subject/info/app/info/${parameter.id}`) as Promise<any>
+}
 export function fetchSubjectInfo(parameter: any) {
     return useGet(`/subject/info/${parameter.id}`) as Promise<SubjectInfoResult>
 }