feat(knowledge): 添加 MinerU组件以支持 PDF 文件处理

- 新增 RenderMinerU 组件,用于 PDF 文件的预处理和 Markdown 编辑
- 在 create.vue 中集成 RenderMinerU组件,实现预处理结果预览功能
- 更新公共样式以支持 Markdown 渲染
- 在 main.js 中注册 RMinerU组件
- 修改 package.json,添加 markdown-it 和 markdown-it-katex 依赖
- 更新 vue.config.js,添加对 mjs 文件的处理规则
This commit is contained in:
陈昱达
2025-04-11 16:26:27 +08:00
parent e9ee7fe0a2
commit d108379f41
8 changed files with 379 additions and 42 deletions

View File

@@ -0,0 +1,173 @@
<template>
<div style="height: 100%;">
<div class="flex" style="height:calc(100% - 20px);flex:1">
<iframe
id="iframe"
:src="`${iframeSrc}/pdfjs-dist/web/viewer.html?file=${encodeURIComponent(prdUrl)}`"
class="miner-u el-card is-always-shadow ml20"
></iframe>
<div style="flex:1;max-width: 800px;" class="mh20 miner-u-md">
<el-tabs type="border-card" style="height: 100%;overflow: hidden" @tab-click="changeTab">
<el-tab-pane label="预览" style="overflow:scroll;">
<div v-html="markdownHtml" class="view-body"></div>
</el-tab-pane>
<el-tab-pane label="编辑">
<div class="lineH25" contenteditable id="md-editor" @blur="emitMarkDown">{{ markdown }}</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</template>
<script>
import { minerUBbox, minerUMarkDown } from '@/api/generatedApi/index'
import { DEFAULT_COLOR_SECTION, PDF_COLOR_PICKER } from './pdf-color'
import MarkdownIt from 'markdown-it'
import markdownItKatex from 'markdown-it-katex'
const md = new MarkdownIt({
html: true
}).use(markdownItKatex)
export default {
name: 'index',
data() {
return {
prdUrl: ``,
iframeSrc: window.location.href,
bboxList: [],
markdown: '',
md,
markdownHtml: ''
}
},
props: {},
watch: {},
components: {},
filters: {},
methods: {
emitMarkDown() {
let pre = document.getElementById('md-editor').innerText
this.$emit('getMarkDownIt', { innerText: pre })
},
formatJson(data) {
return data.map(item => {
let bboxes = []
// 处理预处理块
if (item.preproc_blocks && item.preproc_blocks.length > 0) {
item.preproc_blocks.forEach(block => {
bboxes.push({
type: block.type,
bbox: block.bbox,
color: PDF_COLOR_PICKER[block.type] || DEFAULT_COLOR_SECTION
})
})
}
// 处理丢弃块
if (item.discarded_blocks && item.discarded_blocks.length > 0) {
item.discarded_blocks.forEach(block => {
bboxes.push({
type: block.type,
bbox: block.bbox,
color: PDF_COLOR_PICKER[block.type] || DEFAULT_COLOR_SECTION
})
})
}
return {
...item,
bboxes
}
})
},
// bbox 解析 传递 颜色
getPDFDetailBbox() {
minerUBbox({ documentId: 1 }).then(res => {
this.bboxList = this.formatJson(JSON.parse(JSON.stringify(res.content.content)))
})
},
changeTab() {
let pre = document.getElementById('md-editor').innerText
this.markdownHtml = md.render(pre)
},
async getPDFDetailMarkDown() {
const response = await fetch(minerUMarkDown({ documentId: 1 }))
this.markdown = await response.text()
this.markdownHtml = this.md.render(this.markdown)
},
// 向 iframe 发送消息
sendMessageToIframe(type, message) {
// 获取 iframe 元素
const iframe = document.getElementById('iframe')
// 检查 iframe 是否存在并且可以发送消息
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(
{
type,
data: message
},
'*'
)
}
}
},
created() {
this.getPDFDetailBbox()
this.getPDFDetailMarkDown()
},
mounted() {
// 监听 iframe 的 postMessage 事件
window.addEventListener('message', event => {
// 检查消息来源是否合法
if (event.origin + '/' === process.env.BASE_URL) {
// 根据消息状态执行不同操作
switch (event.data.status) {
case 'loaded':
// 格式化 JSON 数据并发送给 iframe
this.sendMessageToIframe('initExtractLayerData', this.bboxList)
this.sendMessageToIframe('title', '')
break
}
}
if (event.data.pageNum) {
const num = event.data.pageNum || 1
this.sendMessageToIframe('pageChange', num)
}
if (event.data.pageNumDetail) {
const pageNumDetail = event.data.pageNumDetail || 1
this.page.value = pageNumDetail
this.sendMessageToIframe('pageNumDetail', pageNumDetail)
}
})
},
computed: {}
}
</script>
<style scoped lang="scss">
.miner-u {
outline: none;
border: none;
flex: 1;
border-radius: unset;
//width:500px;
//height:100%
}
#md-editor {
//超过宽度自动折行
white-space: pre-wrap;
word-wrap: break-word;
overflow: auto;
outline: none;
border: none;
}
.miner-u-md {
/deep/ .el-tabs--border-card > .el-tabs__content {
height: calc(100% - 30px);
overflow: auto;
}
.tabs__content {
}
}
</style>