zy-react-library/components/Pdf/index.js

131 lines
3.5 KiB
JavaScript
Raw Normal View History

2025-12-22 14:47:41 +08:00
import { useFullscreen } from "ahooks";
import { Button, message, Modal, Spin } from "antd";
import { useRef, useState } from "react";
2025-10-22 17:54:38 +08:00
import { Document, Page, pdfjs } from "react-pdf";
2025-11-08 15:52:06 +08:00
import useDownloadFile from "../../hooks/useDownloadFile";
2025-12-22 14:47:41 +08:00
import { getFileUrl } from "../../utils";
import "react-pdf/dist/Page/AnnotationLayer.css";
import "react-pdf/dist/Page/TextLayer.css";
import "./index.less";
2025-10-22 17:54:38 +08:00
/**
* PDF查看组件
*/
2025-10-22 17:54:38 +08:00
function Pdf(props) {
const {
visible = false,
onCancel,
file,
2025-11-08 15:52:06 +08:00
name,
2025-10-22 17:54:38 +08:00
inline = false,
style = {},
} = props;
const fileUrl = getFileUrl();
const [numPages, setNumPages] = useState(0);
const [pdfWidth, setPdfWidth] = useState(600);
const [loading, setLoading] = useState(true);
2025-12-22 14:47:41 +08:00
const fullscreenRef = useRef(null);
const [isFullscreen, { enterFullscreen, exitFullscreen }] = useFullscreen(fullscreenRef);
const { downloadFile } = useDownloadFile();
2025-12-17 16:56:26 +08:00
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
2025-10-22 17:54:38 +08:00
const onDocumentLoadSuccess = ({ numPages }) => {
setNumPages(numPages);
setLoading(false);
};
const onDocumentLoadError = () => {
setLoading(false);
message.error("加载 PDF 文件失败");
if (onCancel)
onCancel();
};
const onPageLoadSuccess = ({ width }) => {
setPdfWidth(width);
};
// 内联模式的PDF内容
const renderPdfContent = () => (
<>
{loading && (
2025-12-22 14:56:49 +08:00
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "72vh" }}>
2025-10-22 17:54:38 +08:00
<Spin size="large" />
</div>
)}
2025-12-22 14:47:41 +08:00
<div style={{ height: isFullscreen ? "calc(100vh - 40px - 24px - 8px - 32px - 12px)" : "72vh", overflowY: "auto", padding: "24px", ...style }}>
2025-10-22 17:54:38 +08:00
<Document
file={!file.includes(fileUrl) ? fileUrl + file : file}
2025-10-22 17:54:38 +08:00
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={onDocumentLoadError}
>
{
2025-12-22 14:47:41 +08:00
Array.from({ length: numPages }).map((_, index) => (
2025-10-22 17:54:38 +08:00
<Page key={`page_${index + 1}`} pageNumber={index + 1} onLoadSuccess={onPageLoadSuccess} />
))
}
</Document>
</div>
</>
);
// 如果是内联模式直接返回PDF内容
if (inline) {
return renderPdfContent();
}
2025-11-08 15:52:06 +08:00
const onDownloadFile = () => {
2025-12-22 14:47:41 +08:00
isFullscreen && exitFullscreen();
downloadFile({
url: file,
name,
2025-11-08 15:52:06 +08:00
});
};
2025-10-22 17:54:38 +08:00
// 默认弹窗模式
return (
2025-12-22 14:47:41 +08:00
<div ref={fullscreenRef}>
<Modal
style={{ top: isFullscreen ? 0 : 100, maxWidth: isFullscreen ? "100vw" : "calc(100vw - 32px)", paddingBottom: isFullscreen ? 0 : 24 }}
open={visible}
maskClosable={false}
width={isFullscreen ? "100vw" : pdfWidth + 100}
title="PDF预览"
onCancel={() => {
isFullscreen && exitFullscreen();
onCancel();
}}
getContainer={false}
footer={[
<Button
key="cancel"
onClick={() => {
isFullscreen && exitFullscreen();
onCancel();
}}
>
关闭
</Button>,
2025-12-22 14:56:49 +08:00
!loading && <Button
2025-12-22 14:47:41 +08:00
key="fullScreen"
onClick={() => {
isFullscreen ? exitFullscreen() : enterFullscreen();
}}
>
{isFullscreen ? "退出全屏" : "全屏"}
</Button>,
<Button key="download" type="primary" onClick={onDownloadFile}>下载</Button>,
]}
>
{renderPdfContent()}
</Modal>
</div>
2025-10-22 17:54:38 +08:00
);
}
export default Pdf;