import { Button, message, Modal, Spin } from "antd"; import { renderAsync } from "docx-preview"; import { useEffect, useRef, useState } from "react"; import useDownloadFile from "../../hooks/useDownloadFile"; import { getFileUrl } from "../../utils"; /** * Word 查看组件。 */ function Word(props) { const { visible = false, onCancel, file, name, inline = false, title = "Word预览", style = {}, } = props; const contentRef = useRef(null); const fullscreenRef = useRef(null); const unmountedRef = useRef(false); const fileUrl = getFileUrl(); const [loading, setLoading] = useState(false); const { downloadFile } = useDownloadFile(); const renderWord = async () => { setLoading(true); contentRef.current.innerHTML = ""; try { const response = await fetch(!file.includes(fileUrl) ? fileUrl + file : file); if (!response.ok) throw new Error("加载 Word 文件失败"); const data = await response.arrayBuffer(); if (unmountedRef.current) return; await renderAsync(data, contentRef.current, null, { className: "docx-preview", inWrapper: true, ignoreWidth: false, ignoreHeight: false, breakPages: true, }); } catch { message.error("加载 Word 文件失败"); if (!inline && onCancel) onCancel(); } finally { if (!unmountedRef.current) setLoading(false); } }; useEffect(() => { if ((!visible && !inline) || !file) return; unmountedRef.current = false; const initTimer = setTimeout(() => { renderWord(); }, 100); return () => { unmountedRef.current = true; if (contentRef.current) contentRef.current.innerHTML = ""; if (initTimer) clearTimeout(initTimer); }; }, [visible, inline, file]); const renderWordContent = () => (
); if (inline) return renderWordContent(); const onDownloadFile = () => { downloadFile({ url: file, name, }); }; return (
{ onCancel(); }} getContainer={false} footer={[ , , ]} > {renderWordContent()}
); } Word.displayName = "Word"; export default Word;