refactor(router): 移除PDF预览页面并优化课程详情页布局
移除不再使用的PDF预览页面及其路由配置,优化课程详情页文件列表的布局和交互
Showing
4 changed files
with
16 additions
and
139 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-03-20 20:36:36 | 2 | * @Date: 2025-03-20 20:36:36 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-05-08 11:14:46 | 4 | + * @LastEditTime: 2025-05-08 12:23:36 |
| 5 | * @FilePath: /mlaj/src/main.js | 5 | * @FilePath: /mlaj/src/main.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -18,10 +18,10 @@ import { library } from '@fortawesome/fontawesome-svg-core' | ... | @@ -18,10 +18,10 @@ import { library } from '@fortawesome/fontawesome-svg-core' |
| 18 | /* import font awesome icon component */ | 18 | /* import font awesome icon component */ |
| 19 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' | 19 | import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' |
| 20 | /* import specific icons */ | 20 | /* import specific icons */ |
| 21 | -import { faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle } from '@fortawesome/free-solid-svg-icons' | 21 | +import { faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle, faDownload } from '@fortawesome/free-solid-svg-icons' |
| 22 | 22 | ||
| 23 | /* add icons to the library */ | 23 | /* add icons to the library */ |
| 24 | -library.add(faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle) | 24 | +library.add(faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle, faDownload ) |
| 25 | 25 | ||
| 26 | const app = createApp(App) | 26 | const app = createApp(App) |
| 27 | // 屏蔽警告信息 | 27 | // 屏蔽警告信息 | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-03-20 20:36:36 | 2 | * @Date: 2025-03-20 20:36:36 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-04-18 10:08:35 | 4 | + * @LastEditTime: 2025-05-08 12:06:46 |
| 5 | * @FilePath: /mlaj/src/router/routes.js | 5 | * @FilePath: /mlaj/src/router/routes.js |
| 6 | * @Description: 路由地址映射配置 | 6 | * @Description: 路由地址映射配置 |
| 7 | */ | 7 | */ |
| ... | @@ -219,11 +219,5 @@ export const routes = [ | ... | @@ -219,11 +219,5 @@ export const routes = [ |
| 219 | title: '课程集合页面', | 219 | title: '课程集合页面', |
| 220 | } | 220 | } |
| 221 | }, | 221 | }, |
| 222 | - { | ||
| 223 | - path: '/pdf-preview', | ||
| 224 | - name: 'pdf-preview', | ||
| 225 | - component: () => import('../views/study/PdfPreviewPage.vue'), | ||
| 226 | - meta: { title: 'PDF预览' }, | ||
| 227 | - }, | ||
| 228 | ...checkinRoutes, | 222 | ...checkinRoutes, |
| 229 | ] | 223 | ] | ... | ... |
src/views/study/PdfPreviewPage.vue
deleted
100644 → 0
| 1 | -<!-- | ||
| 2 | - * @Date: 2024-01-17 | ||
| 3 | - * @Description: PDF预览页面 | ||
| 4 | ---> | ||
| 5 | -<template> | ||
| 6 | - <div class="pdf-preview-page bg-white min-h-screen flex flex-col"> | ||
| 7 | - <!-- 顶部导航栏 --> | ||
| 8 | - <div class="flex items-center justify-between p-4 bg-white border-b sticky top-0 z-10"> | ||
| 9 | - <div class="flex items-center space-x-2"> | ||
| 10 | - <font-awesome-icon icon="file-pdf" class="text-red-500 text-xl" /> | ||
| 11 | - <span class="text-gray-900 font-medium">{{ title }}</span> | ||
| 12 | - </div> | ||
| 13 | - <div class="flex items-center space-x-4"> | ||
| 14 | - <a :href="pdfUrl" target="_blank" class="text-blue-600 hover:text-blue-800"> | ||
| 15 | - <font-awesome-icon icon="external-link-alt" class="mr-1" /> | ||
| 16 | - 新窗口打开 | ||
| 17 | - </a> | ||
| 18 | - <button @click="goBack" class="text-gray-500 hover:text-gray-700"> | ||
| 19 | - <font-awesome-icon icon="times" /> | ||
| 20 | - </button> | ||
| 21 | - </div> | ||
| 22 | - </div> | ||
| 23 | - | ||
| 24 | - <!-- PDF内容区域 --> | ||
| 25 | - <div class="flex-1 overflow-y-auto bg-gray-100 p-4"> | ||
| 26 | - <div v-for="pageNum in pageNums" :key="pageNum" class="mb-4" ref="pageRefs"> | ||
| 27 | - <VuePdfEmbed | ||
| 28 | - v-if="pageVisibility[pageNum]" | ||
| 29 | - :source="{ url: pdfUrl }" | ||
| 30 | - :page="pageNum" | ||
| 31 | - :scale="1.5" | ||
| 32 | - :render-text="true" | ||
| 33 | - style="width: 100%;" | ||
| 34 | - /> | ||
| 35 | - </div> | ||
| 36 | - </div> | ||
| 37 | - </div> | ||
| 38 | -</template> | ||
| 39 | - | ||
| 40 | -<script setup> | ||
| 41 | -import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue'; | ||
| 42 | -import { useRoute, useRouter } from 'vue-router'; | ||
| 43 | -import VuePdfEmbed, { useVuePdfEmbed } from 'vue-pdf-embed'; | ||
| 44 | - | ||
| 45 | -const route = useRoute(); | ||
| 46 | -const router = useRouter(); | ||
| 47 | - | ||
| 48 | -// 获取路由参数 | ||
| 49 | -const title = ref(route.query.title || 'PDF预览'); | ||
| 50 | -const pdfUrl = ref(route.query.url || ''); | ||
| 51 | - | ||
| 52 | -// PDF页面相关 | ||
| 53 | -const pageRefs = ref([]); | ||
| 54 | -const pageVisibility = ref({}); | ||
| 55 | -let pageIntersectionObserver; | ||
| 56 | - | ||
| 57 | -// 使用PDF嵌入组件 | ||
| 58 | -const { doc } = useVuePdfEmbed({ | ||
| 59 | - source: { url: pdfUrl.value }, | ||
| 60 | -}); | ||
| 61 | - | ||
| 62 | -// 计算总页数 | ||
| 63 | -const pageNums = computed(() => | ||
| 64 | - doc.value | ||
| 65 | - ? [...Array(doc.value.numPages + 1).keys()].slice(1) | ||
| 66 | - : [] | ||
| 67 | -); | ||
| 68 | - | ||
| 69 | -// 重置页面交叉观察器 | ||
| 70 | -const resetPageIntersectionObserver = () => { | ||
| 71 | - pageIntersectionObserver?.disconnect(); | ||
| 72 | - pageIntersectionObserver = new IntersectionObserver((entries) => { | ||
| 73 | - entries.forEach((entry) => { | ||
| 74 | - if (entry.isIntersecting) { | ||
| 75 | - const index = pageRefs.value.indexOf(entry.target); | ||
| 76 | - const pageNum = pageNums.value[index]; | ||
| 77 | - pageVisibility.value[pageNum] = true; | ||
| 78 | - } | ||
| 79 | - }); | ||
| 80 | - }); | ||
| 81 | - pageRefs.value.forEach((element) => { | ||
| 82 | - if (element) { | ||
| 83 | - pageIntersectionObserver.observe(element); | ||
| 84 | - } | ||
| 85 | - }); | ||
| 86 | -}; | ||
| 87 | - | ||
| 88 | -// 返回上一页 | ||
| 89 | -const goBack = () => { | ||
| 90 | - router.back(); | ||
| 91 | -}; | ||
| 92 | - | ||
| 93 | -// 监听页数变化 | ||
| 94 | -watch(pageNums, (newPageNums) => { | ||
| 95 | - if (newPageNums.length > 0) { | ||
| 96 | - pageVisibility.value = { [newPageNums[0]]: true }; | ||
| 97 | - nextTick(resetPageIntersectionObserver); | ||
| 98 | - } | ||
| 99 | -}); | ||
| 100 | - | ||
| 101 | -// 组件卸载前清理 | ||
| 102 | -onBeforeUnmount(() => { | ||
| 103 | - pageIntersectionObserver?.disconnect(); | ||
| 104 | -}); | ||
| 105 | -</script> | ||
| 106 | - | ||
| 107 | -<style lang="less" scoped> | ||
| 108 | -.pdf-preview-page { | ||
| 109 | - .pdf-content { | ||
| 110 | - background-color: #f3f4f6; | ||
| 111 | - } | ||
| 112 | -} | ||
| 113 | -</style> |
| ... | @@ -50,23 +50,19 @@ | ... | @@ -50,23 +50,19 @@ |
| 50 | <div v-if="course.course_type === 'file'" class="w-full relative bg-white rounded-lg shadow-sm"> | 50 | <div v-if="course.course_type === 'file'" class="w-full relative bg-white rounded-lg shadow-sm"> |
| 51 | <div class="p-4 space-y-3"> | 51 | <div class="p-4 space-y-3"> |
| 52 | <div v-for="(item, index) in courseFile?.list" :key="index" class="group hover:bg-gray-50 transition-colors rounded-lg p-3"> | 52 | <div v-for="(item, index) in courseFile?.list" :key="index" class="group hover:bg-gray-50 transition-colors rounded-lg p-3"> |
| 53 | - <div class="flex items-center space-x-3"> | 53 | + <div class="flex items-center justify-between space-x-3 px-2"> |
| 54 | - <div class="flex-shrink-0"> | 54 | + <div class="flex items-center space-x-3 flex-1 min-w-0"> |
| 55 | - <font-awesome-icon icon="file-alt" class="text-gray-400 text-xl" /> | 55 | + <font-awesome-icon icon="file-alt" class="text-gray-400 text-lg flex-shrink-0" /> |
| 56 | - </div> | 56 | + <h3 class="text-xs font-medium text-gray-900 truncate">{{ item.title }}</h3> |
| 57 | - <div class="flex-1 min-w-0"> | ||
| 58 | - <h3 class="text-sm font-medium text-gray-900 truncate">{{ item.title }}</h3> | ||
| 59 | - <!-- PDF文件预览 --> | ||
| 60 | - <template v-if="item.url.toLowerCase().endsWith('.pdf')"> | ||
| 61 | - <button @click="openPdfViewer(item)" class="mt-2 w-full text-left text-blue-600 hover:text-blue-800 hover:underline"> | ||
| 62 | - <font-awesome-icon icon="eye" class="mr-1" /> | ||
| 63 | - 预览PDF | ||
| 64 | - </button> | ||
| 65 | - </template> | ||
| 66 | - <template v-else> | ||
| 67 | - <a :href="item.url" target="_blank" class="text-sm text-blue-600 hover:text-blue-800 hover:underline truncate block mt-1">打开文件</a> | ||
| 68 | - </template> | ||
| 69 | </div> | 57 | </div> |
| 58 | + <template v-if="item.url.toLowerCase().endsWith('.pdf')"> | ||
| 59 | + <a :href="item.url" download class="text-xs text-blue-600 hover:text-blue-800 hover:underline whitespace-nowrap"> | ||
| 60 | + 查看文件 | ||
| 61 | + </a> | ||
| 62 | + </template> | ||
| 63 | + <template v-else> | ||
| 64 | + <a :href="item.url" target="_blank" class="text-xs text-blue-600 hover:text-blue-800 hover:underline whitespace-nowrap">打开文件</a> | ||
| 65 | + </template> | ||
| 70 | </div> | 66 | </div> |
| 71 | </div> | 67 | </div> |
| 72 | </div> | 68 | </div> | ... | ... |
-
Please register or login to post a comment