| 
									
										
										
										
											2025-10-22 17:54:38 +08:00
										 |  |  |  | import { Button, message, Modal, Spin } from "antd"; | 
					
						
							|  |  |  |  | import { useState } from "react"; | 
					
						
							|  |  |  |  | import { Document, Page, pdfjs } from "react-pdf"; | 
					
						
							|  |  |  |  | import { getFileUrl } from "../../utils/index"; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-28 15:16:58 +08:00
										 |  |  |  | /** | 
					
						
							|  |  |  |  |  * PDF查看组件 | 
					
						
							|  |  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2025-10-22 17:54:38 +08:00
										 |  |  |  | function Pdf(props) { | 
					
						
							|  |  |  |  |   const { | 
					
						
							|  |  |  |  |     visible = false, | 
					
						
							|  |  |  |  |     onCancel, | 
					
						
							|  |  |  |  |     file, | 
					
						
							|  |  |  |  |     inline = false, | 
					
						
							|  |  |  |  |     style = {}, | 
					
						
							|  |  |  |  |   } = props; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   const fileUrl = getFileUrl(); | 
					
						
							|  |  |  |  |   const [numPages, setNumPages] = useState(0); | 
					
						
							|  |  |  |  |   const [pdfWidth, setPdfWidth] = useState(600); | 
					
						
							|  |  |  |  |   const [loading, setLoading] = useState(true); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   pdfjs.GlobalWorkerOptions.workerSrc = new URL( | 
					
						
							|  |  |  |  |     "pdfjs-dist/build/pdf.worker.min.mjs", | 
					
						
							|  |  |  |  |     import.meta.url, | 
					
						
							|  |  |  |  |   ).toString(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   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: "88vh", overflowY: "auto", padding: "24px", ...style }}> | 
					
						
							|  |  |  |  |         <Document | 
					
						
							|  |  |  |  |           file={fileUrl + file} | 
					
						
							|  |  |  |  |           onLoadSuccess={onDocumentLoadSuccess} | 
					
						
							|  |  |  |  |           onLoadError={onDocumentLoadError} | 
					
						
							|  |  |  |  |         > | 
					
						
							|  |  |  |  |           { | 
					
						
							|  |  |  |  |             Array.from({ length: numPages }).map((el, index) => ( | 
					
						
							|  |  |  |  |               <Page key={`page_${index + 1}`} pageNumber={index + 1} onLoadSuccess={onPageLoadSuccess} /> | 
					
						
							|  |  |  |  |             )) | 
					
						
							|  |  |  |  |           } | 
					
						
							|  |  |  |  |         </Document> | 
					
						
							|  |  |  |  |       </div> | 
					
						
							|  |  |  |  |     </> | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 如果是内联模式,直接返回PDF内容
 | 
					
						
							|  |  |  |  |   if (inline) { | 
					
						
							|  |  |  |  |     return renderPdfContent(); | 
					
						
							|  |  |  |  |   } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   // 默认弹窗模式
 | 
					
						
							|  |  |  |  |   return ( | 
					
						
							|  |  |  |  |     <Modal | 
					
						
							|  |  |  |  |       open={visible} | 
					
						
							|  |  |  |  |       width={pdfWidth + 100} | 
					
						
							|  |  |  |  |       title="PDF预览" | 
					
						
							|  |  |  |  |       onCancel={onCancel} | 
					
						
							|  |  |  |  |       footer={<Button onClick={onCancel}>关闭</Button>} | 
					
						
							|  |  |  |  |     > | 
					
						
							|  |  |  |  |       {renderPdfContent()} | 
					
						
							|  |  |  |  |     </Modal> | 
					
						
							|  |  |  |  |   ); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | export default Pdf; |