浏览代码

Merge remote-tracking branch 'origin/wanzi'

liyanbo 4 月之前
父节点
当前提交
fed9df728d

二进制
src/assets/programming/leftbtn.png


二进制
src/assets/programming/list_bg02.png


二进制
src/assets/programming/rightbtn.png


二进制
src/assets/programming/xiaozhi.png


+ 20 - 4
src/components/videopage/VideoPlayer.vue

@@ -3,7 +3,7 @@
     <div class="box-video">
        <!-- 视频 -->
       <template v-if="contentType === 'video'">
-        <div class="video-wrapper">
+        <div class="video-wrapper" :class="{ 'video-paused': isVideoPaused }">
           <video
             class="full-box-video"
             ref="videoRef"
@@ -12,6 +12,8 @@
             @seeked="handleSeeked"
             @ended="handleVideoEnded"
             @loadedmetadata="handleLoadedMetadata"
+            @pause="handleVideoPause"
+            @play="handleVideoPlay"
           ></video>
           <!-- 历史播放位置提示 -->
           <div 
@@ -22,9 +24,7 @@
             <el-icon @click.stop="closeHistoryTip" class="close-icon"><CloseBold /></el-icon>
             <span @click="goToLastPosition">回到上次播放位置</span>
           </div>
-          <!-- 自定义进度条上的章节要点小圆点 
-              :title="marker.title || `章节要点 (${marker.time}s)`" 
-          -->
+          <!-- 章节要点小圆点 -->
           <div class="progress-markers" v-if="chapterMarkers.length > 0">
             <div 
               v-for="marker in chapterMarkers" 
@@ -96,6 +96,8 @@ const showHistoryTip = ref(false)
 const lastPlayTime = ref(0)
 // 历史播放提示位置百分比
 const historyTipPosition = ref(0)
