|
@@ -1,12 +1,18 @@
|
|
|
<template>
|
|
|
<el-scrollbar style="height: calc(100vh - 120px)">
|
|
|
<div class="grid-container">
|
|
|
- <div v-for="(box, index) in drawingData" :key="index" class="suit-box">
|
|
|
+ <div v-for="(box, index) in drawingData" :key="index" class="suit-box" :data-index="index">
|
|
|
<div class="pdf-box">
|
|
|
<PDFView
|
|
|
+ v-if="box.pdfPath && visiblePdfs[index]"
|
|
|
:need-to-show-pdf="true"
|
|
|
:pdf-source="baseUrl + box.pdfPath"
|
|
|
+ :key="'pdf-' + index + '-' + visiblePdfs[index]"
|
|
|
/>
|
|
|
+ <div v-else class="pdf-placeholder">
|
|
|
+ <!-- 可以添加一个简单的PDF图标或提示文字 -->
|
|
|
+ <el-icon :size="40"><Document /></el-icon>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="suit-title">{{ box?.drawingTitle }}</div>
|
|
|
<div class="suit-desc">{{ box?.created }}</div>
|
|
@@ -19,29 +25,91 @@
|
|
|
import { drawingList } from "@/api/process/reportBreak";
|
|
|
import { useProcessStore } from "@/store/modules/processView";
|
|
|
import PDFView from "@/components/PDFView/index.vue";
|
|
|
+import { onMounted, ref, onBeforeUnmount } from "vue";
|
|
|
+import { Document } from '@element-plus/icons-vue';
|
|
|
|
|
|
const processStore = useProcessStore();
|
|
|
const drawingData = ref<any>([]);
|
|
|
+const visiblePdfs = ref<boolean[]>([]);
|
|
|
+const observer = ref<IntersectionObserver | null>(null);
|
|
|
+const lastVisibleIndex = ref<number>(-1);
|
|
|
|
|
|
const baseUrl = import.meta.env.VITE_APP_UPLOAD_URL;
|
|
|
|
|
|
onMounted(() => {
|
|
|
- drawingList({ materialCode: processStore.scanInfo.materialCode }).then(
|
|
|
- (res) => {
|
|
|
- drawingData.value = res.data;
|
|
|
- }
|
|
|
- );
|
|
|
+ drawingList({ materialCode: processStore.scanInfo.materialCode }).then((res) => {
|
|
|
+ drawingData.value = res.data;
|
|
|
+ visiblePdfs.value = new Array(res.data.length).fill(false);
|
|
|
+ initIntersectionObserver();
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ cleanupObserver();
|
|
|
});
|
|
|
+
|
|
|
+const initIntersectionObserver = () => {
|
|
|
+ cleanupObserver();
|
|
|
+
|
|
|
+ observer.value = new IntersectionObserver((entries) => {
|
|
|
+ entries.forEach(entry => {
|
|
|
+ const index = parseInt(entry.target.getAttribute('data-index') || '0', 10);
|
|
|
+
|
|
|
+ if (entry.isIntersecting) {
|
|
|
+ // 显示当前PDF
|
|
|
+ visiblePdfs.value[index] = true;
|
|
|
+ lastVisibleIndex.value = index;
|
|
|
+
|
|
|
+ // 可以在这里添加预加载相邻PDF的逻辑
|
|
|
+ preloadAdjacentPdfs(index);
|
|
|
+ } else {
|
|
|
+ // 当元素离开视口时,根据策略决定是否卸载
|
|
|
+ if (shouldUnloadPdf(index, lastVisibleIndex.value)) {
|
|
|
+ visiblePdfs.value[index] = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }, {
|
|
|
+ rootMargin: '200px 0px', // 提前200px加载
|
|
|
+ threshold: 0.01
|
|
|
+ });
|
|
|
+
|
|
|
+ // 使用nextTick确保DOM已更新
|
|
|
+ setTimeout(() => {
|
|
|
+ document.querySelectorAll('.suit-box').forEach((box) => {
|
|
|
+ observer.value?.observe(box);
|
|
|
+ });
|
|
|
+ }, 0);
|
|
|
+};
|
|
|
+
|
|
|
+const preloadAdjacentPdfs = (currentIndex: number) => {
|
|
|
+ // 预加载前后各1个PDF
|
|
|
+ const preloadIndices = [currentIndex - 1, currentIndex + 1];
|
|
|
+ preloadIndices.forEach(i => {
|
|
|
+ if (i >= 0 && i < visiblePdfs.value.length && !visiblePdfs.value[i]) {
|
|
|
+ visiblePdfs.value[i] = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const shouldUnloadPdf = (index: number, lastVisibleIndex: number) => {
|
|
|
+ // 只保留当前可见项和相邻项的PDF加载
|
|
|
+ return Math.abs(index - lastVisibleIndex) > 2;
|
|
|
+};
|
|
|
+
|
|
|
+const cleanupObserver = () => {
|
|
|
+ if (observer.value) {
|
|
|
+ observer.value.disconnect();
|
|
|
+ observer.value = null;
|
|
|
+ }
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.grid-container {
|
|
|
display: grid;
|
|
|
- /*行间距*/
|
|
|
grid-row-gap: 24px;
|
|
|
- /*列间距*/
|
|
|
grid-column-gap: 24px;
|
|
|
-
|
|
|
overflow-y: auto;
|
|
|
padding: 24px;
|
|
|
width: calc(100% - 48px);
|
|
@@ -50,7 +118,7 @@ onMounted(() => {
|
|
|
.suit-box {
|
|
|
height: 343px;
|
|
|
background-color: white;
|
|
|
- border-radius: 16px 16px 16px 16px;
|
|
|
+ border-radius: 16px;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: start;
|
|
@@ -60,6 +128,17 @@ onMounted(() => {
|
|
|
height: 263px;
|
|
|
width: 100%;
|
|
|
overflow: hidden;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+
|
|
|
+ .pdf-placeholder {
|
|
|
+ height: 100%;
|
|
|
+ width: 100%;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: #999;
|
|
|
}
|
|
|
|
|
|
.suit-title {
|
|
@@ -78,4 +157,4 @@ onMounted(() => {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|