Просмотр исходного кода

feat: add progress page and adjust related pages

1. 新增课程进度页面pages/catalog/progress.uvue,实现课程进度展示与跳转
2. 调整目录页跳转路径到进度页面
3. 登录页新增隐私政策勾选框
4. 优化首页与详情页布局及逻辑
408249787@qq.com 1 неделя назад
Родитель
Сommit
d080e7cb74

+ 7 - 0
pages.json

@@ -43,6 +43,13 @@
 			}
 		},
 		{
+			"path": "pages/catalog/progress",
+			"style": {
+				"navigationStyle": "custom",
+				"disableScroll": true
+			}
+		},
+		{
 			"path": "pages/user/info",
 			"style": {
 				"navigationStyle": "custom",

+ 26 - 21
pages/catalog/detail.uvue

@@ -53,22 +53,24 @@ const course = ref<SubjectCourseResult>()
 //通过路由参数获取课程id
 async function fetchCatalog() {
   course.value = await fetchSubjectCourseApp({ id: router.query().id })
-  if (!course.value?.courseUserProgress) {
-    await updateSubjectProgress({
-      courseId: course.value?.id,
-      mainProgress: 1,
-      assistantProgress: 1,
-      status: 0
-    })
-    progress.value = 1
-    progress2.value = 1
-  } else if (course.value?.courseUserProgress.status == 0) {
-    progressStatus.value = course.value?.courseUserProgress.status
-    progress2.value = course.value?.courseUserProgress.assistantProgress
-  } else {
-    progressStatus.value = course.value?.courseUserProgress.status
-    progress2.value = 1
-  }
+  progressStatus.value = course.value?.courseUserProgress.status
+  progress2.value = Number(router.query().progress)
+  console.log(progress2.value);
+  // if (!course.value?.courseUserProgress) {
+  //   await updateSubjectProgress({
+  //     courseId: course.value?.id,
+  //     mainProgress: 1,
+  //     assistantProgress: 1,
+  //     status: 0
+  //   })
+  //   progress.value = 1
+  //   progress2.value = 1
+  // } else if (course.value?.courseUserProgress.status == 0) {
+
+  // } else {
+  //   progressStatus.value = course.value?.courseUserProgress.status
+  //   progress2.value = 1
+  // }
 }
 onMounted(async () => {
   isLoading.value = true
@@ -207,7 +209,7 @@ onUnmounted(() => {
   <cl-page v-show="!isLoading">
     <Back />
     <view class="video-container">
-      <video v-if="progress2 !== 4" id="video1" class="w-full h-full " :src="data.videoSrc"
+      <video v-if="progress2 !== 4" id="video1" class="w-full h-full " enable-play-gesture :src="data.videoSrc"
         :show-center-play-btn="false" :show-background-playback-button="false" :show-fullscreen-btn="false"
         :show-casting-button="false" autoplay @controlstoggle="handleControlsToggle" @ended="handleEnded">
       </video>
@@ -265,7 +267,7 @@ onUnmounted(() => {
         <view class="text-[20px] font-bold text-white">
           {{ course?.mainTitle }}
         </view>
-        <view class="control-progress">
+        <!-- <view class="control-progress">
           <view class="before"></view>
           <view v-for="(item, i) in menu2Items" :key="item.id"
             class="py-2 px-3 flex items-center flex-row justify-center ov gap-[5px]  relative z-[1]"
@@ -274,7 +276,7 @@ onUnmounted(() => {
             <text class="text-[12px]  font-bold" :class="{ '!text-[#2BA0F3]': progress2 == i + 1 }">{{ item.name
             }}</text>
           </view>
-        </view>
+        </view> -->
       </view>
     </view>
 
@@ -357,14 +359,17 @@ onUnmounted(() => {
   .control-progress {
     @apply fixed top-1/2 right-[0px] flex flex-col gap-[3px] z-[100] h-[280px] w-[105px];
     transform: translateY(-50%);
-    view{
+
+    view {
       overflow: initial !important;
     }
+
     .before {
       @apply absolute top-0 right-0 h-full w-full bg-[#2BA0F3];
       border-radius: 25px 0 0 25px;
     }
-    .ov{
+
+    .ov {
       overflow: initial !important;
     }
   }

+ 1 - 1
pages/catalog/index.uvue

@@ -49,7 +49,7 @@ function handleDetail(item: SubjectCatalogResult) {
   //   return
   // }
   router.push({
-    path: "/pages/catalog/detail",
+    path: "/pages/catalog/progress",
     query: {
       id: item.id,
     }

+ 118 - 0
pages/catalog/progress.uvue

@@ -0,0 +1,118 @@
+<script setup lang="ts">
+import Back from '@/components/back.uvue'
+import Loading from '@/components/loading.uvue'
+import { ref, onMounted, watch, nextTick, onUnmounted } from 'vue'
+import { type SubjectCourseResult, fetchSubjectCourseApp, updateSubjectProgress } from '@/services/subject/course'
+import { router } from '@/.cool'
+
+const course = ref<SubjectCourseResult>()
+const progress = ref(0)
+const isLoading = ref(false)
+const progressStatus = ref(0)
+//通过路由参数获取课程id
+async function fetchCatalog() {
+    course.value = await fetchSubjectCourseApp({ id: router.query().id })
+    if (!course.value?.courseUserProgress) {
+        await updateSubjectProgress({
+            courseId: course.value?.id,
+            mainProgress: 1,
+            assistantProgress: 1,
+            status: 0
+        })
+        progress.value = 1
+    } else if (course.value?.courseUserProgress.status == 0) {
+        progressStatus.value =  course.value?.courseUserProgress.status
+        progress.value = course.value?.courseUserProgress.assistantProgress
+    } else {
+        progress.value = 6
+        progressStatus.value =  course.value?.courseUserProgress.status
+    }
+}
+onShow(async () => {
+    isLoading.value = true
+    await fetchCatalog()
+    setTimeout(() => {
+        isLoading.value = false
+    }, 1000)
+})
+
+const menuItems = [
+  { id: 1, name: '观察', icon: 'https://oss.xiaoxiongcode.com/static/home/6419.png' ,x:0,y:15},
+  { id: 2, name: '交互', icon: 'https://oss.xiaoxiongcode.com/static/home/6414.png' ,x:15,y:22},
+  { id: 3, name: '思考', icon: 'https://oss.xiaoxiongcode.com/static/home/6418.png' ,x:29,y:13},
+  { id: 4, name: '假设', icon: 'https://oss.xiaoxiongcode.com/static/home/6412.png' ,x:41,y:3},
+  { id: 5, name: '总结', icon: 'https://oss.xiaoxiongcode.com/static/home/6416.png' ,x:59,y:7},
+  { id: 6, name: '实验', icon: 'https://oss.xiaoxiongcode.com/static/home/6417.png' ,x:80,y:10},
+]
+//点击事件
+function handleClick(id: number) {
+  if (course.value?.id && course.value?.courseUserProgress.status  == 0) {
+      updateSubjectProgress({
+      courseId: course.value?.id,
+      mainProgress: 1,
+      assistantProgress: id,
+      status: course.value?.courseUserProgress.status 
+    })
+  }
+   router.push({
+    path: "/pages/catalog/detail",
+    query: {
+      id: router.query().id ,
+      progress: id,
+    }
+  });
+}
+</script>
+<template>
+    <!-- <Loading v-show="isLoading" /> -->
+    <cl-page>
+        <Back />
+        <view class="main">
+      <!-- <image class="absolute top-0 left-0 z-[1] w-full h-full "  mode="aspectFill"  src="https://oss.xiaoxiongcode.com/static/home/641.png"   /> -->
+            
+             <view class="text-[20px] font-bold text-[#333333] absolute top-6 left-20">
+          {{ course?.mainTitle }}
+        </view>
+            <view class="progress w-[90vw] h-[45vw] pb-[5vw] flex items-center justify-end ">
+                <image class="w-[80vw]" mode="widthFix"  src="https://oss.xiaoxiongcode.com/static/home/形状 1.png" />
+                <view v-for="item in menuItems" :key="item.id" class="w-[10vw] h-[19vw] absolute flex items-center justify-between z-[2]"
+                :style="{
+                    top: `${item.y}vw`,
+                    left: `${item.x}vw`
+                }" @click="handleClick(item.id)">
+                <view class="w-[9vw] h-[9vw] flex items-center justify-center bg-[#fff] rounded-[2vw] box-shadow">
+                    <image :src="item.icon" class="w-[4vw] "  mode="widthFix" />
+                    <text class="text-[2vw] text-[#000]">{{item.name}}</text>
+                </view>
+                   <view class="flex items-center justify-between gap-[1vw]">
+                     <image v-if="progress === item.id&&progressStatus == 0" src="https://oss.xiaoxiongcode.com/static/home/6411.png" class="h-[4vw] "  mode="heightFix" />
+                       <view v-else-if="progress<item.id&&progressStatus == 0" class="text-[2vw] w-[4vw] h-[4vw] flex items-center justify-center text-bold text-[#333] bg-[#fff] rounded-full ">
+                       {{ item.id }}
+                     </view>
+                     <image v-else src="https://oss.xiaoxiongcode.com/static/home/6413.png" class="h-[4vw] "  mode="heightFix" />
+                   
+                     <image src="https://oss.xiaoxiongcode.com/static/home/6415.png" class="w-[4vw] "  mode="widthFix" />
+                   </view>
+                </view>
+            </view>
+        </view>
+    </cl-page>
+</template>
+<style lang="scss" scoped>
+.main{
+    background: linear-gradient(0deg, #88C5F0, #D0ECFF);
+    width: 100vw;
+    height: 100vh;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+ .progress{
+    position: relative;
+    z-index: 2;
+ } 
+}
+.box-shadow{
+box-shadow: 4px 7px 10px 0px rgba(62,166,238,0.44);
+}
+</style>

+ 17 - 75
pages/index/components/physics.uvue

@@ -12,88 +12,30 @@ function openPopup() {
 }
 </script>
 <template>
-  <view class="bottom">
-    <view class=" progress">
-      <view class="text-[22px] font-bold">学习进度 {{ user.info.value?.studyCourseNum || 0 }}/100</view>
-      <view class=" w-full flex flex-row items-center justify-center gap-2">
-        <cl-progress class="flex-1" color="linear-gradient(0deg, #1FA5F5 37%, #A2D8FF 100%)"
-          :value="user.info.value?.studyCourseNum" :show-text="false" :strokeWidth="16"
-          :pt="{ outer: { className: '!rounded-full' }, inner: { className: '!rounded-full' } }"></cl-progress>
-
-      </view>
-    </view>
-    <view 
-      @tap="handleView('/pages/test/index')">
-      <cl-image src="https://oss.xiaoxiongcode.com/static/home/113.png" mode="heightFix" width="auto" height="80px" />
-      <!-- <text class="text-[14px]">趣味虚拟实验</text> -->
+  <view class="content">
+    <view @tap="handleView('/pages/catalog/index')" class="w-[57vw] box">
+      <image class="absolute top-0 left-0 z-[1] w-full h-full "  mode="aspectFill"  src="https://oss.xiaoxiongcode.com/static/home/641.png"   />
+             <image class="absolute top-2 right-2 z-[2] h-[14vh]" mode="heightFix" src="https://oss.xiaoxiongcode.com/static/home/645.png"  />
+       <image class="absolute bottom-5 left-5 z-[2] h-[40vh]" mode="heightFix" src="https://oss.xiaoxiongcode.com/static/home/3.gif"  />
+       <image class="absolute bottom-[14vh] right-[12vw] z-[2] h-[20vh]" mode="heightFix" src="https://oss.xiaoxiongcode.com/static/home/play.png"  />
     </view>
-    <view 
-      @tap="handleView('/pages/card/index')">
-      <cl-image src="https://oss.xiaoxiongcode.com/static/home/112.png" mode="heightFix" width="auto" height="80px" />
-      <!-- <text class="text-[14px]">我的收获</text> -->
-    </view>
-    <!-- <view class="flex-1 flex flex-col items-center justify-between gap-1 bg3 py-3" @tap="openPopup">
-      <cl-image src="https://oss.xiaoxiongcode.com/static/home/18.png" mode="widthFix" width="35%" height="auto" />
-      <text class="text-[14px]">AI问答</text>
-    </view> -->
-  </view>
-  <view class="content" @tap="handleView('/pages/catalog/index')">
-    <cl-image src="https://oss.xiaoxiongcode.com/static/home/3.gif" mode="heightFix" height="100%" width="auto" />
-    <view class="flex-1 flex flex-col items-center justify-center gap-2 ft">
-      <view class="text-[10vh] font-bold">
-        启蒙物理AI课
-      </view>
-      <view class="h-[15vh]">
-        <cl-image src="https://oss.xiaoxiongcode.com/static/home/play.png" mode="heightFix" height="100%"
-          width="auto" />
-      </view>
+    <view @tap="handleView('/pages/catalog/index')" class="w-[30vw] box">
+           <image class="absolute top-0 left-0 z-[1] w-full h-full " mode="aspectFill" src="https://oss.xiaoxiongcode.com/static/home/644.png"   />
+       <image class="relative mx-auto mt-2 z-[2] h-[14vh] w-[28vw]" mode="aspectFit" src="https://oss.xiaoxiongcode.com/static/home/642.png"  />
     </view>
   </view>
- 
 </template>
 <style lang="scss" scoped>
-.bottom {
-  @apply absolute bottom-[1vh] left-1/2 w-full max-w-[600px] rounded-[20px] px-10 py-1 flex flex-row items-center justify-between gap-5;
-  transform: translateX(-50%);
-
-  .progress {
-    @apply w-[400px] h-[80px] rounded-[40px] flex justify-center gap-2 px-[30px] gap-3;
-    background: linear-gradient(0deg, #AAE3FF 0%, #DFF4FD 100%);
-    width: 50%;
-  }
-
-  .check {
-    background: linear-gradient(0deg, #FBD00E 0%, #FBEC92 100%);
-    line-height: 20px;
-  }
-}
-
-.bg1 {
-  background: linear-gradient(0deg, #7597FA 0%, #C1DAFF 100%);
-  border-radius: 28px;
-  height: 80px;
-}
-
-.bg2 {
-  background: linear-gradient(0deg, #3CD3DE 0%, #ADFBFF 100%);
-  border-radius: 28px;
-  height: 80px;
-}
-
-.bg3 {
-  background: linear-gradient(0deg, #FFCE4A 0%, #FFEC88 100%);
-  border-radius: 28px;
-  height: 80px;
-}
+.content {
+  @apply w-[90vw]   mx-auto flex flex-row items-center justify-between gap-4 ;
+  height: calc(97vh - 85px);
+.box{
+  @apply h-[70vh]  relative max-h-[40vw];
+  overflow: hidden;
+  border-radius: 30px;
+  border: 1vh solid #fff;
 
-.ft {
-  font-family: eryazhaocaimao;
-  text-shadow: 0 0 10px rgba(255, 255, 255, 0.8), 0 0 20px rgba(255, 255, 255, 0.6), 0 0 30px rgba(255, 255, 255, 0.4), 0 0 40px rgba(62, 166, 238, 0.8);
 }
 
-.content {
-  @apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white w-[120vh] border-[3px] border-[#fff] border-solid rounded-[30px] px-10 py-4 h-[40vh] flex flex-row items-center justify-between gap-4;
-  background: linear-gradient(0deg, #C7F0FE 0%, #30B9FF 100%);
-
 }
 </style>

+ 32 - 18
pages/index/home.uvue

@@ -53,27 +53,41 @@ const visible = ref(false)
 </script>
 <template>
 	<cl-page :backTop="false">
-		<img src="https://oss.xiaoxiongcode.com/static/home/11.jpg" alt="" class="w-full h-full object-cover" />
-		<view class="menus ">
-			<view v-for="item in menuList" :key="item.code"
-				class="flex flex-col items-center p-1 px-4 justify-center gap-1 active:scale-[.9] transition-all duration-300"
-				@tap="handlePage(item)" :class="{ 'selected': item.code === selected }">
-				<cl-image :src="icons[item.code]" mode="aspectFill" width="40" height="40"></cl-image>
-				<text class="text-[12px]">{{ item.label }}</text>
+		<img src="https://oss.xiaoxiongcode.com/static/home/111.png" alt=""
+			class="w-full h-full object-cover absolute top-0 left-0" />
+		<view class="menus w-[90vw]">
+			<image src="https://oss.xiaoxiongcode.com/static/home/643.png"
+				class="w-[90vw] h-[24vh] absolute top-0 left-0 z-[1]"></image>
+			<view class="w-[87vw] relative z-[2] p-1 px-3 flex flex-row items-center justify-between gap-1 mx-auto ">
+				<view v-for="item in menuList" :key="item.code"
+					class="flex flex-col items-center p-1 px-4 justify-center gap-1  transition-all duration-300"
+					@tap="handlePage(item)" :class="{ 'selected': item.code === selected }">
+					<image :src="icons[item.code]" mode="aspectFill"  class="w-[4vw] h-[4vw]"></image>
+					<text  class="text-[1.5vw] text-[#1E1E1E]">{{ item.label }}</text>
+				</view>
+				<view class="flex flex-col items-center p-1 px-4 justify-center gap-1  transition-all duration-300"
+					@tap="visible = true">
+					<view class="bg-[#09ba07] p-[1vw] rounded-[2vw] w-[4vw] h-[4vw] flex items-center justify-center" @tap="visible = true">
+						<image src="https://oss.xiaoxiongcode.com/static/个人中心/微信.png" class="w-full h-full"></image>
+					</view>
+					<text  class="text-[1.5vw] text-[#1E1E1E]">添加老师</text>
+				</view>
 			</view>
 		</view>
-		<view class="flex flex-col items-center justify-center fixed bottom-[3vh] right-[3vh]  " >
-			<view class="bg-[#09ba07] p-2 rounded-full border-[2px] border-[#FFF] border-solid " @tap="visible = true">
+		<!-- <view class="flex flex-col items-center justify-center fixed bottom-[3vh] right-[3vh]  ">
+			 <view class="bg-[#09ba07] p-2 rounded-full border-[2px] border-[#FFF] border-solid " @tap="visible = true">
 				<image src="https://oss.xiaoxiongcode.com/static/个人中心/微信.png" class="w-5 h-5"></image>
 			</view>
 			<text class="text-[14px] text-white font-bold text-stroke">添加老师</text>
-		</view>
-		<cl-popup v-model="visible"  :size="400" :show-header="false" direction="center">
+		</view> -->
+		<cl-popup v-model="visible" :size="400" :show-header="false" direction="center">
 			<view class="flex flex-col items-center justify-center gap-4 py-7 bg-slate-50">
 				<cl-text class="text-center " color="#09ba07" :size="30"> ——专属服务内容—— </cl-text>
-				<image src="https://oss.xiaoxiongcode.com/static/home/qr.png"  show-menu-by-longpress   class="w-32 h-32" />
+				<image src="https://oss.xiaoxiongcode.com/static/home/qr.png" show-menu-by-longpress
+					class="w-32 h-32" />
 				<view class="text-center "> <cl-text class="text-center" color="#999" :size="14"> 长按识别二维码 </cl-text>
-				<cl-text class="text-center" color="#999" :size="14"> 添加微信,享专业老师服务 </cl-text> </view>
+					<cl-text class="text-center" color="#999" :size="14"> 添加微信,享专业老师服务 </cl-text>
+				</view>
 			</view>
 		</cl-popup>
 		<Physics v-if="selected === 'physics'" />
@@ -86,17 +100,17 @@ const visible = ref(false)
 </template>
 <style lang="scss" scoped>
 .menus {
-	@apply absolute top-[3vh] left-1/2 bg-white rounded-[20px] p-2 px-3 flex flex-row items-center justify-center gap-2;
-	transform: translateX(-50%);
+	@apply mt-[3vh] mx-auto rounded-[20px];
 }
 
 .selected {
-	@apply scale-[1.1] bg-[#f0f0f0] rounded-xl;
+	@apply scale-[1.1] bg-[#efefef99] rounded-xl;
+	font-weight: bold;
 }
 
 .text-stroke {
-	text-shadow: 
-		-1px -1px 0 #000,  
+	text-shadow:
+		-1px -1px 0 #000,
 		1px -1px 0 #000,
 		-1px 1px 0 #000,
 		1px 1px 0 #000;

+ 9 - 2
pages/user/login.uvue

@@ -24,7 +24,7 @@
 							<password :form="formData" />
 						</view>
 						<view class="flex flex-row items-center justify-center mb-5">
-							<cl-button :disabled="!agree"
+							<cl-button :disabled="!agree || !agree2"
 								:pt="{ className: '!h-[45px] !rounded-full w-[200px] mx-auto' }" :loading="loading"
 								@tap="toLogin">
 								登录
@@ -35,7 +35,13 @@
 								同意并阅读
 								<cl-text :size="12" color="primary" @tap.stop="toAgreement">
 									《用户服务协议》
-								</cl-text>和
+								</cl-text>
+							
+							</view>
+						</cl-checkbox>
+							<cl-checkbox v-model="agree2">
+							<view class="flex flex-row items-center w-full text-[12px]">
+								同意并阅读
 								<cl-text :size="12" color="primary" @tap.stop="toPrivacy">
 									《隐私政策》
 								</cl-text>
@@ -110,6 +116,7 @@ const actionSheetRef = ref<ClActionSheetComponentPublicInstance | null>(null);
 
 const val = ref('quickly_login')
 const agree = ref(false)
+const agree2 = ref(false)
 const list: ClTabsItem[] = [
 	{
 		label: '验证码登录',