Browse Source

Merge branch 'wanzi' of http://59.110.91.129:3000/zhangmengying/AIClass into wanzi

丸子 8 months ago
parent
commit
377dfe0874
2 changed files with 258 additions and 17 deletions
  1. 253 0
      src/components/PPT/PptView.vue
  2. 5 17
      src/views/AIDevelop.vue

+ 253 - 0
src/components/PPT/PptView.vue

@@ -0,0 +1,253 @@
+<template>
+    <div class="box-ppt">
+      <div class="ppt-box">
+        <!-- 添加翻页动画容器 -->
+        <div ref="pptContainer" class="ppt-container">
+          <VueOfficePptx
+              ref="pptRef"
+              :src="pptPath"
+              @error="handlePptError"
+              @rendered="handlePptRendered"
+              :animation="true"
+              :animation-speed="1.0"
+          />
+        </div>
+      </div>
+    </div>
+
+    <!-- 视频切换按钮 - 始终显示 -->
+    <div class="ppt-switch">
+      <div class="caret-left" @click="prevPage">
+        <el-button type="warning" round
+        :disabled="currentPage <= 1">
+        <img :src="leftImg" alt="Left" />上一页
+        </el-button>
+      </div>
+
+      <span class="page-info">{{ currentPage }} / {{ totalPages }}</span>
+
+      <div class="caret-right" @click="nextPage">
+        <el-button type="warning" round
+        :disabled="currentPage >= totalPages"
+        >下一页<img :src="rightImg" alt="Right" />
+        </el-button>
+      </div>
+
+    </div>
+</template>
+
+<script setup>
+import {
+  ref,
+  onMounted,
+  defineProps,
+} from 'vue'
+
+import { ElMessage } from 'element-plus'
+// 导入图标
+import leftImg from '@/assets/icon/backward.png'
+import rightImg from '@/assets/icon/f-backward.png'
+// PPT
+import  VueOfficePptx  from '@vue-office/pptx'
+
+// 新增PPT翻页相关变量
+const pptRef = ref(null)
+const currentPage = ref(1)
+const totalPages = ref(10)
+
+// 定义props
+const props = defineProps({
+  pptPath: { type: String }, // PPT路径
+})
+
+// 修改PPT渲染完成处理
+const handlePptRendered = (pptInfo) => {
+  console.log('PPT渲染完成', pptInfo);
+  // 获取总页数
+  const pageCount = pptInfo?.slides?.length || 1;
+  totalPages.value = pageCount;
+  // 确保当前页在有效范围内
+  if (currentPage.value > pageCount) {
+    currentPage.value = pageCount;
+  }
+  // 初始化滚动位置
+  scrollToPage(currentPage.value);
+}
+
+// 添加页面变更处理函数
+const handlePageChange = (newPage) => {
+  // 验证页码有效性
+  const normalizedPage = Math.max(1, Math.min(newPage + 1, totalPages.value));
+  if (currentPage.value !== normalizedPage) {
+    currentPage.value = normalizedPage;
+    console.log('页码已更新:', currentPage.value);
+  }
+};
+
+
+// 新增滚动控制变量
+const pptContainer = ref(null)
+const pageHeight = ref(620) // 单页高度
+
+const nextPage = () => {
+  if (currentPage.value < totalPages.value) {
+    currentPage.value++;
+    scrollToPage(currentPage.value);
+  }
+}
+
+// 新增翻页方法
+const prevPage = () => {
+  if (currentPage.value > 1) {
+    currentPage.value--;
+    scrollToPage(currentPage.value);
+  }
+}
+
+// 新增滚动到指定页方法
+const scrollToPage = (pageNum) => {
+  if (pptContainer.value) {
+    // 计算目标滚动位置
+    const targetPosition = (pageNum - 1) * pageHeight.value;
+    // 设置滚动位置
+    pptContainer.value.scrollTop = targetPosition;
+    console.log(`滚动到第${pageNum}页,位置: ${targetPosition}`);
+  }
+}
+
+// 初始化滚动位置
+onMounted(() => {
+  // 获取容器元素
+  pptContainer.value = document.querySelector('.ppt-container');
+  // 初始滚动到第一页
+  scrollToPage(1);
+})
+
+// PPT错误处理事件
+const handlePptError = (error) => {
+  console.error('PPT加载错误:', error)
+  ElMessage.error('PPT加载失败,请检查文件路径或格式')
+}
+</script>
+
+<style scoped lang="scss">
+@use 'sass:math';
+// 定义rpx转换函数
+@function rpx($px) {
+  @return math.div($px, 750) * 100vw;
+}
+
+.box-ppt {
+  width: 100%;
+  height: rpx(300);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  .d-player-wrap {
+    height: rpx(289);
+    width: 68.5%;
+    border-radius: rpx(12);
+    object-fit: cover;
+  }
+}
+.ppt-box{
+  width: 100%;
+  height: rpx(200);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+// 添加翻页动画样式
+.page-transition-enter-active,
+.page-transition-leave-active {
+  transition: all .5s ease;
+}
+.page-transition-enter-from {
+  opacity: .5;
+  transform: translateX(50px) scale(0.95);
+}
+.page-transition-leave-to {
+  opacity: .5;
+  transform: translateX(-50px) scale(0.95);
+}
+// 修改PPT内部预览容器样式
+::v-deep .pptx-preview-wrapper {
+  height: auto !important;
+}
+.ppt-container ::v-deep(.pptx-preview-wrapper) {
+  height: auto !important;
+  // 滚动条整体样式
+  &::-webkit-scrollbar {
+    width: rpx(0); // 滚动条宽度
+    height: rpx(0);
+  }
+
+  // 滚动条滑块样式
+  &::-webkit-scrollbar-thumb {
+    background-color: #e2ddfc; // 滑块颜色
+    border-radius: rpx(4); // 滑块圆角
+  }
+
+  // 滚动条轨道样式
+  &::-webkit-scrollbar-track {
+    background-color: rgba(143, 116, 255, 0.2); // 轨道颜色
+    border-radius: rpx(4); // 轨道圆角
+  }
+  // border-radius: rpx(12);
+}
+
+.ppt-switch {
+  width: 100%;
+  display: flex;
+  margin-top: rpx(5);
+  margin-bottom: rpx(15);
+}
+.caret-right,
+.caret-left {
+  width: rpx(50);
+  margin: auto;
+  display: flex;
+}
+.page-info{
+  color: #fff;
+}
+
+.caret-left ::v-deep(.el-button.is-round),
+.caret-right ::v-deep(.el-button.is-round) {
+  width: rpx(50);
+  height: rpx(15);
+  color: white;
+  font-size: rpx(7);
+  border-radius: none;
+  border: 1px white solid;
+  background-color: rgb(255, 255, 255, 0.5);
+  box-shadow: 0 4px 8px rgba(202, 52, 52, 0.1);
+}
+
+.caret-right img,
+.caret-left img {
+  width: rpx(12);
+}
+
+.ppt-container {
+  overflow: hidden; /* 禁用滚动条 */
+  border-radius: rpx(12);
+  width: 70%;
+  position: relative;
+  height: calc(50vw * 0.75); /* 使用vw单位实现响应式高度 */
+  max-height:80vh; /* 限制最大高度 */
+}
+
+// 修改PPT内部预览容器样式
+::v-deep .pptx-preview-wrapper {
+  height: auto !important;
+  transition: transform 0.3s ease; /* 添加平滑过渡 */
+}
+
+// 确保每张幻灯片占满容器高度
+::v-deep .slide-item {
+  height: rpx(620) !important;
+  width: 100% !important;
+  box-sizing: border-box;
+}
+</style>

+ 5 - 17
src/views/AIDevelop.vue

@@ -105,7 +105,7 @@
           <span>{{ course.courseName }}</span>
         </div>
         <!-- 视频组件 -->
-        <VideoPlayer
+        <VideoPlayer v-if="course.courseContentType === 'video'"
           :contentType="course.courseContentType"
           :videoPath="course.courseVideoPath"
           :imagePath="course.courseImagePath"
@@ -119,6 +119,7 @@
           @videoEnded="handleVideoEnded"
           @switchVideo="handleSelect"
         />
+        <PptView v-if="course.courseContentType === 'ppt'" :pptPath="course.pptPath" ref="pptRef"></PptView>
       </div>
     </div>
 
@@ -154,6 +155,7 @@ import { globalState } from '@/utils/globalState.js'
 // 导入新创建的组件
 import VideoPlayer from '@/components/videopage/VideoPlayer.vue'
 import DialogComponents from '@/components/videopage/DialogComponents.vue'
+import PptView from "@/components/PPT/PptView.vue";
 
 const router = useRouter() // 获取当前路由对象
 const route = useRoute()
@@ -279,22 +281,8 @@ const handleVideoEnded = () => {
 
 // 禁用视频
 const disableVideo = (index = course.value.key) => {
-  let dis = [
-    '3-7',
-    '3-8',
-    '3-9',
-    '3-10',
-    '3-11',
-    '3-12',
-    '3-13',
-    '4-14',
-    '5-15'
-  ]
-
-  if (
-    localStorage.getItem('userName') === 'aiTest' &&
-    dis.indexOf(index) !== -1
-  ) {
+  let dis = Number(index.substring(index.indexOf("-") + 1));
+  if (localStorage.getItem('userName') === 'aiTest' && dis > 5) {
     //提示禁用
     Message().notifyWarning('您的账号并未开放此课程!', true)
     return true