diff --git a/src/views/dialogue/components/DialogueSession.vue b/src/views/dialogue/components/DialogueSession.vue index f42c1c27a90c69a374a9237714104ab8e7349645..8907f9333035f83d44328ba45e64640813abd066 100644 --- a/src/views/dialogue/components/DialogueSession.vue +++ b/src/views/dialogue/components/DialogueSession.vue @@ -254,8 +254,23 @@ const openDocumentPreview = (fileList: Array, markId: string) => { }); previewFileList.value = formattedList; - // 默认选中第一个文件 - selectedPreviewFile.value = formattedList[0]; + + // 🔑 修复:根据点击的标识索引选择对应的文件 + // 从 DOM 元素中获取 data-mark-index 属性 + const clickedElement = document.getElementById(markId); + let targetIndex = 0; // 默认第一个 + + if (clickedElement) { + const markIndex = clickedElement.getAttribute('data-mark-index'); + if (markIndex !== null) { + const index = parseInt(markIndex, 10); + if (!isNaN(index) && index >= 0 && index < formattedList.length) { + targetIndex = index; + } + } + } + + selectedPreviewFile.value = formattedList[targetIndex]; } else { previewFileList.value = []; selectedPreviewFile.value = null; diff --git a/src/views/dialogue/components/DocumentPreview.vue b/src/views/dialogue/components/DocumentPreview.vue index c67b3c645fdf32bf5a96759a82258ede4ca9011a..4d4d0ba306f93d2c8eaf52d11fd3155765cd21f0 100644 --- a/src/views/dialogue/components/DocumentPreview.vue +++ b/src/views/dialogue/components/DocumentPreview.vue @@ -113,6 +113,7 @@ const tableData = ref>>([]); const currentBlobUrl = ref(''); // 追踪当前的Blob URL以便清理 const pdfKey = ref(0); // 用于强制PDF重新渲染 const containerWidth = ref(0); // 容器宽度 +let loadingSequence = 0; // 用于处理异步加载的竞态条件 // PDF和图片的控制状态 const currentPage = ref(1); // PDF当前页码 @@ -144,6 +145,9 @@ const loadPreview = async () => { return; } + // 🔑 修复:增加序列号处理异步竞态条件 + const currentSequence = ++loadingSequence; + // 清理之前的Blob URL if (currentBlobUrl.value) { URL.revokeObjectURL(currentBlobUrl.value); @@ -162,6 +166,7 @@ const loadPreview = async () => { scale.value = 1; showSidebar.value = false; loadedPages.value = 10; // 重置为初始加载页数 + pdfKey.value++; // 强制重新渲染PDF组件 try { const fileType = props.file.documentType.toLowerCase(); @@ -169,69 +174,100 @@ const loadPreview = async () => { // 使用统一的API接口下载文档 const blob = await downloadDocument(props.file.documentId); + // 🔑 检查是否是最新的加载请求 + if (currentSequence !== loadingSequence) { + // 如果不是最新的请求,放弃处理 + console.log('🔑 检测到文件切换,放弃旧的加载请求'); + return; + } + // 图片类型 - 转换为Blob URL if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileType)) { const blobUrl = URL.createObjectURL(blob); - currentBlobUrl.value = blobUrl; - previewContent.value = blobUrl; + if (currentSequence === loadingSequence) { + currentBlobUrl.value = blobUrl; + previewContent.value = blobUrl; + } return; } // PDF类型 - 转换为Blob URL if (fileType === 'pdf') { const blobUrl = URL.createObjectURL(blob); - currentBlobUrl.value = blobUrl; - previewContent.value = blobUrl; + if (currentSequence === loadingSequence) { + currentBlobUrl.value = blobUrl; + previewContent.value = blobUrl; + } return; } // 文本类型 - 直接读取为文本 if (['txt', 'json', 'yaml', 'csv', 'html'].includes(fileType)) { const text = await blob.text(); - previewContent.value = text; + if (currentSequence === loadingSequence) { + previewContent.value = text; + } return; } // Markdown类型 if (fileType === 'md' || fileType === 'md.zip') { const text = await blob.text(); - htmlContent.value = marked.parse(text) as string; + if (currentSequence === loadingSequence) { + htmlContent.value = marked.parse(text) as string; + } return; } // DOCX类型 if (fileType === 'docx' || fileType === 'doc') { const arrayBuffer = await blob.arrayBuffer(); + if (currentSequence !== loadingSequence) return; + const result = await mammoth.convertToHtml({ arrayBuffer }); - htmlContent.value = result.value; + if (currentSequence === loadingSequence) { + htmlContent.value = result.value; + } return; } // Excel类型 if (fileType === 'xlsx' || fileType === 'csv') { const arrayBuffer = await blob.arrayBuffer(); + if (currentSequence !== loadingSequence) return; + const workbook = XLSX.read(arrayBuffer, { type: 'array' }); const firstSheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[firstSheetName]; const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 }) as Array>; - tableData.value = data; + if (currentSequence === loadingSequence) { + tableData.value = data; + } return; } // PPTX类型 - 暂不支持在线预览 if (fileType === 'pptx') { - previewError.value = `PPTX 格式暂不支持在线预览,请下载后查看`; + if (currentSequence === loadingSequence) { + previewError.value = `PPTX 格式暂不支持在线预览,请下载后查看`; + } return; } // 其他类型暂不支持在线预览 - previewContent.value = ''; - previewError.value = `暂不支持 ${fileType.toUpperCase()} 格式的在线预览,请下载后查看`; + if (currentSequence === loadingSequence) { + previewContent.value = ''; + previewError.value = `暂不支持 ${fileType.toUpperCase()} 格式的在线预览,请下载后查看`; + } } catch (error) { console.error('加载预览失败:', error); - previewError.value = `加载预览失败: ${error instanceof Error ? error.message : '未知错误'}`; + if (currentSequence === loadingSequence) { + previewError.value = `加载预览失败: ${error instanceof Error ? error.message : '未知错误'}`; + } } finally { - loading.value = false; + if (currentSequence === loadingSequence) { + loading.value = false; + } } };