131 lines
3.5 KiB
JavaScript
131 lines
3.5 KiB
JavaScript
import { useFullscreen } from "ahooks";
|
||
import { Button, message, Modal, Spin } from "antd";
|
||
import { useRef, useState } from "react";
|
||
import { Document, Page, pdfjs } from "react-pdf";
|
||
import useDownloadFile from "../../hooks/useDownloadFile";
|
||
import { getFileUrl } from "../../utils";
|
||
import "react-pdf/dist/Page/AnnotationLayer.css";
|
||
import "react-pdf/dist/Page/TextLayer.css";
|
||
import "./index.less";
|
||
|
||
/**
|
||
* PDF查看组件
|
||
*/
|
||
function Pdf(props) {
|
||
const {
|
||
visible = false,
|
||
onCancel,
|
||
file,
|
||
name,
|
||
inline = false,
|
||
style = {},
|
||
} = props;
|
||
|
||
const fileUrl = getFileUrl();
|
||
const [numPages, setNumPages] = useState(0);
|
||
const [pdfWidth, setPdfWidth] = useState(600);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
const fullscreenRef = useRef(null);
|
||
|
||
const [isFullscreen, { enterFullscreen, exitFullscreen }] = useFullscreen(fullscreenRef);
|
||
const { downloadFile } = useDownloadFile();
|
||
|
||
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
||
|
||
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 && (
|
||
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "80vh" }}>
|
||
<Spin size="large" />
|
||
</div>
|
||
)}
|
||
<div style={{ height: isFullscreen ? "calc(100vh - 40px - 24px - 8px - 32px - 12px)" : "72vh", overflowY: "auto", padding: "24px", ...style }}>
|
||
<Document
|
||
file={!file.includes(fileUrl) ? fileUrl + file : file}
|
||
onLoadSuccess={onDocumentLoadSuccess}
|
||
onLoadError={onDocumentLoadError}
|
||
>
|
||
{
|
||
Array.from({ length: numPages }).map((_, index) => (
|
||
<Page key={`page_${index + 1}`} pageNumber={index + 1} onLoadSuccess={onPageLoadSuccess} />
|
||
))
|
||
}
|
||
</Document>
|
||
</div>
|
||
</>
|
||
);
|
||
|
||
// 如果是内联模式,直接返回PDF内容
|
||
if (inline) {
|
||
return renderPdfContent();
|
||
}
|
||
|
||
const onDownloadFile = () => {
|
||
isFullscreen && exitFullscreen();
|
||
downloadFile({
|
||
url: file,
|
||
name,
|
||
});
|
||
};
|
||
|
||
// 默认弹窗模式
|
||
return (
|
||
<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>,
|
||
<Button
|
||
key="fullScreen"
|
||
onClick={() => {
|
||
isFullscreen ? exitFullscreen() : enterFullscreen();
|
||
}}
|
||
>
|
||
{isFullscreen ? "退出全屏" : "全屏"}
|
||
</Button>,
|
||
<Button key="download" type="primary" onClick={onDownloadFile}>下载</Button>,
|
||
]}
|
||
>
|
||
{renderPdfContent()}
|
||
</Modal>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default Pdf;
|