hookehuyr

refactor(PdfViewer): 优化PDF查看器关闭逻辑和资源清理

添加PDF组件引用并实现销毁方法
延迟清理状态确保组件完成内部清理
新增onClose和onDestroy事件通知父组件
......@@ -11,14 +11,31 @@
<div class="pdf-viewer-container">
<!-- PDF内容区域 -->
<div class="pdf-content" :class="{ 'pdf-no-select': preventSave }">
<PDF v-if="url && show && !loadingError" :src="url" :showProgress="true" :progressColor="'#1989fa'"
:showPageTooltip="true" :showBackToTopBtn="true" :scrollThreshold="300"
<PDF v-if="url && show && !loadingError"
ref="pdfRef"
:src="url"
:showProgress="true"
:progressColor="'#1989fa'"
:showPageTooltip="true"
:showBackToTopBtn="true"
:scrollThreshold="300"
:pdfWidth="`${Math.round(100 * zoomLevel)}%`"
:rowGap="8" :page="1" :cMapUrl="'https://unpkg.com/pdfjs-dist@3.7.107/cmaps/'"
:withCredentials="false" :useSystemFonts="true" :stopAtErrors="false" :disableFontFace="false"
:disableRange="false" :disableStream="false" :disableAutoFetch="false" @onProgress="handleProgress"
@onComplete="handleComplete" @onScroll="handleScroll" @onPageChange="handlePageChange"
@onPdfInit="handlePdfInit" @onError="handlePdfError" />
:rowGap="8"
:page="1"
:cMapUrl="'https://unpkg.com/pdfjs-dist@3.7.107/cmaps/'"
:withCredentials="false"
:useSystemFonts="true"
:stopAtErrors="false"
:disableFontFace="false"
:disableRange="false"
:disableStream="false"
:disableAutoFetch="false"
@onProgress="handleProgress"
@onComplete="handleComplete"
@onScroll="handleScroll"
@onPageChange="handlePageChange"
@onPdfInit="handlePdfInit"
@onError="handlePdfError" />
<!-- 错误状态显示 -->
<div v-if="loadingError" class="error-container">
......@@ -34,7 +51,7 @@
</div>
<!-- 关闭按钮 -->
<van-button class="close-btn" type="default" icon="cross" round @click="emit('update:show', false)" />
<van-button class="close-btn" type="default" icon="cross" round @click="handleClose" />
<!-- 缩放控制按钮 -->
<div v-if="!loading && !loadingError" class="zoom-controls">
......@@ -70,7 +87,7 @@
</template>
<script setup>
import { ref, watch, nextTick } from 'vue';
import { ref, watch, nextTick, onUnmounted } from 'vue';
import PDF from "pdf-vue3";
/**
......@@ -102,7 +119,7 @@ const props = defineProps({
/**
* 事件定义
*/
const emit = defineEmits(['update:show', 'onLoad', 'onProgress', 'onComplete']);
const emit = defineEmits(['update:show', 'onLoad', 'onProgress', 'onComplete', 'onClose', 'onDestroy']);
// 响应式数据
const loading = ref(true);
......@@ -111,6 +128,7 @@ const loadingError = ref(false);
const errorMessage = ref('');
const zoomLevel = ref(1); // 缩放级别,1为100%
const scrollPosition = ref({ x: 0, y: 0 }); // 记录滚动位置
const pdfRef = ref(null); // PDF组件引用
// 超时处理相关
const loadingTimeout = ref(30000); // 超时时间,默认30秒
......@@ -131,13 +149,21 @@ watch(() => props.show, (newVal) => {
errorMessage.value = '';
zoomLevel.value = 1; // 重置缩放级别
} else if (!newVal) {
// 弹窗关闭时重置状态
// 弹窗关闭时重置状态并清理资源
clearAllTimers(); // 清除计时器
loading.value = true;
// 延迟清理,确保PDF组件有时间完成内部清理
setTimeout(() => {
loading.value = false;
loadingError.value = false;
loadingProgress.value = 0;
errorMessage.value = '';
zoomLevel.value = 1; // 重置缩放级别
scrollPosition.value = { x: 0, y: 0 }; // 重置滚动位置
// 触发关闭销毁事件,通知父组件清理引用
emit('onClose');
}, 100); // 100ms延迟,给PDF组件时间清理
}
});
......@@ -302,6 +328,28 @@ const retryLoad = () => {
};
/**
* 处理关闭弹窗
*/
const handleClose = () => {
// 先清理所有计时器
clearAllTimers();
// 如果PDF组件存在,尝试清理其内部状态
if (pdfRef.value && typeof pdfRef.value.destroy === 'function') {
try {
pdfRef.value.destroy();
} catch (error) {
console.warn('PDF组件销毁时出现警告:', error);
}
}
// 使用nextTick确保在DOM更新前完成清理
nextTick(() => {
emit('update:show', false);
});
};
/**
* 放大PDF
*/
const zoomIn = () => {
......