进度条优化
This commit is contained in:
@@ -66,7 +66,7 @@ interface FileContent {
|
||||
|
||||
interface FilePreviewProps {
|
||||
fileContent: FileContent;
|
||||
reviewPoints: ReviewPoint[];
|
||||
reviewPoints?: ReviewPoint[]; // 设为可选
|
||||
activeReviewPointResultId: string | null;
|
||||
targetPage?: number; // 新增目标页码参数
|
||||
}
|
||||
@@ -79,6 +79,12 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const [pageInputValue, setPageInputValue] = useState<string>('');
|
||||
|
||||
// 拖拽状态管理
|
||||
const [dragMode, setDragMode] = useState(false); // 是否处于拖拽模式
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [dragCursor, setDragCursor] = useState('default');
|
||||
const lastMousePosRef = useRef({ x: 0, y: 0 });
|
||||
|
||||
// 放大文档
|
||||
const handleZoomIn = () => {
|
||||
if (zoomLevel < 200) {
|
||||
@@ -93,27 +99,75 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
}
|
||||
};
|
||||
|
||||
// 切换高亮显示
|
||||
// const toggleHighlights = () => {
|
||||
// setHighlightsVisible(!highlightsVisible);
|
||||
// };
|
||||
// 切换拖拽模式
|
||||
const toggleDragMode = () => {
|
||||
setDragMode(prev => !prev);
|
||||
setDragCursor(prev => prev === 'default' ? 'grab' : 'default');
|
||||
setIsDragging(false);
|
||||
};
|
||||
|
||||
// 当选中的评查点变化时,滚动到对应位置
|
||||
// useEffect(() => {
|
||||
// if (activeReviewPointId && contentRef.current) {
|
||||
// const highlightElement = contentRef.current.querySelector(`[data-review-id="${activeReviewPointId}"]`);
|
||||
// if (highlightElement) {
|
||||
// highlightElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
// // highlightElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
|
||||
// // 添加临时突出显示效果
|
||||
// highlightElement.classList.add('highlight-focus');
|
||||
// setTimeout(() => {
|
||||
// highlightElement.classList.remove('highlight-focus');
|
||||
// }, 1500);
|
||||
// }
|
||||
// }
|
||||
// }, [activeReviewPointId]);
|
||||
// 处理拖拽开始
|
||||
const handleMouseDown = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (!dragMode || e.button !== 0) return; // 只在拖拽模式下响应左键点击
|
||||
|
||||
// 防止选中文本
|
||||
e.preventDefault();
|
||||
|
||||
// 设置拖拽状态
|
||||
setIsDragging(true);
|
||||
setDragCursor('grabbing');
|
||||
|
||||
// 记录鼠标初始位置
|
||||
lastMousePosRef.current = {
|
||||
x: e.clientX,
|
||||
y: e.clientY
|
||||
};
|
||||
};
|
||||
|
||||
// 处理拖拽过程
|
||||
const handleMouseMove = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
if (!dragMode || !isDragging || !contentRef.current) return;
|
||||
|
||||
// 计算鼠标移动距离
|
||||
const dx = e.clientX - lastMousePosRef.current.x;
|
||||
const dy = e.clientY - lastMousePosRef.current.y;
|
||||
|
||||
// 更新容器滚动位置
|
||||
contentRef.current.scrollLeft -= dx;
|
||||
contentRef.current.scrollTop -= dy;
|
||||
|
||||
// 更新鼠标位置记录
|
||||
lastMousePosRef.current = {
|
||||
x: e.clientX,
|
||||
y: e.clientY
|
||||
};
|
||||
};
|
||||
|
||||
// 处理拖拽结束
|
||||
const handleMouseUp = () => {
|
||||
if (!dragMode) return;
|
||||
|
||||
setIsDragging(false);
|
||||
setDragCursor('grab');
|
||||
};
|
||||
|
||||
// 监听鼠标离开窗口事件
|
||||
useEffect(() => {
|
||||
const handleMouseLeave = () => {
|
||||
if (dragMode && isDragging) {
|
||||
setIsDragging(false);
|
||||
setDragCursor('grab');
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mouseleave', handleMouseLeave);
|
||||
document.addEventListener('mouseup', handleMouseUp as EventListener);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mouseleave', handleMouseLeave);
|
||||
document.removeEventListener('mouseup', handleMouseUp as EventListener);
|
||||
};
|
||||
}, [isDragging, dragMode]);
|
||||
|
||||
// 处理页面跳转
|
||||
const prevTargetPageRef = useRef<number | undefined>(undefined);
|
||||
@@ -130,6 +184,7 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("访问ocrResult时出错:", error);
|
||||
toastService.error("访问ocrResult时出错:" + (error instanceof Error ? error.message : '未知错误'));
|
||||
}
|
||||
|
||||
const pageElement = document.getElementById(`page-${newTargetPage}`);
|
||||
@@ -230,11 +285,6 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
|
||||
// 遍历每一页,生成对应的页面组件
|
||||
for (let i = 1; i <= numPages; i++) {
|
||||
// 查找该页面上的评查点,基于position.section匹配页面ID
|
||||
// const pageReviewPoints = reviewPoints.filter(point =>
|
||||
// point.position && point.position.section === `page-${i}`
|
||||
// );
|
||||
|
||||
// 计算当前缩放级别下的页面容器样式
|
||||
const zoomFactor = zoomLevel / 100;
|
||||
const pageContainerStyle = {
|
||||
@@ -250,12 +300,13 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
|
||||
{/* 页面容器,应用缩放变换,设置相对定位用于放置评查点高亮 */}
|
||||
<div
|
||||
className="page-wrapper flex justify-center"
|
||||
className="page-wrapper"
|
||||
style={{
|
||||
transform: `scale(${zoomFactor})`, // 根据zoomLevel应用缩放
|
||||
transformOrigin: 'top center', // 缩放原点设置为顶部中心
|
||||
position: 'relative', // 相对定位,作为评查点高亮的定位参考
|
||||
maxWidth: '100%', // 限制最大宽度
|
||||
display: 'inline-block', // 内联块级元素,宽度由内容决定
|
||||
margin: '0 auto', // 水平居中
|
||||
}}
|
||||
>
|
||||
{/* 渲染PDF页面组件 */}
|
||||
@@ -305,7 +356,14 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
// 渲染文档内容
|
||||
const renderDocumentContent = () => {
|
||||
return (
|
||||
<div style={styles.pdfContainer}>
|
||||
<div
|
||||
style={{
|
||||
...styles.pdfContainer,
|
||||
// 当缩放大于100%时设置最小宽度,确保出现横向滚动条
|
||||
minWidth: zoomLevel > 100 ? `${zoomLevel}%` : '100%',
|
||||
overflow: 'visible'
|
||||
}}
|
||||
>
|
||||
<Document
|
||||
file={'http://172.18.0.100:9000/docauditai/'+fileContent.path}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
@@ -313,7 +371,7 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
console.error("PDF加载错误:", error);
|
||||
setLoadError("PDF文档加载失败:" + (error.message || "未知错误"));
|
||||
}}
|
||||
className="flex flex-col items-center w-full"
|
||||
className="w-full"
|
||||
error={<div className="text-red-500">PDF文档加载失败,请检查链接或网络连接。</div>}
|
||||
noData={<div>无数据</div>}
|
||||
loading={<div className="text-center py-10">PDF加载中...</div>}
|
||||
@@ -336,7 +394,7 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
className="ant-btn ant-btn-sm ant-btn-default py-0 px-1 text-xs h-5 leading-5 "
|
||||
onClick={handleScrollToTop}
|
||||
>
|
||||
<i className="ri-arrow-up-double-line "></i>
|
||||
<i className="ri-arrow-up-double-line"></i>
|
||||
<span className="ml-1">返回顶部</span>
|
||||
</button>
|
||||
<button
|
||||
@@ -378,20 +436,70 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointResult
|
||||
<i className="ri-mark-pen-line"></i> {highlightsVisible ? '隐藏问题' : '显示问题'}
|
||||
</button> */}
|
||||
<span className="ml-2 text-xs text-gray-500 inline-block">{"比例:"+zoomLevel+"%"}</span>
|
||||
<button
|
||||
className={`ant-btn ant-btn-sm ant-btn-default py-0 px-1 text-xs h-5 leading-5 ml-2 ${dragMode ? 'active bg-green-300' : ''}`}
|
||||
title="切换拖拽模式"
|
||||
aria-pressed={dragMode}
|
||||
onClick={toggleDragMode}
|
||||
>
|
||||
<i className="ri-drag-move-line"></i>
|
||||
<span className="ml-1">拖拽模式{dragMode ? '(已激活)' : ''}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="file-preview-content relative overflow-y-auto"
|
||||
className="file-preview-content"
|
||||
ref={contentRef}
|
||||
style={{ maxHeight: 'calc(100vh - 150px)' }}
|
||||
style={{
|
||||
maxHeight: 'calc(100vh - 150px)',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'auto',
|
||||
cursor: dragCursor,
|
||||
userSelect: dragMode ? 'none' : 'auto', // 拖拽模式下防止文本被选中
|
||||
}}
|
||||
>
|
||||
{loadError ? (
|
||||
<div className="text-red-500 p-4">
|
||||
<p>{loadError}</p>
|
||||
</div>
|
||||
) : (
|
||||
renderDocumentContent()
|
||||
)}
|
||||
<button
|
||||
className="pdf-interactive-container"
|
||||
aria-label="PDF文档查看区域"
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseUp={handleMouseUp}
|
||||
onKeyDown={(e) => {
|
||||
// 添加键盘导航支持
|
||||
const scrollAmount = 50;
|
||||
if (e.key === 'ArrowUp') {
|
||||
if (contentRef.current) contentRef.current.scrollTop -= scrollAmount;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowDown') {
|
||||
if (contentRef.current) contentRef.current.scrollTop += scrollAmount;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowLeft') {
|
||||
if (contentRef.current) contentRef.current.scrollLeft -= scrollAmount;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
if (contentRef.current) contentRef.current.scrollLeft += scrollAmount;
|
||||
e.preventDefault();
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
position: 'relative',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
display: 'block',
|
||||
border: 'none',
|
||||
background: 'transparent',
|
||||
textAlign: 'center',
|
||||
padding: 0
|
||||
}}
|
||||
>
|
||||
{loadError ? (
|
||||
<div className="text-red-500 p-4">
|
||||
<p>{loadError}</p>
|
||||
</div>
|
||||
) : (
|
||||
renderDocumentContent()
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user