Files
mnote/design/pdf方案2.md
T

116 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
根据你的需求(PDF 内容精确引用到思维导图节点,且支持双向跳转),结合项目技术栈(Next.js + TypeScript),推荐以下 PDF 组件方案:
### 推荐组件:`@react-pdf-viewer/core`(搭配 `@react-pdf-viewer/selection-mode` 插件)
#### 核心优势:
1. **精确内容选取**:支持页面级、文本片段级选择,可获取选中内容的页码、坐标、文本内容
2. **双向链接能力**:可生成带定位信息的锚点(如 `#page=3&selection=xxx`),实现思维导图点击跳转
3. **React 生态适配**:完美兼容 Next.js 15 和 TypeScript,支持 SSR/SSG
4. **轻量可扩展**:核心包体积小,按需加载插件(如文本选择、搜索、缩放)
#### 实现思路:
1. **PDF 查看器集成**
```tsx
// components/PDFViewer.tsx
import { Viewer, Worker } from '@react-pdf-viewer/core';
import { selectionModePlugin } from '@react-pdf-viewer/selection-mode';
import '@react-pdf-viewer/core/lib/styles/index.css';
import '@react-pdf-viewer/selection-mode/lib/styles/index.css';
const selectionMode = selectionModePlugin();
const { SelectionMode } = selectionMode;
interface PDFViewerProps {
fileUrl: string;
onSelect: (data: {
text: string;
pageNumber: number;
position: { x: number; y: number };
}) => void;
}
export default function PDFViewer({ fileUrl, onSelect }: PDFViewerProps) {
return (
<Worker workerUrl="https://unpkg.com/pdfjs-dist@3.4.120/build/pdf.worker.min.js">
<SelectionMode
onSelect={(args) => {
if (args.selectionText) {
onSelect({
text: args.selectionText,
pageNumber: args.pageIndex + 1, // 页码从1开始
position: args.selectionRects[0]?.position || { x: 0, y: 0 },
});
}
}}
>
<Viewer fileUrl={fileUrl} plugins={[selectionMode]} />
</SelectionMode>
</Worker>
);
}
```
2. **思维导图节点与 PDF 引用绑定**
```tsx
// 思维导图节点数据结构扩展
interface MindMapNode {
id: string;
text: string;
pdfReference?: {
fileId: string; // 关联的PDF文件ID
pageNumber: number;
text: string; // 引用的文本内容
position?: { x: number; y: number }; // 可选:更精确的定位
};
}
// 点击节点跳转PDF
const handleNodeClick = (node: MindMapNode) => {
if (node.pdfReference) {
// 导航到PDF查看页并定位
router.push(`/documents/${node.pdfReference.fileId}?page=${node.pdfReference.pageNumber}`);
}
};
```
3. **PDF 选择内容插入思维导图**
```tsx
// 在PDF查看页中使用
const PDFDocumentPage = ({ params }) => {
const [mindMapNodes, setMindMapNodes] = useState<MindMapNode[]>([]);
const handlePDFSelect = (data) => {
// 创建新节点并关联PDF引用
const newNode: MindMapNode = {
id: uuidv4(),
text: data.text.substring(0, 50) + '...', // 截断显示
pdfReference: {
fileId: params.id,
pageNumber: data.pageNumber,
text: data.text,
position: data.position,
},
};
setMindMapNodes([...mindMapNodes, newNode]);
};
return <PDFViewer fileUrl={pdfUrl} onSelect={handlePDFSelect} />;
};
```
4. **双向跳转优化**
- 在 PDF 查看页加载时,通过 URL 参数自动定位到指定页:
```tsx
const { page } = useSearchParams();
const defaultPage = page ? parseInt(page.toString()) : 1;
// 传递defaultPage给Viewer组件
```
- 思维导图节点显示引用标识(如 📄3 表示引用第3页),增强可视化关联
### 备选方案:
如果需要更强大的 PDF 处理能力(如 MinerU 提取后的结构化内容引用),可结合:
- **后端**MinerU 提取 PDF 时记录「文本块-页码」映射关系
- **前端**:通过 `@react-pdf-viewer` 定位到 MinerU 识别的文本块位置
该方案完全符合项目前后端分离架构,且能无缝集成到现有的思维导图(simple-mind-map)和文档系统中。