Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
mlaj
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2025-10-22 10:05:01 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
3ca244119ac63c8df5c6d81745479ba7013c524e
3ca24411
1 parent
b98a2843
feat(PdfViewer): 添加PDF加载超时处理机制
添加超时监控功能,当PDF加载超过设定时间或长时间无进度更新时自动停止加载并显示错误信息
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
71 additions
and
10 deletions
src/components/ui/PdfViewer.vue
src/components/ui/PdfViewer.vue
View file @
3ca2441
<!--
* @Date: 2025-01-21
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-10-2
1 15:20:39
* @LastEditTime: 2025-10-2
2 09:57:57
* @FilePath: /mlaj/src/components/ui/PdfViewer.vue
* @Description: PDF预览组件 - 使用pdf-vue3库
-->
...
...
@@ -112,12 +112,19 @@ const errorMessage = ref('');
const zoomLevel = ref(1); // 缩放级别,1为100%
const scrollPosition = ref({ x: 0, y: 0 }); // 记录滚动位置
// 超时处理相关
const loadingTimeout = ref(30000); // 超时时间,默认30秒
const timeoutTimer = ref(null); // 超时计时器
const lastProgressTime = ref(0); // 最后一次进度更新时间
const progressCheckInterval = ref(null); // 进度检查间隔器
/**
* 监听show属性变化,控制PDF加载
*/
watch(() => props.show, (newVal) => {
if (newVal && props.url) {
// 重置所有状态
clearAllTimers(); // 清除之前的计时器
loading.value = true;
loadingError.value = false;
loadingProgress.value = 0;
...
...
@@ -125,6 +132,7 @@ watch(() => props.show, (newVal) => {
zoomLevel.value = 1; // 重置缩放级别
} else if (!newVal) {
// 弹窗关闭时重置状态
clearAllTimers(); // 清除计时器
loading.value = true;
loadingError.value = false;
loadingProgress.value = 0;
...
...
@@ -139,6 +147,7 @@ watch(() => props.show, (newVal) => {
watch(() => props.url, (newUrl) => {
if (newUrl && props.show) {
// URL变化时重置状态
clearAllTimers(); // 清除之前的计时器
loading.value = true;
loadingError.value = false;
loadingProgress.value = 0;
...
...
@@ -153,6 +162,8 @@ watch(() => props.url, (newUrl) => {
*/
const handleProgress = (loadRatio) => {
loadingProgress.value = Math.round(loadRatio);
// 更新最后进度时间
lastProgressTime.value = Date.now();
emit('onProgress', loadRatio);
};
...
...
@@ -160,6 +171,8 @@ const handleProgress = (loadRatio) => {
* 处理PDF下载完成
*/
const handleComplete = () => {
// 清除所有计时器
clearAllTimers();
loading.value = false;
loadingError.value = false;
loadingProgress.value = 100;
...
...
@@ -168,9 +181,53 @@ const handleComplete = () => {
};
/**
* 处理PDF滚动事件
* @param {number} scrollOffset - 滚动偏移量
* 清除所有计时器
*/
const clearAllTimers = () => {
if (timeoutTimer.value) {
clearTimeout(timeoutTimer.value);
timeoutTimer.value = null;
}
if (progressCheckInterval.value) {
clearInterval(progressCheckInterval.value);
progressCheckInterval.value = null;
}
};
/**
* 启动超时监控
*/
const startTimeoutMonitoring = () => {
// 清除之前的计时器
clearAllTimers();
// 记录开始时间
lastProgressTime.value = Date.now();
// 启动进度检查间隔器,每5秒检查一次
progressCheckInterval.value = setInterval(() => {
const now = Date.now();
const timeSinceLastProgress = now - lastProgressTime.value;
// 如果超过设定的超时时间且进度没有变化,则触发超时
if (timeSinceLastProgress > loadingTimeout.value && loading.value) {
clearAllTimers();
loadingError.value = true;
errorMessage.value = 'PDF加载超时,请检查网络连接或文件是否存在';
loading.value = false;
}
}, 5000); // 每5秒检查一次
// 设置总体超时计时器(作为备用)
timeoutTimer.value = setTimeout(() => {
if (loading.value) {
clearAllTimers();
loadingError.value = true;
errorMessage.value = 'PDF加载超时,请检查网络连接或文件是否存在';
loading.value = false;
}
}, loadingTimeout.value + 5000); // 比进度检查多5秒作为缓冲
};
const handleScroll = (scrollOffset) => {
// 记录当前滚动位置
const pdfContainer = document.querySelector('.pdf-viewer-container .pdf-content');
...
...
@@ -195,6 +252,9 @@ const handlePageChange = (page) => {
* @param {Object} pdf - PDF文档对象
*/
const handlePdfInit = (pdf) => {
// 启动超时监控
startTimeoutMonitoring();
// PDF初始化完成后的处理
loadingError.value = false;
nextTick(() => {
...
...
@@ -233,6 +293,7 @@ const handlePdfError = (error) => {
* 重试加载PDF
*/
const retryLoad = () => {
clearAllTimers(); // 清除之前的计时器
loadingError.value = false;
loading.value = true;
loadingProgress.value = 0;
...
...
@@ -250,17 +311,17 @@ const zoomIn = () => {
if (pdfContainer) {
const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2;
const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2;
const oldZoom = zoomLevel.value;
zoomLevel.value = Math.min(3, zoomLevel.value + 0.25);
const newZoom = zoomLevel.value;
// 使用nextTick确保DOM更新后再调整滚动位置
nextTick(() => {
const zoomRatio = newZoom / oldZoom;
const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2;
const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2;
pdfContainer.scrollTo({
left: Math.max(0, newScrollLeft),
top: Math.max(0, newScrollTop),
...
...
@@ -281,17 +342,17 @@ const zoomOut = () => {
if (pdfContainer) {
const centerX = pdfContainer.scrollLeft + pdfContainer.clientWidth / 2;
const centerY = pdfContainer.scrollTop + pdfContainer.clientHeight / 2;
const oldZoom = zoomLevel.value;
zoomLevel.value = Math.max(0.5, zoomLevel.value - 0.25);
const newZoom = zoomLevel.value;
// 使用nextTick确保DOM更新后再调整滚动位置
nextTick(() => {
const zoomRatio = newZoom / oldZoom;
const newScrollLeft = centerX * zoomRatio - pdfContainer.clientWidth / 2;
const newScrollTop = centerY * zoomRatio - pdfContainer.clientHeight / 2;
pdfContainer.scrollTo({
left: Math.max(0, newScrollLeft),
top: Math.max(0, newScrollTop),
...
...
@@ -310,7 +371,7 @@ const resetZoom = () => {
if (pdfContainer) {
// 重置到顶部中央位置
zoomLevel.value = 1;
nextTick(() => {
pdfContainer.scrollTo({
left: 0,
...
...
Please
register
or
login
to post a comment