Parcourir la source

修改课程内容页面

丸子 il y a 4 mois
Parent
commit
72f76b2fd5

+ 153 - 78
src/views/programming/ProgrammingCourset.vue

@@ -29,10 +29,6 @@
 
     <!-- 课程部分 -->
     <div class="lower-box" v-if="!showVideo">
-        <!-- 左切换按钮 -->
-        <div v-if="!showVideo && courseItems.length > 3" class="carousel-btn prev-btn" @click="prevSlide" :class="{ 'disabled-btn': currentIndex === 0 }" :disabled="currentIndex === 0">
-          <el-icon class="btn-icon" :class="{ 'disabled-icon': currentIndex === 0 }"><ArrowLeftBold /></el-icon>
-        </div>
         <div 
             class="content-box"
             ref="contentBox"
@@ -44,9 +40,9 @@
           >
           <!-- 动态渲染课程内容 -->
           <div 
-            v-for="(item) in courseItems" 
+            v-for="(item, index) in courseItems" 
             :key="item.id"
-            class="slide-item"
+            :class="['slide-item', { active: activeButton === index }]"
             :style="courseItems.length <= 3 ? { float: 'left' } : {}"
             @click="handleCourseItemClick(item)"
           >
@@ -67,10 +63,22 @@
             </div>
           </div>
         </div>
-        <!-- 右切换按钮 -->
-        <div v-if="!showVideo && courseItems.length > 3" class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': currentIndex >= courseItems.length - 3 }" :disabled="currentIndex >= courseItems.length - 3">
-          <el-icon class="btn-icon" :class="{ 'disabled-icon': currentIndex >= courseItems.length - 3 }"><ArrowRightBold /></el-icon>
-        </div>
+    </div>
+
+    <!-- 底部切换按钮 -->
+    <div v-if="!showVideo && courseItems.length > 3" class="bottom-box">
+      <!-- 左切换按钮 -->
+      <div class="carousel-btn prev-btn" @click="prevSlide" :class="{ 'disabled-btn': activeButton === 0 }" :disabled="activeButton === 0">
+        <img :src="leftbtn" alt="左按钮" class="btn-image" :class="{ 'disabled-icon': activeButton === 0 }" />
+      </div>
+      <!-- 进度条滑块 -->
+      <div class="line-container" v-if="courseItems.length > 0">
+        <el-slider v-model="activeButton" :max="courseItems.length - 1" :step="1" :show-tooltip="false" />
+      </div>
+      <!-- 右切换按钮 -->
+      <div class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': activeButton >= courseItems.length - 1 }" :disabled="activeButton >= courseItems.length - 1">
+        <img :src="rightbtn" alt="右按钮" class="btn-image" :class="{ 'disabled-icon': activeButton >= courseItems.length - 1 }" />
+      </div>
     </div>
     
     <!-- 视频和编程界面 -->
@@ -91,6 +99,9 @@ import { getBlocklyByTypeId } from '@/api/programming/index.js'
 import  explanation  from '@/assets/programming/explanation.png'
 import  practice  from '@/assets/programming/practice.png'
 import  summary  from '@/assets/programming/summary.png'
+// 导入按钮图片
+import leftbtn from '@/assets/programming/leftbtn.png'
+import rightbtn from '@/assets/programming/rightbtn.png'
 
 import Interface from './Interface.vue'
 
@@ -119,8 +130,8 @@ const courseItems = ref([])
 const selectedCourseData = ref(null)
 // 保存原始API返回的数据
 const resData = ref([])
-// 轮播图当前索引
-const currentIndex = ref(0)
+// 当前激活的按钮索引
+const activeButton = ref(0)
 
 // 拖动相关变量
 const isDragging = ref(false)