+// 视频是否暂停状态
+const isVideoPaused = ref(false)
 
 // 定义节流函数
 const throttle = (fn, delay) => {
@@ -279,6 +281,16 @@ const closeHistoryTip = () => {
   showHistoryTip.value = false
 }
 
+// 处理视频暂停事件
+const handleVideoPause = () => {
+  isVideoPaused.value = true
+}
+
+// 处理视频播放事件
+const handleVideoPlay = () => {
+  isVideoPaused.value = false
+}
+
 // 初始化视频播放器
 const initVideoPlayer = () => {
   if (props.contentType !== 'video') return
@@ -519,6 +531,10 @@ onBeforeUnmount(() => {
 video::-webkit-media-controls-panel:not([hidden]) ~ .progress-markers {
   opacity: 1;
 }
+/* 当视频暂停时显示标记 */
+.video-paused .progress-markers {
+  opacity: 1;
+}
 .progress-marker {position: absolute;
   width: rpx(4);
   height: rpx(4);

+ 85 - 135
src/views/programming/ProgrammingGame.vue

@@ -24,11 +24,6 @@
 
         <!-- 编程部分 -->
         <div class="middle-wrapper">
-          <!-- 左切换按钮 -->
-          <div 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="middle-box"
             ref="middleBox"
@@ -51,49 +46,47 @@
               </div>
             </div>
           </div>
-          
-          <!-- 右切换按钮 -->
-          <div class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': currentIndex >= courseCategories.length - 3 }" :disabled="currentIndex >= courseCategories.length - 3">
-            <el-icon class="btn-icon" :class="{ 'disabled-icon': currentIndex >= courseCategories.length - 3 }"><ArrowRightBold /></el-icon>
-          </div>
         </div>
 
         <!-- 底部切换按钮 -->
         <div class="bottom-box">
-          <div class="line-container">
-            <div class="bold-line"></div>
-            <div 
-              v-for="(button, index) in circleButtons" 
-              :key="index" 
-              class="circle-button"
-              :class="{ 'active': activeButton === index }"
-              @click="activeButton = index"
-            >
-            </div>
+          <!-- 左切换按钮 -->
+          <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="circleButtons.length > 0">
+            <el-slider v-model="activeButton" :max="circleButtons.length - 1" :step="1" :show-tooltip="false" />
+          </div>
+          <!-- 右切换按钮 -->
+          <div class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': activeButton >= courseCategories.length - 1 }" :disabled="activeButton >= courseCategories.length - 1">
+            <img :src="rightbtn" alt="右按钮" class="btn-image" :class="{ 'disabled-icon': activeButton >= courseCategories.length - 1 }" />
           </div>
         </div>
     </div>
 </template>
 
 <script setup>
-import { ref, reactive, watch, onMounted, onUnmounted, computed } from 'vue'
+import { ref, reactive, watch } from 'vue'
 // 返回图标
-import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue';
+import { ArrowLeftBold } from '@element-plus/icons-vue';
 // 导入路由
 import { useRouter } from 'vue-router';
 // 导入课程类别接口
 import { getThemeList } from '@/api/programming/index.js'
+// 导入按钮图片
+import leftbtn from '@/assets/programming/leftbtn.png'
+import rightbtn from '@/assets/programming/rightbtn.png'
+
 
 // 创建路由实例
 const router = useRouter()
 // 当前激活的按钮索引
-const activeButton = ref(-1)
+const activeButton = ref(0)
 // 定义圆形按钮数据
 const circleButtons = reactive([])
 // 定义课程类别数据
 const courseCategories = reactive([])
-// 轮播图当前索引
-const currentIndex = ref(0)
 
 // 获取主题列表
 getThemeList().then(res => {
@@ -116,13 +109,9 @@ getThemeList().then(res => {
   }
 })
 
-// 自动滚动到中间位置
+// 监听activeButton变化,切换数据项时的居中显示和放大效果
 watch(activeButton, (newIndex) => {
   if (middleBox.value) {
-    const itemWidth = rpxValue(200) + rpxValue(20);
-    const calculatedIndex = Math.round(newIndex / 3) * 3;
-    currentIndex.value = Math.max(0, Math.min(courseCategories.length - 3, calculatedIndex));
-    
     // 找到对应的课程卡片元素
     const courseElement = middleBox.value.querySelector(`.middle-inner-box:nth-child(${newIndex + 1})`);
     if (courseElement) {
@@ -173,67 +162,25 @@ const handleMouseUp = () => {
   }
   
   // 滚动事件处理函数
-  const handleScroll = () => {
-    if (middleBox.value && !isDragging.value) {
-      // 检查是否滚动到最右侧
-      const { scrollLeft, scrollWidth, clientWidth } = middleBox.value;
-      // 当滚动到最右侧时,禁用右侧箭头
-      if (scrollLeft + clientWidth >= scrollWidth - 10) {
-        currentIndex.value = Math.max(0, courseCategories.length - 3);
-      } else {
-        // 向右滑动,左侧按钮正常显示
-        if (scrollLeft > 10) {
-          // 根据滚动位置计算当前索引,但不限制为0
-          const itemWidth = rpxValue(200) + rpxValue(20);
-          const calculatedIndex = Math.round(scrollLeft / itemWidth);
-          currentIndex.value = Math.max(0, Math.min(courseCategories.length - 3, calculatedIndex));
-        } else { // 滚动到最左侧
-          currentIndex.value = 0;
-        }
-      }
-    }
-  }
+const handleScroll = () => {}
 
 // 获取middleBox元素的引用
 const middleBox = ref(null)
 
 // 上一页
 const prevSlide = () => {
-  if (currentIndex.value > 0) {
-    currentIndex.value = Math.max(0, currentIndex.value - 3)
-    // 滚动到对应位置
-    if (middleBox.value) {
-      const scrollPosition = currentIndex.value * (rpxValue(200) + rpxValue(20));
-      middleBox.value.scrollTo({
-        left: scrollPosition,
-        behavior: 'smooth'
-      });
-    }
+  if (activeButton.value > 0) {
+    activeButton.value -= 1;
   }
 }
 
 // 下一页
 const nextSlide = () => {
-  if (currentIndex.value < courseCategories.length - 3) {
-    currentIndex.value = Math.min(courseCategories.length - 3, currentIndex.value + 3)
-    // 滚动到对应位置
-    if (middleBox.value) {
-      const scrollPosition = currentIndex.value * (rpxValue(200) + rpxValue(20));
-      middleBox.value.scrollTo({
-        left: scrollPosition,
-        behavior: 'smooth'
-      });
-    }
+  if (activeButton.value < courseCategories.length - 1) {
+    activeButton.value += 1;
   }
 }
 
-// rpx转换为像素值的辅助函数
-const rpxValue = (px) => {
-  return (px / 750) * window.innerWidth;
-}
-
-
-
 // 跳转到编程课程列表页
 const goToProgrammingList = (course, index) => {
   router.push({
@@ -344,16 +291,15 @@ const goToHomePage = () => {
 }
   
 .middle-wrapper {
-  height: 60%;
+  height: 75%;
   overflow: hidden; /* 溢出隐藏 */
-  position: relative;
   display: flex;
   align-items: center;
   justify-content: center;
 }
 
 .middle-box {
-  min-width: rpx(650); /* 固定最小宽度 */
+  min-width: 100%; /* 固定最小宽度 */
   height: 100%;
   margin: 0 rpx(50);
   overflow-x: auto; /* 水平滚动条 */
@@ -400,13 +346,13 @@ const goToHomePage = () => {
   z-index: 10; /* 确保放大时在顶层显示 */
 }
 
-/* 选中时的放大效果 */
+/* 选中时的放大效果 - 加强视觉反馈 */
 .child-box-with-bg.active {
-  transform: scale(1.1); /* 放大1.1倍 */
-  z-index: 10; /* 确保放大时在顶层显示 */
+  transform: scale(1.1); /* 选中时放大1.2倍,比悬浮效果更明显 */
+  z-index: 20; /* 确保选中时在顶层显示 */
+  transition: all 0.3s ease; /* 过渡动画效果 */
 }
 
-
 /* 标题样式 */
 .box-title {
   position: absolute;
@@ -426,97 +372,101 @@ const goToHomePage = () => {
   display: flex;
   align-items: center;
   justify-content: center;
+  position: relative;
 }
 
 .line-container {
-  width: 65%;
+  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(-5);
+    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;
+  }
 }
 
-.bold-line {
-  position: absolute;
-  width: 100%;
-  height: rpx(5);
-  background-color: rgba(37, 115, 188, 0.5);
-  border-radius: rpx(3);
-}
 
-.circle-button {
-  width: rpx(7);
-  height: rpx(7);
-  border-radius: 50%;
-  background-color: rgba(255, 255, 255);
-  border: rpx(1) solid #00c1fc;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  cursor: pointer;
-  transition: all 0.3s ease;
-  z-index: 1;
-}
-.circle-button:hover {
-  background-color: white;
-  transform: scale(1.5); // 放大效果
-}
-.circle-button.active {
-  background-color: #f9df04;
-  border: rpx(1) solid #00c1fc;
-  color: white;
-  transform: scale(2);
-  box-shadow: 0 0 rpx(10) rgba(0, 0, 0, 0.5);
-}
 
 /* 轮播图按钮样式 */
 .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: 10;
-  box-shadow: 0 rpx(5) rpx(10) rgba(0, 0, 0, 0.2);
   transition: all 0.3s ease;
 }
 
 .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: 2%;
+  margin-right: rpx(20);
 }
 
 .next-btn {
-  right: 2%;
+  margin-left: rpx(20);
 }
 
-.btn-icon {
-  font-size: rpx(15);
-  color: #333;
+.btn-image {
+  width: rpx(40);
+  height: rpx(40);
+  object-fit: contain;
 }
 
+
+
 </style>

+ 110 - 151
src/views/programming/ProgrammingList.vue

@@ -24,19 +24,14 @@
 
         <!-- 编程部分 -->
          <div class="middle-wrapper">
-          <!-- 左切换按钮 -->
-          <div 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="middle-box"
               ref="middleBox"
               @mousedown="handleMouseDown"
-            @mousemove="handleMouseMove"
-            @mouseup="handleMouseUp"
-            @mouseleave="handleMouseLeave"
-            @scroll="handleScroll"
+              @mousemove="handleMouseMove"
+              @mouseup="handleMouseUp"
+              @mouseleave="handleMouseLeave"
+              @scroll="handleScroll"
             >
               <div
                 v-for="(courseType, index) in specificCourses"
@@ -53,15 +48,17 @@
                   <div class="bg-image-container" :style="{ backgroundImage: `url(${courseType.bgImage})` }">
                     <!-- 星星图标 -->
                     <template v-if="!courseType.isDisabled">
-                      <div
-                        v-for="starIndex in 5"
-                        :key="starIndex"
-                        class="star-icon"
-                        :style="{
-                          backgroundImage: `url(${starIndex <= courseType.progress ? star01Image : star02Image})`,
-                          left: `${30 + (starIndex - 1) * 30}px`
-                        }"
-                      ></div>
+                      <div class="stars-container">
+                        <div
+                          v-for="starIndex in 5"
+                          :key="starIndex"
+                          class="star-icon"
+                          :style="{
+                            backgroundImage: `url(${starIndex <= courseType.progress ? star01Image : star02Image})`,
+                            '--star-index': starIndex
+                          }"
+                        ></div>
+                      </div>
                     </template>
                   </div>
                   <div class="text-container">
@@ -74,35 +71,33 @@
                 </div>
               </div>
             </div>
-
-        <!-- 右切换按钮 -->
-        <div class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': currentIndex >= specificCourses.length - 3 }" :disabled="currentIndex >= specificCourses.length - 3">
-          <el-icon class="btn-icon" :class="{ 'disabled-icon': currentIndex >= specificCourses.length - 3 }"><ArrowRightBold /></el-icon>
-        </div>
-
          </div>
 
         <!-- 底部切换按钮 -->
         <div class="bottom-box">
-          <div class="line-container">
-            <div class="bold-line"></div>
-            <div
-              v-for="(button, index) in circleButtons"
-              :key="index"
-              class="circle-button"
-              :class="{ 'active': activeButton === index }"
-              @click="activeButton = index"
-            >
-            </div>
+          <!-- 左切换按钮 -->
+          <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="circleButtons.length > 0">
+            <el-slider v-model="activeButton" :max="circleButtons.length - 1" :step="1" :show-tooltip="false" />
+          </div>
+          <!-- 右切换按钮 -->
+          <div class="carousel-btn next-btn" @click="nextSlide" :class="{ 'disabled-btn': activeButton >= specificCourses.length - 1 }" :disabled="activeButton >= specificCourses.length - 1">
+            <img :src="rightbtn" alt="右按钮" class="btn-image" :class="{ 'disabled-icon': activeButton >= specificCourses.length - 1 }" />
           </div>
         </div>
     </div>
 </template>
 
 <script setup>
-import { ref, reactive, watch, onMounted, onUnmounted } from 'vue'
+import { ref, reactive, watch, onMounted } from 'vue'
 // 返回图标
-import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue';
+import { ArrowLeftBold } from '@element-plus/icons-vue';
+// 导入按钮图片
+import leftbtn from '@/assets/programming/leftbtn.png'
+import rightbtn from '@/assets/programming/rightbtn.png'
 // 导入路由
 import { useRouter, useRoute } from 'vue-router';
 // 获取类型列表
@@ -136,8 +131,6 @@ const specificCourses = reactive([])
 
 // 当前激活的按钮索引
 const activeButton = ref(0)
-// 轮播图当前索引
-const currentIndex = ref(0)
 
 // 在获取到categoryId后再调用获取类型列表getTypeByThemeId接口
 const fetchTopicList = () => {
@@ -171,23 +164,17 @@ const fetchTopicList = () => {
   }
 }
 
-// 定义圆形按钮数据(根据课程数量动态生成)
-const circleButtons = reactive(specificCourses.map((_, index) => ({ text: String(index + 1) })))
+// 定义圆形按钮数据
+const circleButtons = reactive([])
 
 // 自动滚动到中间位置
 watch(activeButton, (newIndex) => {
   if (middleBox.value && newIndex !== -1) {
-    const containerWidth = middleBox.value.clientWidth;
-    const calculatedIndex = Math.max(0, Math.min(
-      specificCourses.length - 3, 
-      Math.round(newIndex / 3) * 3
-    ));
-    currentIndex.value = calculatedIndex;
-    
     // 找到对应的课程卡片元素
     const courseElement = middleBox.value.querySelector(`.middle-inner-box:nth-child(${newIndex + 1})`);
     if (courseElement) {
       // 计算滚动位置,选中的卡片居中
+      const containerWidth = middleBox.value.clientWidth;
       const elementLeft = courseElement.offsetLeft;
       const elementWidth = courseElement.offsetWidth;
       // 计算居中位置
@@ -200,7 +187,6 @@ watch(activeButton, (newIndex) => {
     }
   }
 });
-
 // 拖动相关变量
 const isDragging = ref(false)
 const startX = ref(0)
@@ -233,55 +219,19 @@ const handleMouseLeave = () => {
 }
 
 // 滚动事件处理函数
-const handleScroll = () => {
-  if (middleBox.value && !isDragging.value) {
-    // 检查是否滚动到最右侧
-    const { scrollLeft, scrollWidth, clientWidth } = middleBox.value;
-    // 当滚动到最右侧时,禁用右侧箭头
-    if (scrollLeft + clientWidth >= scrollWidth - 10) {
-      currentIndex.value = Math.max(0, specificCourses.length - 3);
-    } else {
-      // 向右滑动,左侧按钮正常显示
-      if (scrollLeft > 10) {
-        // 根据滚动位置计算当前索引,但不限制为0
-        currentIndex.value = Math.max(0, Math.min(
-          specificCourses.length - 3, 
-          Math.round(scrollLeft / (clientWidth * 0.75))
-        ));
-      } else { // 滚动到最左侧
-        currentIndex.value = 0;
-      }
-    }
-  }
-}
+const handleScroll = () => {}
 
-// 上一
+// 上一条数据
 const prevSlide = () => {
-  if (currentIndex.value > 0) {
-    currentIndex.value = Math.max(0, currentIndex.value - 3)
-    // 滚动到对应位置
-    if (middleBox.value) {
-      const scrollAmount = middleBox.value.clientWidth * 0.75
-      middleBox.value.scrollTo({
-        left: Math.max(0, middleBox.value.scrollLeft - scrollAmount),
-        behavior: 'smooth'
-      })
-    }
+  if (activeButton.value > 0) {
+    activeButton.value -= 1;
   }
 }
 
-// 下一
+// 下一条数据
 const nextSlide = () => {
-  if (currentIndex.value < specificCourses.length - 3) {
-    currentIndex.value = Math.min(specificCourses.length - 3, currentIndex.value + 3)
-    // 滚动到对应位置
-    if (middleBox.value) {
-      const scrollAmount = middleBox.value.clientWidth * 0.75
-      middleBox.value.scrollTo({
-        left: middleBox.value.scrollLeft + scrollAmount,
-        behavior: 'smooth'
-      })
-    }
+  if (activeButton.value < specificCourses.length - 1) {
+    activeButton.value += 1;
   }
 }
 
@@ -290,12 +240,10 @@ const middleBox = ref(null)
 
 // 组件挂载时获取路由参数设置标题和课程ID
 onMounted(() => {
-
   const title = route.query.courseTitle
   if (title) {
     pageTitle.value = title
   }
-
   const id = route.query.categoryId
   if (id) {
     categoryId.value = id
@@ -311,7 +259,6 @@ const goToProgrammingList = (courseType, index) => {
     Message().notifyWarning('您的账号并未开放此课程!', true)
     return
   }
-
   // 设置当前选中项
   activeButton.value = index;
   // 跳转ProgrammingCourset页面,并传递课程信息作为参数
@@ -418,7 +365,7 @@ const goToProgrammingList = (courseType, index) => {
 }
 
 .middle-wrapper {
-  height: 80%;
+  height: 75%;
   overflow: hidden; /* 溢出隐藏 */
   position: relative;
   display: flex;
@@ -427,9 +374,8 @@ const goToProgrammingList = (courseType, index) => {
 }
 
 .middle-box {
-  min-width: rpx(660); /* 固定最小宽度 */
+  min-width: 100%; /* 固定最小宽度 */
   height: 100%;
-  margin: 0 rpx(50);
   overflow-x: auto; /* 水平滚动条 */
   overflow-y: hidden; /* 取消上下滚动 */
   white-space: nowrap; /* 防止元素换行 */
@@ -448,7 +394,8 @@ const goToProgrammingList = (courseType, index) => {
   display: inline-flex;
   align-items: center; /* 垂直居中 */
   justify-content: center; /* 水平居中 */
-  margin-left: rpx(30);
+  margin-right: rpx(20);
+  margin-left: rpx(20);
   vertical-align: middle; /* 垂直居中对齐 */
 }
 
@@ -505,7 +452,7 @@ const goToProgrammingList = (courseType, index) => {
 /* 禁用状态样式 */
 .new-white-box.disabled {
   cursor: not-allowed;
-  filter: grayscale(0%); /* 改为100%黑白色 */
+  filter: grayscale(0%);
   pointer-events: none;
   position: relative;
 }
@@ -548,6 +495,16 @@ const goToProgrammingList = (courseType, index) => {
   position: relative;
 }
 
+/* 星星容器样式 */
+.stars-container {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: rpx(40);
+  z-index: 1;
+}
+
 /* star图标样式 */
 .star-icon {
   position: absolute;
@@ -559,7 +516,9 @@ const goToProgrammingList = (courseType, index) => {
   background-repeat: no-repeat;
   z-index: 1;
   transform-origin: left;
-  transform: scale(0.91);
+  transform: scale(1);
+  // 星星间距
+  left: calc(rpx(15) + (var(--star-index) - 1) * rpx(15));
 }
 
 /* 文字容器 */
@@ -600,94 +559,94 @@ const goToProgrammingList = (courseType, index) => {
 }
 
 .line-container {
-  width: 65%;
+  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(-5);
+    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;
+  }
 }
 
-.bold-line {
-  position: absolute;
-  width: 100%;
-  height: rpx(5);
-  background-color: rgba(37, 115, 188, 0.5);
-  border-radius: rpx(3);
-}
 
-.circle-button {
-  width: rpx(7);
-  height: rpx(7);
-  border-radius: 50%;
-  background-color: rgba(255, 255, 255);
-  border: rpx(1) solid #00c1fc;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  cursor: pointer;
-  transition: all 0.3s ease;
-  z-index: 1;
-}
-.circle-button:hover {
-  background-color: white;
-  transform: scale(1.5); // 放大效果
-}
-.circle-button.active {
-  background-color: #f9df04;
-  border: rpx(1.5) solid #00c1fc;
-  color: white;
-  transform: scale(2);
-  box-shadow: 0 0 rpx(10) rgba(0, 0, 0, 0.5);
-}
 
 /* 轮播图按钮样式 */
 .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: 10;
-  box-shadow: 0 rpx(5) rpx(10) rgba(0, 0, 0, 0.2);
   transition: all 0.3s ease;
 }
 
 .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: 2%;
+  margin-right: rpx(20);
 }
 
 .next-btn {
-  right: 2%;
+  margin-left: rpx(20);
 }
 
-.btn-icon {
-  font-size: rpx(15);
-  color: #333;
+.btn-image {
+  width: rpx(40);
+  height: rpx(40);
+  object-fit: contain;
 }
 
 </style>