hookehuyr

feat(PdfViewer): 添加PDF加载超时处理机制

添加超时监控功能,当PDF加载超过设定时间或长时间无进度更新时自动停止加载并显示错误信息
<!--
* @Date: 2025-01-21
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-10-21 15:20:39
* @LastEditTime: 2025-10-22 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;
......