@@ -142,33 +153,15 @@ const getStarCount = (contentType) => {
 
 // 上一页
 const prevSlide = () => {
-  if (currentIndex.value > 0) {
-    currentIndex.value = Math.max(0, currentIndex.value - 3)
-    // 滚动到对应位置
-    if (contentBox.value) {
-      const itemWidth = rpxValue(140) + rpxValue(70); // 宽度+间距
-      const scrollPosition = currentIndex.value * itemWidth;
-      contentBox.value.scrollTo({
-        left: scrollPosition,
-        behavior: 'smooth'
-      });
-    }
+  if (activeButton.value > 0) {
+    activeButton.value -= 1;
   }
 }
 
 // 下一页
 const nextSlide = () => {
-  if (currentIndex.value < courseItems.value.length - 3) {
-    currentIndex.value = Math.min(courseItems.value.length - 3, currentIndex.value + 3)
-    // 滚动到对应位置
-    if (contentBox.value) {
-      const itemWidth = rpxValue(140) + rpxValue(70); // 宽度+间距
-      const scrollPosition = currentIndex.value * itemWidth;
-      contentBox.value.scrollTo({
-        left: scrollPosition,
-        behavior: 'smooth'
-      });
-    }
+  if (activeButton.value < courseItems.value.length - 1) {
+    activeButton.value += 1;
   }
 }
 
@@ -219,26 +212,28 @@ const rpxValue = (px) => {
 }
 
 // 滚动事件处理函数
-const handleScroll = () => {
-  if (contentBox.value && !isDragging.value) {
-    // 检查是否滚动到最右侧
-    const { scrollLeft, scrollWidth, clientWidth } = contentBox.value;
-    // 当滚动到最右侧时,禁用右侧箭头
-    if (scrollLeft + clientWidth >= scrollWidth - 10) { 
-      currentIndex.value = Math.max(0, courseItems.value.length - 3);
-    } else {
-      // 向右滑动,左侧按钮正常显示
-      if (scrollLeft > 10) {
-        // 根据滚动位置计算当前索引,但不限制为0
-        const itemWidth = rpxValue(140) + rpxValue(70); // 宽度+间距
-        const calculatedIndex = Math.round(scrollLeft / itemWidth);
-        currentIndex.value = Math.max(0, Math.min(courseItems.value.length - 3, calculatedIndex));
-      } else { // 滚动到最左侧
-        currentIndex.value = 0;
-      }
+const handleScroll = () => {}
+
+// 监听activeButton变化,自动滚动到中间位置
+watch(activeButton, (newIndex) => {
+  if (contentBox.value && newIndex !== -1) {
+    // 找到对应的课程卡片元素
+    const courseElement = contentBox.value.querySelector(`.slide-item:nth-child(${newIndex + 1})`);
+    if (courseElement) {
+      // 计算滚动位置,选中的卡片居中
+      const containerWidth = contentBox.value.clientWidth;
+      const elementLeft = courseElement.offsetLeft;
+      const elementWidth = courseElement.offsetWidth;
+      // 计算居中位置
+      const scrollPosition = elementLeft - (containerWidth / 2) + (elementWidth / 2);
+      // 平滑滚动到计算的位置
+      contentBox.value.scrollTo({
+        left: scrollPosition,
+        behavior: 'smooth'
+      });
     }
   }
-}
+});
 
 // 提取课程数据获取和处理逻辑为单独函数
 const fetchCourseData = () => {
@@ -367,6 +362,7 @@ watch(showVideo, (newValue, oldValue) => {
 .top-box {
   height: 20%;
   display: flex;
+  
 }
 
 .top-left-box,
@@ -454,12 +450,13 @@ watch(showVideo, (newValue, oldValue) => {
 }
 
 .lower-box {
-  flex: 1;
+  height: 75%;
+  overflow: hidden; /* 溢出隐藏 */
+  position: relative;
   display: flex;
   align-items: center;
   justify-content: center;
-  width: 100%;
-  height: 100%;
+  margin-top: rpx(-25);
 }
 
 .content-box {
@@ -500,15 +497,14 @@ watch(showVideo, (newValue, oldValue) => {
 }
 
 .slide-item {
-  width: rpx(140); /* 设置固定宽度 */
-  height: rpx(120); /* 高度设置 */
-  margin: rpx(80) rpx(35);
-  border-radius: rpx(40);
+  width: rpx(130); /* 设置固定宽度 */
+  height: rpx(110); /* 高度设置 */
+  margin: rpx(85) rpx(40);
+  border-radius: rpx(35);
   background-color: rgba(255, 255, 255);
   display: inline-flex;
   align-items: center;
   justify-content: center;
-  box-shadow: 0 rpx(5) rpx(10) rgba(0, 0, 0, 0.2);
   transition: transform 0.3s ease;
   cursor: pointer;
   z-index: 2; /* 内容在背景图上方 */
@@ -533,6 +529,20 @@ watch(showVideo, (newValue, oldValue) => {
   transform: translateY(50%) scale(1.1);
   z-index: 10;
 }
+/* 默认选中第一个元素的样式 */
+/* 奇数项选中样式 */
+.slide-item:nth-child(odd).active {
+  transform: translateY(-50%) scale(1.1);
+  z-index: 10;
+  box-shadow: 0 rpx(8) rpx(15) rgba(0, 0, 0, 0.3);
+}
+
+/* 偶数项选中样式 */
+.slide-item:nth-child(even).active {
+  transform: translateY(50%) scale(1.1);
+  z-index: 10;
+  box-shadow: 0 rpx(8) rpx(15) rgba(0, 0, 0, 0.3);
+}
 
 /* 内容样式 */
 .box-content {
@@ -588,52 +598,117 @@ watch(showVideo, (newValue, oldValue) => {
 
 /* 轮播图按钮样式 */
 .carousel-btn {
-  position: absolute;
-  top: 50%;
-  transform: translateY(-50%);
-  width: rpx(30);
-  height: rpx(30);
-  background-color: rgba(255, 255, 255, 0.8);
+  width: rpx(40);
+  height: rpx(40);
   border-radius: 50%;
   display: flex;
   align-items: center;
   justify-content: center;
   cursor: pointer;
-  z-index: 100; /* 提高按钮层级确保始终在最上层 */
-  box-shadow: 0 rpx(5) rpx(10) rgba(0, 0, 0, 0.2);
+  z-index: 10;
   transition: all 0.3s ease;
-  pointer-events: all;
 }
 
 .carousel-btn:hover:not(.disabled-btn) {
-  background-color: rgba(255, 255, 255, 1);
-  transform: translateY(-50%) scale(1.1);
+ transform: scale(1.1);
 }
 
 .carousel-btn:disabled,
 .disabled-btn {
-  opacity: 0.5;
   cursor: not-allowed;
-  background-color: rgba(200, 200, 200, 0.7);
   box-shadow: none;
 }
 
 .disabled-icon {
-  color: #ccc !important;
-  filter: grayscale(100%);
-  opacity: 0.6;
+  opacity: 0.5;
 }
 
 .prev-btn {
-  left: 1%;
+  margin-right: rpx(5);
 }
 
 .next-btn {
-  right: 1%;
+  margin-left: rpx(5);
 }
 
 .btn-icon {
   font-size: rpx(15);
   color: #333;
 }
+
+/* 底部切换按钮样式 */
+.bottom-box {
+  height: 15%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.bottom-box .carousel-btn {
+  position: relative;
+  top: 0;
+  transform: none;
+  width: rpx(40);
+  height: rpx(40);
+  background-color: transparent;
+  box-shadow: none;
+}
+
+.bottom-box .carousel-btn:hover:not(.disabled-btn) {
+  transform: none;
+}
+
+.line-container {
+  width: 70%; /* 滑块宽度 */
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  /* el-slider滑块样式 */
+  :deep(.el-slider__runway) {
+    height: rpx(10); /* 滑块轨道高度 */
+    background-color: rgba(228, 227, 254,0.3); /* 轨道背景色 */
+    border-radius: rpx(10);
+  }
+  
+  :deep(.el-slider__bar) {
+    height: rpx(10); /* 滑块激活部分高度 */
+    background-color: #2598c2; /* 激活部分颜色为蓝色 */
+    border-radius: rpx(10);
+  }
+  
+  :deep(.el-slider__button) {
+    width: rpx(35); 
+    height: rpx(35); 
+    margin-top: rpx(-5);
+    margin-left: rpx(-10);
+    border: none; /* 移除边框 */
+    background-image: url('@/assets/programming/xiaozhi.png'); 
+    background-size: 100%; /* 背景图片完全覆盖按钮 */
+    background-position: center; /* 背景图片居中 */
+    background-repeat: no-repeat; /* 背景图片不重复 */
+    background-color: transparent; /* 透明背景 */
+    &:hover {
+      transform: scale(1.1); /* 悬停时放大效果 */
+    }
+    &.hover,
+    &:active {
+      transform: scale(1.1); /* 激活时放大效果 */
+      box-shadow: none; /* 移除阴影效果 */
+    }
+  }
+  
+  :deep(.el-slider__stop) {
+    width: rpx(10); /* 停止点大小 */
+    height: rpx(10); /* 停止点大小 */
+    background-color: white; /* 停止点颜色 */
+    opacity: 0.2;
+  }
+}
+
+.btn-image {
+  width: rpx(40);
+  height: rpx(40);
+  object-fit: contain;
+}
 </style>

+ 1 - 1
src/views/programming/ProgrammingGame.vue

@@ -368,7 +368,7 @@ const goToHomePage = () => {
 
 
 .bottom-box {
-  height: 20%;
+  height: 15%;
   display: flex;
   align-items: center;
   justify-content: center;

+ 1 - 1
src/views/programming/ProgrammingList.vue

@@ -552,7 +552,7 @@ const goToProgrammingList = (courseType, index) => {
   z-index: 5;
 }
 .bottom-box {
-  height: 20%;
+  height: 15%;
   display: flex;
   align-items: center;
   justify-content: center;