|
@@ -1,7 +1,7 @@
|
|
|
<template>
|
|
|
<div class="pptist-student-viewer" :class="{ 'fullscreen': isFullscreen, 'laser-pen': laserPen }">
|
|
|
<!-- 左侧导航栏 -->
|
|
|
- <div class="layout-content-left">
|
|
|
+ <div class="layout-content-left" v-show="type == '1'">
|
|
|
<div class="thumbnails">
|
|
|
<div class="viewer-header">
|
|
|
<h3>幻灯片导航</h3>
|
|
@@ -16,12 +16,10 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="page-number">幻灯片 {{ slideIndex + 1 }} / {{ slides.length }}</div>
|
|
|
-
|
|
|
- <!-- 进度条 -->
|
|
|
+ <!-- <div class="page-number">幻灯片 {{ slideIndex + 1 }} / {{ slides.length }}</div>
|
|
|
<div class="progress-bar">
|
|
|
<div class="progress-fill" :style="{ width: `${((slideIndex + 1) / slides.length) * 100}%` }"></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
@@ -50,41 +48,47 @@
|
|
|
|
|
|
<div class="viewer-canvas" ref="viewerCanvasRef">
|
|
|
<!-- 全屏时:使用放映功能 -->
|
|
|
- <ScreenSlideList v-if="isFullscreen && showSlideList" :slideWidth="slideWidth"
|
|
|
+ <!-- <ScreenSlideList :slideWidth="slideWidth"
|
|
|
:slideHeight="slideHeight" :animationIndex="0" :turnSlideToId="() => { }"
|
|
|
- :manualExitFullscreen="() => { }" />
|
|
|
+ :manualExitFullscreen="() => { }" /> -->
|
|
|
|
|
|
<!-- 不全屏时:使用编辑模式的显示比例和居中逻辑 -->
|
|
|
- <div v-else-if="showSlideList" class="slide-list-wrap" :style="{
|
|
|
- width: (slideWidth * canvasScale) + 'px',
|
|
|
- height: (slideHeight * canvasScale) + 'px',
|
|
|
- left: `${(containerWidth - slideWidth * canvasScale) / 2}px`,
|
|
|
- top: `${(containerHeight - slideHeight * canvasScale) / 2}px`
|
|
|
+ <div class="slide-list-wrap" :style="{
|
|
|
+ width: isFullscreen ? '100%' : (slideWidth * canvasScale) + 'px',
|
|
|
+ height: isFullscreen ? '100%' : (slideHeight * canvasScale) + 'px',
|
|
|
+ left: isFullscreen ? '0' : `${(containerWidth - slideWidth * canvasScale) / 2}px`,
|
|
|
+ top: isFullscreen ? '0' : `${(containerHeight - slideHeight * canvasScale) / 2}px`
|
|
|
}">
|
|
|
<div class="viewport" v-if="false">
|
|
|
- <!-- 背景 -->
|
|
|
<div class="background" :style="backgroundStyle"></div>
|
|
|
|
|
|
- <!-- 使用ScreenElement组件显示元素 -->
|
|
|
<ScreenElement v-for="(element, index) in elementList" :key="element.id" :elementInfo="element"
|
|
|
:elementIndex="index + 1" :animationIndex="0" :turnSlideToId="() => { }"
|
|
|
:manualExitFullscreen="() => { }" />
|
|
|
</div>
|
|
|
|
|
|
- <!-- 加载状态提示 -->
|
|
|
- <ScreenSlideList v-if="showSlideList" :slideWidth="slideWidth * canvasScale"
|
|
|
+ <ScreenSlideList :slideWidth="slideWidth * canvasScale"
|
|
|
:slideHeight="slideHeight * canvasScale" :animationIndex="0" :turnSlideToId="() => { }"
|
|
|
:manualExitFullscreen="() => { }" />
|
|
|
</div>
|
|
|
- <div v-else-if="!showSlideList" class="loading-indicator">
|
|
|
- <div class="loading-text">正在重新加载...</div>
|
|
|
- </div>
|
|
|
<!-- 全屏时的左右下角工具按钮 -->
|
|
|
<div v-if="isFullscreen" class="tools-left">
|
|
|
<IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="previousSlide" />
|
|
|
<IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="nextSlide" />
|
|
|
</div>
|
|
|
|
|
|
+ <!-- 作业提交按钮 - 当当前幻灯片包含iframe时显示 -->
|
|
|
+ <div
|
|
|
+ v-if="currentSlideHasIframe"
|
|
|
+ class="homework-submit-btn"
|
|
|
+ :style="{ right: getHomeworkButtonRight() + 'px' }"
|
|
|
+ @click="handleHomeworkSubmit"
|
|
|
+ v-tooltip="'作业提交'"
|
|
|
+ >
|
|
|
+ <IconEdit class="tool-btn" />
|
|
|
+ <span class="btn-text">作业提交</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 功能组件 -->
|
|
|
<SlideThumbnails v-if="slideThumbnailModelVisible" :turnSlideToIndex="goToSlide"
|
|
|
@close="slideThumbnailModelVisible = false" />
|
|
@@ -109,6 +113,13 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+ <div class="layout-content-right" v-show="type == '1'">
|
|
|
+ <div class="thumbnails">
|
|
|
+ <div class="viewer-header">
|
|
|
+ <h3>左侧导航</h3>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
@@ -116,6 +127,7 @@
|
|
|
import { computed, ref, onMounted, onUnmounted, nextTick, inject } from 'vue'
|
|
|
import { storeToRefs } from 'pinia'
|
|
|
import { useSlidesStore } from '@/store'
|
|
|
+import { ElementTypes } from '@/types/slides'
|
|
|
import { fillDigit } from '@/utils/common'
|
|
|
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
|
|
|
import ScreenSlideList from '@/views/Screen/ScreenSlideList.vue'
|
|
@@ -125,6 +137,18 @@ import WritingBoardTool from '@/views/Screen/WritingBoardTool.vue'
|
|
|
import CountdownTimer from '@/views/Screen/CountdownTimer.vue'
|
|
|
import useSlideBackgroundStyle from '@/hooks/useSlideBackgroundStyle'
|
|
|
import useImport from '@/hooks/useImport'
|
|
|
+import message from '@/utils/message'
|
|
|
+
|
|
|
+// 定义组件props
|
|
|
+interface Props {
|
|
|
+ courseid?: string | null
|
|
|
+ type?: string | null
|
|
|
+}
|
|
|
+
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
+ courseid: null,
|
|
|
+ type: null
|
|
|
+})
|
|
|
|
|
|
// 图标组件通过全局注册,无需导入
|
|
|
|
|
@@ -154,7 +178,7 @@ const slideHeight = ref(0)
|
|
|
|
|
|
// 计算幻灯片尺寸的函数
|
|
|
const calculateSlideSize = () => {
|
|
|
- const slideWrapRef = viewerCanvasRef.value || document.body
|
|
|
+ const slideWrapRef = isFullscreen.value ? document.body : viewerCanvasRef.value
|
|
|
const winWidth = slideWrapRef.clientWidth
|
|
|
const winHeight = slideWrapRef.clientHeight
|
|
|
|
|
@@ -212,7 +236,7 @@ const calculateScale = () => {
|
|
|
const scale = Math.min(scaleX, scaleY) * 0.9
|
|
|
|
|
|
console.log('最终缩放比例:', scale)
|
|
|
- canvasScale.value = scale
|
|
|
+ canvasScale.value = isFullscreen.value ? 1 : props.type == '1' ? 0.9 : 0.95
|
|
|
}
|
|
|
else {
|
|
|
console.error('找不到容器元素')
|
|
@@ -233,6 +257,11 @@ const elementList = computed(() => {
|
|
|
return currentSlide.value?.elements || []
|
|
|
})
|
|
|
|
|
|
+// 检测当前幻灯片是否包含iframe元素
|
|
|
+const currentSlideHasIframe = computed(() => {
|
|
|
+ return elementList.value.some(element => element.type === ElementTypes.FRAME)
|
|
|
+})
|
|
|
+
|
|
|
// 跳转到指定幻灯片
|
|
|
const goToSlide = (index: number) => {
|
|
|
console.log('goToSlide 被调用,目标索引:', index)
|
|
@@ -365,6 +394,24 @@ const backToEditor = () => {
|
|
|
window.location.href = '/'
|
|
|
}
|
|
|
|
|
|
+// 作业提交功能
|
|
|
+const handleHomeworkSubmit = () => {
|
|
|
+ console.log('作业提交按钮被点击')
|
|
|
+ // 这里可以跳转到作业提交页面,并传递当前幻灯片的ID
|
|
|
+ // 例如:window.location.href = `/course/${props.courseid}/homework/${currentSlide.value?.id}`
|
|
|
+ message.info('作业提交功能暂未实现')
|
|
|
+}
|
|
|
+
|
|
|
+// 获取作业提交按钮的右侧位置
|
|
|
+const getHomeworkButtonRight = () => {
|
|
|
+ if (isFullscreen.value) {
|
|
|
+ return 30 // 全屏时按钮在右侧30px
|
|
|
+ }
|
|
|
+ if (props.type === '1') {
|
|
|
+ return 230 // type=1时(有左侧导航栏)按钮在右侧230px
|
|
|
+ }
|
|
|
+ return 30 // type=2时按钮在右侧30px
|
|
|
+}
|
|
|
|
|
|
|
|
|
// 键盘快捷键
|
|
@@ -428,6 +475,23 @@ const handleViewportSizeUpdated = (event: any) => {
|
|
|
onMounted(() => {
|
|
|
document.addEventListener('keydown', handleKeydown)
|
|
|
|
|
|
+ // 处理URL参数
|
|
|
+ if (props.courseid || props.type) {
|
|
|
+ console.log('收到URL参数:', { courseid: props.courseid, type: props.type })
|
|
|
+
|
|
|
+ // 这里可以根据courseid和type进行相应的处理
|
|
|
+ // 比如加载特定的课程数据、设置特定的显示模式等
|
|
|
+ if (props.courseid) {
|
|
|
+ console.log('课程ID:', props.courseid)
|
|
|
+ // TODO: 根据courseid加载对应的课程数据
|
|
|
+ }
|
|
|
+
|
|
|
+ if (props.type) {
|
|
|
+ console.log('类型:', props.type)
|
|
|
+ // TODO: 根据type设置特定的显示模式或功能
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 计算初始缩放比例
|
|
|
nextTick(() => {
|
|
|
calculateScale()
|
|
@@ -456,10 +520,14 @@ onMounted(() => {
|
|
|
previousSlide,
|
|
|
nextSlide,
|
|
|
enterFullscreen,
|
|
|
- toggleLaserPen
|
|
|
+ toggleLaserPen,
|
|
|
+ // 添加URL参数到全局对象中
|
|
|
+ courseid: props.courseid,
|
|
|
+ type: props.type
|
|
|
}
|
|
|
|
|
|
console.log('PPTist Student View 已加载,可通过 window.PPTistStudent 访问功能')
|
|
|
+ console.log('URL参数:', { courseid: props.courseid, type: props.type })
|
|
|
})
|
|
|
|
|
|
onUnmounted(() => {
|
|
@@ -492,6 +560,9 @@ onUnmounted(() => {
|
|
|
.layout-content-left {
|
|
|
display: none; // 全屏时隐藏左侧导航栏
|
|
|
}
|
|
|
+ .layout-content-right {
|
|
|
+ display: none; // 全屏时隐藏左侧导航栏
|
|
|
+ }
|
|
|
|
|
|
.viewer-header {
|
|
|
display: none; // 全屏时隐藏顶部标题栏
|
|
@@ -512,8 +583,16 @@ onUnmounted(() => {
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
|
|
|
+.layout-content-right {
|
|
|
+ width: 200px;
|
|
|
+ height: 100%;
|
|
|
+ background-color: #fff;
|
|
|
+ border-left: 1px solid #e0e0e0;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
.thumbnails {
|
|
|
- padding: 16px;
|
|
|
+ padding: 0;
|
|
|
|
|
|
.viewer-header {
|
|
|
margin-bottom: 16px;
|
|
@@ -527,6 +606,9 @@ onUnmounted(() => {
|
|
|
}
|
|
|
|
|
|
.thumbnail-list {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0 16px;
|
|
|
+ box-sizing: border-box;
|
|
|
.thumbnail-item {
|
|
|
position: relative;
|
|
|
margin-bottom: 12px;
|
|
@@ -685,6 +767,11 @@ onUnmounted(() => {
|
|
|
background-color: #fff;
|
|
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.01), 0 0 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
border-radius: 8px;
|
|
|
+
|
|
|
+ /* 全屏时去掉圆角 */
|
|
|
+ .pptist-student-viewer.fullscreen & {
|
|
|
+ border-radius: 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.loading-indicator {
|
|
@@ -813,6 +900,10 @@ onUnmounted(() => {
|
|
|
width: 160px;
|
|
|
}
|
|
|
|
|
|
+ .layout-content-right {
|
|
|
+ width: 160px;
|
|
|
+ }
|
|
|
+
|
|
|
.viewer-header {
|
|
|
padding: 0 16px;
|
|
|
|
|
@@ -826,4 +917,49 @@ onUnmounted(() => {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/* 作业提交按钮样式 */
|
|
|
+.homework-submit-btn {
|
|
|
+ position: fixed;
|
|
|
+ bottom: 30px;
|
|
|
+ z-index: 100;
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
+ color: white;
|
|
|
+ padding: 12px 20px;
|
|
|
+ border-radius: 25px;
|
|
|
+ cursor: pointer;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-text {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-btn {
|
|
|
+ background: transparent;
|
|
|
+ color: white;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ font-size: 16px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: transparent;
|
|
|
+ transform: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|