Merge branch 'PingChuan' into shiy-login
# Conflicts: # app/components/reviews/ReviewTabs.tsx
This commit is contained in:
@@ -5,7 +5,8 @@
|
||||
import { useState, useEffect, useRef, ChangeEvent } from 'react';
|
||||
import { Document, Page, pdfjs } from 'react-pdf';
|
||||
import { DOCUMENT_URL } from '~/api/axios-client';
|
||||
import { CollaboraViewer } from '~/components/collabora/CollaboraViewer';
|
||||
import { CollaboraViewer, type CollaboraViewerHandle } from '~/components/collabora/CollaboraViewer';
|
||||
import { requestPageInfo, customGotoPage } from '~/components/collabora/lib';
|
||||
|
||||
// 导入react-pdf的CSS样式(文本层和注释层必需)
|
||||
import 'react-pdf/dist/esm/Page/TextLayer.css';
|
||||
@@ -89,10 +90,60 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
const [zoomLevel, setZoomLevel] = useState(100);
|
||||
// const [highlightsVisible, setHighlightsVisible] = useState(true);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const collaboraViewerRef = useRef<CollaboraViewerHandle>(null);
|
||||
const [numPages, setNumPages] = useState<number | null>(null);
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const [pageInputValue, setPageInputValue] = useState<string>('');
|
||||
|
||||
|
||||
// 获取文件类型
|
||||
const real_path = fileContent.path || fileContent.template_contract_path || '';
|
||||
const fileExtension = real_path.split('.').pop()?.toLowerCase();
|
||||
const isDocx = fileExtension === 'docx';
|
||||
const isPdf = fileExtension === 'pdf';
|
||||
|
||||
// DOCX 页数获取: 使用 requestPageInfo 方法
|
||||
useEffect(() => {
|
||||
if (!isDocx) return;
|
||||
|
||||
// console.log('[FilePreview] DOCX 文档加载,尝试获取页数');
|
||||
|
||||
let intervalCleared = false;
|
||||
|
||||
// 等待 CollaboraViewer 准备就绪
|
||||
const checkInterval = setInterval(() => {
|
||||
if (intervalCleared) return;
|
||||
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
console.log('[FilePreview] 等待 Collabora 就绪...');
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log('[FilePreview] Collabora 已就绪,尝试获取页数');
|
||||
clearInterval(checkInterval);
|
||||
intervalCleared = true;
|
||||
|
||||
const iframeWindow = collaboraViewerRef.current.getIframeWindow?.();
|
||||
if (!iframeWindow) {
|
||||
console.warn('[FilePreview] 无法获取 iframe window');
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 requestPageInfo 获取页数
|
||||
requestPageInfo(iframeWindow)
|
||||
.then((info) => {
|
||||
setNumPages(info.totalPages);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn('[FilePreview] 获取 DOCX 页数失败:', error.message);
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// 清理定时器
|
||||
return () => {
|
||||
clearInterval(checkInterval);
|
||||
};
|
||||
}, [isDocx]);
|
||||
|
||||
// 拖拽状态管理
|
||||
const [dragMode, setDragMode] = useState(false); // 是否处于拖拽模式
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
@@ -101,15 +152,35 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 放大文档
|
||||
const handleZoomIn = () => {
|
||||
if (zoomLevel < 200) {
|
||||
setZoomLevel(prevZoom => prevZoom + 10);
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.zoomIn();
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:修改 zoomLevel 状态
|
||||
if (zoomLevel < 200) {
|
||||
setZoomLevel(prevZoom => prevZoom + 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 缩小文档
|
||||
const handleZoomOut = () => {
|
||||
if (zoomLevel > 50) {
|
||||
setZoomLevel(prevZoom => prevZoom - 10);
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.zoomOut();
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:修改 zoomLevel 状态
|
||||
if (zoomLevel > 50) {
|
||||
setZoomLevel(prevZoom => prevZoom - 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -246,22 +317,47 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
};
|
||||
|
||||
// 处理页码跳转
|
||||
const handlePageJump = () => {
|
||||
if (!pageInputValue || !numPages) return;
|
||||
|
||||
const handlePageJump = async () => {
|
||||
if (!pageInputValue) return;
|
||||
|
||||
const targetPageNum = parseInt(pageInputValue, 10);
|
||||
|
||||
// 验证页码是否在有效范围内
|
||||
if (targetPageNum > 0 && targetPageNum <= numPages) {
|
||||
// 找到目标页面元素并滚动到该位置
|
||||
const pageElement = document.getElementById(`page-${targetPageNum}`);
|
||||
if (pageElement) {
|
||||
pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用自定义页面跳转
|
||||
const iframeWindow = collaboraViewerRef.current?.getIframeWindow?.();
|
||||
if (!iframeWindow) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetPageNum > 0) {
|
||||
try {
|
||||
await customGotoPage(iframeWindow, targetPageNum);
|
||||
// 跳转成功,清空输入框
|
||||
setPageInputValue('');
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : '未知错误';
|
||||
toastService.error(`跳转失败: ${errorMessage}`);
|
||||
}
|
||||
} else {
|
||||
toastService.warning('请输入有效页码');
|
||||
setPageInputValue('');
|
||||
}
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:验证页码并滚动到目标页面
|
||||
if (!numPages) return;
|
||||
|
||||
if (targetPageNum > 0 && targetPageNum <= numPages) {
|
||||
// 找到目标页面元素并滚动到该位置
|
||||
const pageElement = document.getElementById(`page-${targetPageNum}`);
|
||||
if (pageElement) {
|
||||
pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
} else {
|
||||
// 页码超出范围,显示错误信息或重置输入
|
||||
toastService.warning(`请输入有效页码 (1-${numPages})`);
|
||||
setPageInputValue('');
|
||||
}
|
||||
} else {
|
||||
// 页码超出范围,显示错误信息或重置输入
|
||||
toastService.warning(`请输入有效页码 (1-${numPages})`);
|
||||
setPageInputValue('');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -289,8 +385,18 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 滚动到顶部
|
||||
const handleScrollToTop = () => {
|
||||
if (contentRef.current) {
|
||||
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.scrollToTop();
|
||||
} else {
|
||||
// PDF 文件:滚动容器到顶部
|
||||
if (contentRef.current) {
|
||||
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -389,8 +495,6 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 渲染文档内容
|
||||
const renderDocumentContent = () => {
|
||||
const real_path = fileContent.path || fileContent.template_contract_path || '';
|
||||
|
||||
// 如果路径无效,显示错误信息
|
||||
if (!real_path) {
|
||||
if(!fileContent.template_contract_path){
|
||||
@@ -408,9 +512,7 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
}
|
||||
|
||||
// console.log('real_path',real_path);
|
||||
// 获取文件扩展名
|
||||
const fileExtension = real_path.split('.').pop()?.toLowerCase();
|
||||
|
||||
|
||||
// PDF内容渲染
|
||||
const renderPdfContent = () => (
|
||||
<div
|
||||
@@ -474,8 +576,9 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
// DOCX文件使用Collabora Online预览
|
||||
return (
|
||||
<CollaboraViewer
|
||||
ref={collaboraViewerRef}
|
||||
fileId={real_path}
|
||||
mode="view"
|
||||
mode="edit"
|
||||
userId={userInfo?.sub || 'guest'}
|
||||
userName={userInfo?.nick_name || '访客'}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user