hookehuyr

refactor(router): 移除PDF预览页面并优化课程详情页布局

移除不再使用的PDF预览页面及其路由配置,优化课程详情页文件列表的布局和交互
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-05-08 11:14:46
* @LastEditTime: 2025-05-08 12:23:36
* @FilePath: /mlaj/src/main.js
* @Description: 文件描述
*/
......@@ -18,10 +18,10 @@ import { library } from '@fortawesome/fontawesome-svg-core'
/* import font awesome icon component */
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
/* import specific icons */
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'
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'
/* add icons to the library */
library.add(faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle)
library.add(faCirclePause, faCirclePlay, faPlay, faPause, faBackwardStep, faForwardStep, faVolumeUp, faRedo, faRepeat, faList, faChevronDown, faVolumeOff, faXmark, faFileAlt, faTimes, faEye, faFilePdf, faExternalLinkAlt, faSpinner, faExclamationCircle, faDownload )
const app = createApp(App)
// 屏蔽警告信息
......
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-04-18 10:08:35
* @LastEditTime: 2025-05-08 12:06:46
* @FilePath: /mlaj/src/router/routes.js
* @Description: 路由地址映射配置
*/
......@@ -219,11 +219,5 @@ export const routes = [
title: '课程集合页面',
}
},
{
path: '/pdf-preview',
name: 'pdf-preview',
component: () => import('../views/study/PdfPreviewPage.vue'),
meta: { title: 'PDF预览' },
},
...checkinRoutes,
]
......
<!--
* @Date: 2024-01-17
* @Description: PDF预览页面
-->
<template>
<div class="pdf-preview-page bg-white min-h-screen flex flex-col">
<!-- 顶部导航栏 -->
<div class="flex items-center justify-between p-4 bg-white border-b sticky top-0 z-10">
<div class="flex items-center space-x-2">
<font-awesome-icon icon="file-pdf" class="text-red-500 text-xl" />
<span class="text-gray-900 font-medium">{{ title }}</span>
</div>
<div class="flex items-center space-x-4">
<a :href="pdfUrl" target="_blank" class="text-blue-600 hover:text-blue-800">
<font-awesome-icon icon="external-link-alt" class="mr-1" />
新窗口打开
</a>
<button @click="goBack" class="text-gray-500 hover:text-gray-700">
<font-awesome-icon icon="times" />
</button>
</div>
</div>
<!-- PDF内容区域 -->
<div class="flex-1 overflow-y-auto bg-gray-100 p-4">
<div v-for="pageNum in pageNums" :key="pageNum" class="mb-4" ref="pageRefs">
<VuePdfEmbed
v-if="pageVisibility[pageNum]"
:source="{ url: pdfUrl }"
:page="pageNum"
:scale="1.5"
:render-text="true"
style="width: 100%;"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import VuePdfEmbed, { useVuePdfEmbed } from 'vue-pdf-embed';
const route = useRoute();
const router = useRouter();
// 获取路由参数
const title = ref(route.query.title || 'PDF预览');
const pdfUrl = ref(route.query.url || '');
// PDF页面相关
const pageRefs = ref([]);
const pageVisibility = ref({});
let pageIntersectionObserver;
// 使用PDF嵌入组件
const { doc } = useVuePdfEmbed({
source: { url: pdfUrl.value },
});
// 计算总页数
const pageNums = computed(() =>
doc.value
? [...Array(doc.value.numPages + 1).keys()].slice(1)
: []
);
// 重置页面交叉观察器
const resetPageIntersectionObserver = () => {
pageIntersectionObserver?.disconnect();
pageIntersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const index = pageRefs.value.indexOf(entry.target);
const pageNum = pageNums.value[index];
pageVisibility.value[pageNum] = true;
}
});
});
pageRefs.value.forEach((element) => {
if (element) {
pageIntersectionObserver.observe(element);
}
});
};
// 返回上一页
const goBack = () => {
router.back();
};
// 监听页数变化
watch(pageNums, (newPageNums) => {
if (newPageNums.length > 0) {
pageVisibility.value = { [newPageNums[0]]: true };
nextTick(resetPageIntersectionObserver);
}
});
// 组件卸载前清理
onBeforeUnmount(() => {
pageIntersectionObserver?.disconnect();
});
</script>
<style lang="less" scoped>
.pdf-preview-page {
.pdf-content {
background-color: #f3f4f6;
}
}
</style>
......@@ -50,23 +50,19 @@
<div v-if="course.course_type === 'file'" class="w-full relative bg-white rounded-lg shadow-sm">
<div class="p-4 space-y-3">
<div v-for="(item, index) in courseFile?.list" :key="index" class="group hover:bg-gray-50 transition-colors rounded-lg p-3">
<div class="flex items-center space-x-3">
<div class="flex-shrink-0">
<font-awesome-icon icon="file-alt" class="text-gray-400 text-xl" />
</div>
<div class="flex-1 min-w-0">
<h3 class="text-sm font-medium text-gray-900 truncate">{{ item.title }}</h3>
<!-- PDF文件预览 -->
<template v-if="item.url.toLowerCase().endsWith('.pdf')">
<button @click="openPdfViewer(item)" class="mt-2 w-full text-left text-blue-600 hover:text-blue-800 hover:underline">
<font-awesome-icon icon="eye" class="mr-1" />
预览PDF
</button>
</template>
<template v-else>
<a :href="item.url" target="_blank" class="text-sm text-blue-600 hover:text-blue-800 hover:underline truncate block mt-1">打开文件</a>
</template>
<div class="flex items-center justify-between space-x-3 px-2">
<div class="flex items-center space-x-3 flex-1 min-w-0">
<font-awesome-icon icon="file-alt" class="text-gray-400 text-lg flex-shrink-0" />
<h3 class="text-xs font-medium text-gray-900 truncate">{{ item.title }}</h3>
</div>
<template v-if="item.url.toLowerCase().endsWith('.pdf')">
<a :href="item.url" download class="text-xs text-blue-600 hover:text-blue-800 hover:underline whitespace-nowrap">
查看文件
</a>
</template>
<template v-else>
<a :href="item.url" target="_blank" class="text-xs text-blue-600 hover:text-blue-800 hover:underline whitespace-nowrap">打开文件</a>
</template>
</div>
</div>
</div>
......