mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-10 03:16:49 +08:00
314 lines
9.9 KiB
Vue
314 lines
9.9 KiB
Vue
<template>
|
|
<div style="height: 100%;">
|
|
<div class="mv10 mh20 text-right" v-if="isEdit">
|
|
<el-button type="primary" size="medium" @click="saveMarkDown">保存并处理</el-button>
|
|
<el-button size="medium">取消</el-button>
|
|
</div>
|
|
<div :class="!isEdit ? 'mt10 flex' : 'flex'" style="height:calc(100% - 35px);flex:1">
|
|
<iframe
|
|
v-if="isShowPdf"
|
|
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;" 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" id="viewBody" ref="viewBody"></div>
|
|
</el-tab-pane>
|
|
<el-tab-pane label="编辑" :disabled="!isEdit" v-if="isEdit">
|
|
<div class="lineH25 view-body" contenteditable id="md-editor" @blur="emitMarkDown" v-html="markdown">
|
|
<!-- <pre id="viewBody"></pre>-->
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import { getPdfUrl, minerUBbox, minerUMarkDown, minerUMarkDownUpdate } 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 {
|
|
tableIdCounter: 0,
|
|
prdUrl: ``,
|
|
iframeSrc: window.location.origin,
|
|
bboxList: [],
|
|
markdown: '',
|
|
md,
|
|
markdownHtml: '',
|
|
page: 1,
|
|
copyTable: null,
|
|
tableActionButtons: [
|
|
{
|
|
label: '重新识别',
|
|
icon: 'el-icon-edit',
|
|
click: tableElement => {
|
|
console.log('重新识别')
|
|
}
|
|
},
|
|
{
|
|
label: '编辑',
|
|
icon: 'el-icon-edit',
|
|
click: tableElement => {
|
|
this.copyTable = tableElement.innerHTML
|
|
tableElement.classList.remove('m-view')
|
|
tableElement.setAttribute('contenteditable', 'true')
|
|
let buttonContainer = tableElement.querySelector('.md-editor-setting')
|
|
buttonContainer.innerHTML = null
|
|
this.generateButton(tableElement, buttonContainer, this.tableActionConfirm)
|
|
}
|
|
}
|
|
],
|
|
tableActionConfirm: [
|
|
{
|
|
label: '返回',
|
|
icon: 'el-icon-edit',
|
|
click: tableElement => {
|
|
tableElement.classList.add('m-view')
|
|
tableElement.setAttribute('contenteditable', 'false')
|
|
let buttonContainer = tableElement.querySelector('.md-editor-setting')
|
|
buttonContainer.innerHTML = null
|
|
this.generateButton(tableElement, buttonContainer, this.tableActionButtons)
|
|
}
|
|
}
|
|
// {
|
|
// label: '取消',
|
|
// icon: 'el-icon-edit',
|
|
// click: tableElement => {}
|
|
// }
|
|
]
|
|
}
|
|
},
|
|
props: {
|
|
documentId: {
|
|
type: String,
|
|
default: '1361351897324294144'
|
|
},
|
|
isEdit: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
isShowPdf: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
},
|
|
watch: {},
|
|
components: {},
|
|
filters: {},
|
|
methods: {
|
|
// 封装 按钮生成事件
|
|
generateButton(tableElement, buttonContainer, actionButtons) {
|
|
let contenteditable = tableElement.getAttribute('contenteditable')
|
|
let buttons = !actionButtons ? (contenteditable === 'false' ? this.tableActionButtons : this.tableActionConfirm) : actionButtons
|
|
// 循环按钮配置
|
|
for (let i = 0; i < buttons.length; i++) {
|
|
const button = document.createElement('button')
|
|
button.innerText = buttons[i].label
|
|
button.className = 'el-button el-button--primary el-button--mini editor-button'
|
|
button.style.pointerEvents = 'auto'
|
|
button.addEventListener('click', () => {
|
|
buttons[i].click(tableElement)
|
|
})
|
|
buttonContainer.appendChild(button)
|
|
}
|
|
},
|
|
|
|
// 生成视觉模型
|
|
viewHtmlModel() {
|
|
this.$nextTick(() => {
|
|
const mdHtml = document.getElementById('md-editor')
|
|
mdHtml.addEventListener('mouseover', e => {
|
|
const tableElement = e.target.closest('table')
|
|
if (tableElement) {
|
|
// 检查是否已经存在按钮容器
|
|
let buttonContainer = tableElement.querySelector('.md-editor-setting')
|
|
if (!buttonContainer) {
|
|
buttonContainer = document.createElement('div')
|
|
buttonContainer.style.position = 'absolute'
|
|
buttonContainer.style.pointerEvents = 'none'
|
|
buttonContainer.style.zIndex = '9999'
|
|
buttonContainer.className = 'md-editor-setting'
|
|
buttonContainer.setAttribute('contenteditable', 'false')
|
|
this.generateButton(tableElement, buttonContainer)
|
|
// 设置按钮位置在表格正中间浮动
|
|
const rect = tableElement.getBoundingClientRect()
|
|
buttonContainer.style.left = `10px` // 调整位置
|
|
buttonContainer.style.top = `-20px` // 调整位置
|
|
tableElement.appendChild(buttonContainer)
|
|
}
|
|
}
|
|
})
|
|
|
|
mdHtml.addEventListener('mouseout', e => {
|
|
const tableElement = e.target.closest('table')
|
|
if (!tableElement || !tableElement.contains(e.relatedTarget)) {
|
|
const buttonContainer = tableElement.querySelector('.md-editor-setting')
|
|
if (buttonContainer) {
|
|
buttonContainer.remove()
|
|
}
|
|
}
|
|
})
|
|
})
|
|
},
|
|
// 导出
|
|
emitMarkDown() {
|
|
let pre = document.getElementById('md-editor').innerText
|
|
this.$emit('getMarkDownIt', { innerText: pre })
|
|
},
|
|
saveMarkDown() {
|
|
let pre = document.getElementById('md-editor').innerText
|
|
minerUMarkDownUpdate({
|
|
documentId: this.documentId,
|
|
newMd: 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: this.documentId }).then(res => {
|
|
this.bboxList = this.formatJson(JSON.parse(JSON.stringify(res.content.content)))
|
|
})
|
|
},
|
|
changeTab() {
|
|
let pre = document.getElementById('md-editor').innerHTML
|
|
// pre = JSON.stringify(pre)
|
|
// let copyMdHtml = md.render(pre)
|
|
// 给 copyMdHtml 里面的table 增加 class m-view
|
|
// copyMdHtml = copyMdHtml.re
|
|
this.markdownHtml = md.render(pre.replace(/class="m-view"/g, ''))
|
|
},
|
|
// 初始md 文档
|
|
async getPDFDetailMarkDown() {
|
|
const response = await fetch(minerUMarkDown({ documentId: this.documentId }))
|
|
this.markdown = await response.text()
|
|
this.markdown = this.markdown
|
|
.replace(/<table/g, () => {
|
|
const uniqueId = `table-${this.tableIdCounter++}`
|
|
return `<table contenteditable='false' id="${uniqueId}" class="m-view"`
|
|
})
|
|
.replace(/<script/g, '< script')
|
|
this.markdownHtml = this.md.render(this.markdown.replace(/class="m-view"/g, ''))
|
|
},
|
|
// 向 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()
|
|
this.prdUrl = getPdfUrl({ documentId: this.documentId })
|
|
},
|
|
mounted() {
|
|
// 监听 iframe 的 postMessage 事件
|
|
window.addEventListener('message', event => {
|
|
// 检查消息来源是否合法
|
|
if (event.origin === window.location.origin) {
|
|
// 根据消息状态执行不同操作
|
|
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 = pageNumDetail
|
|
this.sendMessageToIframe('pageNumDetail', pageNumDetail)
|
|
}
|
|
})
|
|
|
|
this.viewHtmlModel()
|
|
},
|
|
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>
|