feat: enhance modal functionality and integrate new components

- Added keyframes and animation for a smooth scale-in effect in the Tailwind configuration.
- Updated Image component to improve quality handling and style definitions.
- Introduced WordViewer and WordViewerModal components for document viewing capabilities.
- Enhanced Modal component to support embedded mode with customizable position and dimensions.
- Integrated IframeModal across various pages for user assistance and content display.
- Updated Content and Menu pages to utilize new components and improve user interaction.
- Added utility function to retrieve public paths for resources.
This commit is contained in:
zhongyidian committed 2025-10-29 00:18:06 +08:00
1 parent 13dd84a8a7
commit 4ce7520066
44 files changed
+1209 -100

No files matched your search

+215
View File
@@ -0,0 +1,215 @@
import { useEffect, useState } from "react";
import mammoth from "mammoth";
interface WordViewerProps {
/** Word 文档的路径 */
docPath: string;
/** 容器的类名 */
className?: string;
}
export const WordViewer = ({ docPath, className = "" }: WordViewerProps) => {
const [htmlContent, setHtmlContent] = useState<string>("");
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string>("");
useEffect(() => {
const loadDocument = async () => {
try {
setLoading(true);
setError("");
// 获取 Word 文档
const response = await fetch(docPath);
if (!response.ok) {
throw new Error("无法加载文档");
}
// 转换为 ArrayBuffer
const arrayBuffer = await response.arrayBuffer();
// 使用 mammoth 转换为 HTML
const result = await mammoth.convertToHtml({
arrayBuffer: arrayBuffer,
});
setHtmlContent(result.value);
// 如果有警告信息,可以在控制台输出
if (result.messages.length > 0) {
console.warn("文档转换警告:", result.messages);
}
} catch (err) {
console.error("加载文档失败:", err);
setError(err instanceof Error ? err.message : "加载文档失败");
} finally {
setLoading(false);
}
};
loadDocument();
}, [docPath]);
if (loading) {
return (
<div className={`flex justify-center items-center ${className}`}>
<div className="text-[#82B2D6] text-2xl font-bold">加载中...</div>
</div>
);
}
if (error) {
return (
<div className={`flex justify-center items-center ${className}`}>
<div className="text-red-500 text-2xl font-bold">加载失败: {error}</div>
</div>
);
}
return (
<div className={`h-full flex flex-col p-4 ${className}`}>
{/* 头部工具栏 */}
{/* <div className="flex justify-between items-center mb-4">
<h3 className="text-[#82B2D6] text-2xl font-bold">工作室活动文稿</h3>
<a
href={docPath}
download="工作室活动文稿.docx"
className="px-6 py-2 bg-[#82B2D6] text-white rounded-lg hover:bg-[#6a9bc4] transition-colors text-sm font-medium"
>
下载文档
</a>
</div> */}
{/* 文档内容区域 custom-scrollbar*/}
<div className="flex-1 overflow-y-auto bg-white rounded-lg px-4 py-0 ">
<div
className="word-content"
dangerouslySetInnerHTML={{ __html: htmlContent }}
style={{
maxWidth: "100%",
color: "#333",
lineHeight: "1.8",
}}
/>
</div>
{/* 内联样式 - 美化文档内容 */}
<style>{`
.word-content h1 {
font-size: 2em;
font-weight: bold;
margin: 1em 0 0.5em;
color: #1a1a1a;
border-bottom: 2px solid #82B2D6;
padding-bottom: 0.3em;
}
.word-content h2 {
font-size: 1.5em;
font-weight: bold;
margin: 0.8em 0 0.4em;
color: #2a2a2a;
}
.word-content h3 {
font-size: 1.3em;
font-weight: bold;
margin: 0.6em 0 0.3em;
color: #3a3a3a;
}
.word-content p {
margin: 0.8em 0;
text-align: justify;
text-indent: 2em;
}
/* 表格内的段落不需要缩进 */
.word-content table p {
text-indent: 0;
margin: 0.4em 0;
}
.word-content img {
max-width: 100%;
height: auto;
display: block;
margin: 1.5em auto;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.word-content ul,
.word-content ol {
margin: 0.8em 0;
padding-left: 2em;
}
.word-content li {
margin: 0.4em 0;
}
.word-content table {
width: 100%;
border-collapse: collapse;
margin: 1em 0;
table-layout: fixed;
}
.word-content table th,
.word-content table td {
border: 1px solid #ddd;
padding: 0.8em;
text-align: left;
vertical-align: top;
word-wrap: break-word;
word-break: break-word;
overflow-wrap: break-word;
}
.word-content table th {
background-color: #f5f5f5;
font-weight: bold;
}
/* 表格第一列(标题列)固定宽度 */
.word-content table tr td:first-child,
.word-content table tr th:first-child {
width: 200px;
min-width: 200px;
white-space: normal;
font-weight: 600;
background-color: #f8f9fa;
}
.word-content strong,
.word-content b {
font-weight: bold;
color: #1a1a1a;
}
.word-content em,
.word-content i {
font-style: italic;
}
.word-content a {
color: #82B2D6;
text-decoration: underline;
}
.word-content a:hover {
color: #6a9bc4;
}
.word-content blockquote {
border-left: 4px solid #82B2D6;
padding-left: 1em;
margin: 1em 0;
color: #666;
font-style: italic;
}
`}</style>
</div>
);
};