进度条优化

This commit is contained in:
2025-04-25 14:12:36 +08:00
parent 0eaaa5b041
commit b9b5be1d47
9 changed files with 377 additions and 270 deletions
-7
View File
@@ -586,25 +586,18 @@ export default function DocumentsIndex() {
// 检查audit_status是否为0,如果是则更新为2
if (auditStatus === 0 || auditStatus === null) {
try {
// 显示加载状态
loadingBarService.show();
const response = await updateDocumentAuditStatus(fileId.toString(), 2);
if (response.error) {
console.error('更新文件审核状态失败:', response.error);
toastService.error('更新文件审核状态失败:' + (response.error || '未知错误'));
loadingBarService.hide();
return;
}
} catch (error) {
console.error('更新文件审核状态时出错:', error);
toastService.error('更新文件审核状态时出错:' + (error instanceof Error ? error.message : '未知错误'));
loadingBarService.hide();
return;
}
} else {
// 显示加载状态
loadingBarService.show();
}
// 导航到评查详情页
+192
View File
@@ -0,0 +1,192 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { createPortal } from 'react-dom';
import { Spin, Tooltip, Input } from 'antd';
import {
LeftOutlined,
RightOutlined,
PlusCircleOutlined,
MinusCircleOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
CloseCircleOutlined,
ExclamationCircleOutlined,
RotateLeftOutlined,
RotateRightOutlined,
UnorderedListOutlined,
} from '@ant-design/icons';
import './index.less';
import { Document, Page, pdfjs } from 'react-pdf';
import pdfjsWorker from 'react-pdf/dist/esm/pdf.worker.entry';
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
const PDFView = ({
file,
parentDom,
onClose,
}: {
file?: string | null;
parentDom?: HTMLDivElement | null;
onClose?: () => void;
}) => {
const defaultWidth = 600;
const pageDiv = useRef<HTMLDivElement>(null);
const [numPages, setNumPages] = useState<number>(0);
const [pageNumber, setPageNumber] = useState<number>(1);
const [pageWidth, setPageWidth] = useState<number>(defaultWidth);
const [fullscreen, setFullscreen] = useState<boolean>(false);
const [rotation, setRotation] = useState<number>(0);
const [showThumbnails, setShowThumbnails] = useState<boolean>(false);
const [visiblePages, setVisiblePages] = useState<number[]>([1]); // 控制可见页面
const parent = parentDom || document.body;
// 加载 PDF 元信息,不渲染全部页面
const onDocumentLoadSuccess = useCallback(({ numPages }: { numPages: number }) => {
setNumPages(numPages);
}, []);
const lastPage = () => pageNumber > 1 && setPageNumber(pageNumber - 1);
const nextPage = () => pageNumber < numPages && setPageNumber(pageNumber + 1);
const onPageNumberChange = (e: { target: { value: string } }) => {
let value = Math.max(1, Math.min(numPages, Number(e.target.value) || 1));
setPageNumber(value);
setVisiblePages([value]); // 只加载当前页
};
const pageZoomIn = () => setPageWidth(pageWidth * 1.2);
const pageZoomOut = () => pageWidth > defaultWidth && setPageWidth(pageWidth * 0.8);
const pageFullscreen = () => {
setPageWidth(fullscreen ? defaultWidth : parent.offsetWidth - 50);
setFullscreen(!fullscreen);
};
const rotateLeft = () => setRotation((prev) => (prev - 90) % 360);
const rotateRight = () => setRotation((prev) => (prev + 90) % 360);
const toggleThumbnails = () => setShowThumbnails(!showThumbnails);
// 动态更新可见页面
useEffect(() => {
if (!showThumbnails) {
setVisiblePages([pageNumber]);
} else {
// 缩略图模式下限制加载数量,避免卡顿
const start = Math.max(1, pageNumber - 2);
const end = Math.min(numPages, pageNumber + 2);
setVisiblePages(Array.from({ length: end - start + 1 }, (_, i) => start + i));
}
}, [pageNumber, showThumbnails, numPages]);
useEffect(() => setPageNumber(1), [file]);
useEffect(() => {
if( pageDiv.current){
(pageDiv.current.scrollTop = 0)
}
}, [pageNumber]);
const renderContent=()=>(<div className='view'>
<div className='viewContent' >
<div className='pageMain' ref={pageDiv}>
<div className='pageContainer'>
<Document
file={file}
onLoadSuccess={onDocumentLoadSuccess}
error={
<div style={{ textAlign: 'center', width: defaultWidth + 'px' }}>
<ExclamationCircleOutlined style={{ fontSize: '150px', color: '#fe725c', margin: '100px' }} />
</div>
}
loading={<div style={{ textAlign: 'center', width: defaultWidth + 'px' }}><Spin size="large" style={{ margin: '200px' }} /></div>}
>
{showThumbnails ? (
<div className='thumbnailContainer'>
{Array.from({ length: numPages }, (_, i) => i + 1).map((page) => (
<div
key={page}
className='thumbnail'
onClick={() => {
setPageNumber(page);
setShowThumbnails(false);
}}
>
{visiblePages.includes(page) ? (
<Page
pageNumber={page}
width={150}
rotate={rotation}
loading={<Spin />}
renderTextLayer={false} // 禁用文本层,提升性能
renderAnnotationLayer={false} // 禁用注释层
/>
) : (
<div className='thumbnailPlaceholder'> {page} </div>
)}
<span> {page} </span>
</div>
))}
</div>
) : (
<Page
pageNumber={pageNumber}
width={pageWidth}
rotate={rotation}
loading={<Spin size="large" />}
renderTextLayer={false} // 禁用文本层
renderAnnotationLayer={false} // 禁用注释层
error={() => setPageNumber(1)}
/>
)}
</Document>
</div>
</div>
<div className='pageBar'>
<div className='pageTool'>
<Tooltip title={pageNumber === 1 ? '已是第一页' : '上一页'}>
<LeftOutlined onClick={lastPage} />
</Tooltip>
<Input
value={pageNumber}
onChange={onPageNumberChange}
onPressEnter={onPageNumberChange as any}
type="number"
/>{' '}
/ {numPages}
<Tooltip title={pageNumber === numPages ? '已是最后一页' : '下一页'}>
<RightOutlined onClick={nextPage} />
</Tooltip>
<Tooltip title="放大">
<PlusCircleOutlined onClick={pageZoomIn} />
</Tooltip>
<Tooltip title="缩小">
<MinusCircleOutlined onClick={pageZoomOut} />
</Tooltip>
<Tooltip title="向左旋转">
<RotateLeftOutlined onClick={rotateLeft} />
</Tooltip>
<Tooltip title="向右旋转">
<RotateRightOutlined onClick={rotateRight} />
</Tooltip>
<Tooltip title={showThumbnails ? '关闭缩略图' : '显示缩略图'}>
<UnorderedListOutlined onClick={toggleThumbnails} />
</Tooltip>
<Tooltip title={fullscreen ? '恢复默认' : '适合窗口'}>
{fullscreen ? <FullscreenExitOutlined onClick={pageFullscreen} /> : <FullscreenOutlined onClick={pageFullscreen} />}
</Tooltip>
{onClose && (
<Tooltip title="关闭">
<CloseCircleOutlined onClick={onClose} />
</Tooltip>
)}
</div>
</div>
</div>
</div>)
if(parentDom){
return renderContent()
}
return createPortal(
renderContent(),
parent,)
};
export default PDFView;
+2 -2
View File
@@ -45,8 +45,7 @@ import {
// 从ReviewPointsList组件中导入ReviewPoint类型
import { type ReviewPoint } from '~/components/reviews';
import { messageService } from "~/components/ui/MessageModal";
import { Button } from "~/components/ui/Button";
import { loadingBarService } from "~/components/ui/LoadingBar";
/**
* 文件信息组件
@@ -248,6 +247,7 @@ export default function ReviewDetails() {
// loader 数据加载出错
useEffect(()=>{
loadingBarService.hide();
if(Object.keys(loaderData).find(key => key === 'result') && !loaderData.result){
messageService.show({
title: '错误',