mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-10 11:26:50 +08:00
334 lines
12 KiB
JavaScript
334 lines
12 KiB
JavaScript
var LAYER_CHANGE_ACTIVE_CLASS = 'layerChange-active'
|
||
|
||
// 获取 button 元素
|
||
var layerChangeButton = document.getElementById('layerChange');
|
||
|
||
var isLayerChangeButtonActive = () => {
|
||
return layerChangeButton.classList.contains(LAYER_CHANGE_ACTIVE_CLASS)
|
||
}
|
||
|
||
var getLocale = () => {
|
||
console.log('test-iframe-locale', localStorage.getItem('umi-locale') ,localStorage.getItem('locale') , '')
|
||
return localStorage.getItem('umi_locale') || localStorage.getItem('locale') || 'zh-CN';
|
||
}
|
||
|
||
// 添加tooltip
|
||
function createHoverTooltip(element, tooltipText, id, options = {}) {
|
||
const tooltip = document.createElement('div');
|
||
tooltip.className = `tooltip-${id} tooltip`;
|
||
tooltip.style.display = 'none';
|
||
tooltip.style.zIndex = '999';
|
||
document.body.appendChild(tooltip);
|
||
|
||
const defaultOptions = {
|
||
offset: { y: 10 },
|
||
delay: 200,
|
||
duration: 200,
|
||
};
|
||
|
||
const mergedOptions = { ...defaultOptions, ...options };
|
||
|
||
let tooltipTimer;
|
||
|
||
function positionTooltip() {
|
||
const rect = element.getBoundingClientRect();
|
||
const tooltipRect = tooltip.getBoundingClientRect();
|
||
const left = rect.left + (rect.width - tooltipRect.width) / 2;
|
||
const top = rect.bottom + mergedOptions.offset.y;
|
||
|
||
tooltip.style.left = `${left}px`;
|
||
tooltip.style.top = `${top}px`;
|
||
}
|
||
|
||
function showTooltip() {
|
||
tooltip.textContent = tooltipText;
|
||
tooltip.style.display = 'block';
|
||
tooltip.style.opacity = '0';
|
||
tooltip.style.transition = `opacity ${mergedOptions.duration}ms`;
|
||
positionTooltip();
|
||
setTimeout(() => {
|
||
tooltip.style.opacity = '1';
|
||
}, 10);
|
||
}
|
||
|
||
function hideTooltip() {
|
||
tooltip.style.opacity = '0';
|
||
setTimeout(() => {
|
||
tooltip.style.display = 'none';
|
||
}, mergedOptions.duration);
|
||
}
|
||
|
||
element.addEventListener('mouseenter', () => {
|
||
tooltipTimer = setTimeout(showTooltip, mergedOptions.delay);
|
||
});
|
||
|
||
element.addEventListener('mouseleave', () => {
|
||
clearTimeout(tooltipTimer);
|
||
hideTooltip();
|
||
});
|
||
|
||
window.addEventListener('resize', positionTooltip);
|
||
window.addEventListener('scroll', positionTooltip);
|
||
|
||
// 返回对象,包含 updateTooltipText 函数
|
||
return {
|
||
updateTooltipText: (newText) => {
|
||
tooltipText = newText;
|
||
positionTooltip()
|
||
if (tooltip.style.display !== 'none') {
|
||
showTooltip();
|
||
tooltipText = newText;
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
const tooltipLayer = createHoverTooltip(layerChangeButton, getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results', 'layerChange', { offset: { y: 22 } });
|
||
|
||
|
||
|
||
window.addEventListener('storage', function(event) {
|
||
// 检查事件是否与监听的键相关
|
||
if (event.key === 'umi_locale'|| event.key === 'locale') {
|
||
const text = isLayerChangeButtonActive() ? event?.newValue === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results': getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results'
|
||
tooltipLayer?.updateTooltipText(text)
|
||
}
|
||
});
|
||
|
||
|
||
// 添加点击事件监听器
|
||
layerChangeButton.addEventListener('click', function() {
|
||
// 检查当前 button 的选中状态
|
||
if (isLayerChangeButtonActive()) {
|
||
// 如果已经处于选中状态,则移除选中状态的 class
|
||
const annotationLayerList = document.getElementsByClassName('annotationLayer')
|
||
Array?.from(annotationLayerList)?.forEach(element => {
|
||
var extractLayer = element.querySelector('#extractLayer');
|
||
if(extractLayer) {
|
||
extractLayer.style.opacity = 0
|
||
}
|
||
});
|
||
console.log('test-dd', annotationLayerList, typeof annotationLayerList)
|
||
tooltipLayer?.updateTooltipText( getLocale() === 'zh-CN' ? '显示识别结果': 'Display recognition results')
|
||
this.classList.remove(LAYER_CHANGE_ACTIVE_CLASS);
|
||
} else {
|
||
// 如果未处于选中状态,则添加选中状态的 class
|
||
this.classList.add(LAYER_CHANGE_ACTIVE_CLASS);
|
||
tooltipLayer?.updateTooltipText(getLocale() === 'zh-CN' ? '隐藏识别结果': 'Hide recognition results')
|
||
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
|
||
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
|
||
|
||
const annotationLayerList = document.getElementsByClassName('annotationLayer')
|
||
Array?.from(annotationLayerList)?.forEach(element => {
|
||
var extractLayer = element.querySelector('#extractLayer');
|
||
if(extractLayer) {
|
||
extractLayer.style.opacity = 1
|
||
}
|
||
})
|
||
}
|
||
});
|
||
|
||
|
||
// 获取显示消息的元素
|
||
const messageDisplay = document.getElementById('messageDisplay');
|
||
function removeDuplicates(arr) {
|
||
return [...new Set(arr)];
|
||
}
|
||
|
||
window.addEventListener('error', function(event) {
|
||
if (event.target && event.target.tagName === 'SCRIPT') {
|
||
console.error("Script error detected: ", event);
|
||
}
|
||
}, true);
|
||
|
||
// 添加消息监听器
|
||
window.addEventListener('message', function(event) {
|
||
const receivedMessage = event.data;
|
||
const data = receivedMessage?.data
|
||
const type = receivedMessage?.type
|
||
function setHasRenderAnimatedPage (num) {
|
||
if(!window.hasRenderAnimatedPage ) {
|
||
window.hasRenderAnimatedPage = []
|
||
}
|
||
if( typeof window.hasRenderAnimatedPage === 'object'){
|
||
window.hasRenderAnimatedPage = removeDuplicates([...window.hasRenderAnimatedPage, num])
|
||
}
|
||
}
|
||
let animatingBox = new Map()
|
||
function renderExtractLayer(data, pageNum, scale) {
|
||
// 判断按钮是开的还是关的
|
||
if(!isLayerChangeButtonActive()) return;
|
||
|
||
const bboxes = data?.[pageNum]?.bboxes || []
|
||
|
||
function drawBoxes(boxes, scale) {
|
||
if(animatingBox.get(pageNum)) return
|
||
|
||
// const annotationLayer = document.querySelector('.canvasWrapper');
|
||
const pageLayer = document.getElementsByClassName('page')?.[pageNum]
|
||
const annotationLayer = pageLayer.querySelectorAll('.annotationLayer')?.[0];
|
||
// annotationLayer.removeAttribute('hidden');
|
||
if(!annotationLayer) {
|
||
// console.error('error: annotationLayer has not been rendered')
|
||
return
|
||
}
|
||
const extractLayer = annotationLayer.querySelector('#extractLayer');
|
||
|
||
// 因为pdfjs只会缓存8页的内容,所以采用每次切换移除重建canvas的方式
|
||
if (extractLayer) {
|
||
extractLayer?.remove();
|
||
}
|
||
annotationLayer.style.width = '100%';
|
||
annotationLayer.style.height = '100%'
|
||
annotationLayer.style.position = 'absolute';
|
||
annotationLayer.style.top = 0;
|
||
annotationLayer.style.left = 0;
|
||
const computedLayer = document.querySelector('.canvasWrapper');
|
||
const canvas = document.createElement('canvas');
|
||
canvas.id = 'extractLayer'
|
||
const w = pageLayer?.offsetWidth - 18;
|
||
const h = pageLayer?.offsetHeight - 18;
|
||
canvas.width = true ? `${w}` : '100%';
|
||
canvas.height = true ? `${h}`: '100%';
|
||
canvas.style.width = true ? `${w}px` : '100%';
|
||
canvas.style.height = true ? `${h}px`: '100%';
|
||
canvas.style.position = 'absolute';
|
||
canvas.style.top = 0;
|
||
canvas.style.left = 0;
|
||
annotationLayer.append(canvas)
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
// 移除之前的画布内容
|
||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
ctx.save();
|
||
// console.log('renderExtractLayer: draw boxes')
|
||
|
||
function drawPartialRect(ctx, box, progress, scale) {
|
||
const [x, y, x2, y2]= box.bbox.map((i) => (i * scale));
|
||
const width = x2 - x;
|
||
const height = y2 - y;
|
||
const color = box?.color?.line
|
||
const fillColor = box?.color?.fill
|
||
ctx.beginPath();
|
||
ctx.strokeStyle = color;
|
||
|
||
// 左边竖线
|
||
ctx.moveTo(x, y);
|
||
ctx.lineTo(x, y2);
|
||
|
||
// 上边横线
|
||
ctx.moveTo(x, y);
|
||
ctx.lineTo(x + width * (progress < 0 ? 0: progress), y);
|
||
|
||
// 右边竖线 (只在进度完成时绘制)
|
||
if (progress === 1) {
|
||
ctx.moveTo(x2, y);
|
||
ctx.lineTo(x2, y2);
|
||
ctx.fillStyle = fillColor;
|
||
ctx.fillRect(x, y, width, height);
|
||
}
|
||
|
||
// 下边横线
|
||
ctx.moveTo(x, y2);
|
||
ctx.lineTo(x + width * (progress < 0 ? 0: progress), y2);
|
||
|
||
ctx.stroke();
|
||
}
|
||
|
||
function fillRect(ctx, box, scale) {
|
||
const [x, y, x2, y2]= box.bbox.map((i) => (i * scale));
|
||
const width = x2 - x;
|
||
const height = y2 - y;
|
||
const color = box?.color?.fill
|
||
|
||
ctx.fillStyle = color;
|
||
ctx.fillRect(x, y, width, height);
|
||
}
|
||
|
||
function animateBox(ctx, box, duration = 1000) {
|
||
const startTime = performance.now();
|
||
|
||
function animate(currentTime) {
|
||
const elapsedTime = currentTime - startTime;
|
||
const progress = Math.min(elapsedTime / duration, 1);
|
||
// ctx.clearRect(...box.bbox); // 清除之前的绘制
|
||
drawPartialRect(ctx, box, progress, scale);
|
||
|
||
if (progress < 1) {
|
||
requestAnimationFrame(animate);
|
||
}
|
||
}
|
||
|
||
requestAnimationFrame(animate);
|
||
}
|
||
|
||
async function animateAllBoxes() {
|
||
// const [index, value] of array.entries()
|
||
for (const [index, box] of boxes?.entries()) {
|
||
await animateBox(ctx, box, 600); // 动画时间改为500ms
|
||
await new Promise(resolve => setTimeout(resolve, 200)); // 每个框之间的延迟也减少到100ms
|
||
}
|
||
|
||
// 所有线框动画完成后,一次性填充所有矩形
|
||
// ctx.clearRect(...box.bbox); // 清除之前的绘制
|
||
// boxes.forEach(box => fillRect(ctx, box, scale));
|
||
console.log("test-animate All animations completed and boxes filled");
|
||
animatingBox.set(pageNum, false)
|
||
}
|
||
|
||
boxes.forEach((box, index) => {
|
||
drawPartialRect(ctx, box, 1, scale);
|
||
});
|
||
|
||
|
||
canvas.style.width = false ? `${w}px` : '100%';
|
||
canvas.style.height = false ? `${h}px`: '100%';
|
||
ctx.restore();
|
||
}
|
||
!!bboxes?.length&&drawBoxes(bboxes, scale);
|
||
|
||
}
|
||
|
||
// init extractLayer data
|
||
if(type === 'initExtractLayerData') {
|
||
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
|
||
const currentPageNumber = window?.PDFViewerApplication?.pdfViewer?._currentPageNumber || 1
|
||
window.pdfExtractData = data;
|
||
window.renderExtractLayer = renderExtractLayer
|
||
// window.renderExtractLayer(window.pdfExtractData, currentPageNumber - 1, scale)
|
||
// use the picture view rather than outlined view
|
||
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
|
||
window?.PDFViewerApplication?.pdfSidebar?.switchView(1, false)
|
||
}
|
||
|
||
if(type === 'pageChange') {
|
||
if(window.renderExtractLayer
|
||
&& window.pdfExtractData
|
||
) {
|
||
const scale = 0.943 / 0.7071 * window?.PDFViewerApplication?.pdfViewer?._currentScale || 1
|
||
const currentPageNumber = data || 0
|
||
window.renderExtractLayer(window.pdfExtractData, Number(0), scale)
|
||
window.renderExtractLayer(window.pdfExtractData, Number(data), scale)
|
||
} else if(!window.pdfExtractData) {
|
||
// console.error('extract pdf render data has not been initialized')
|
||
}
|
||
}
|
||
|
||
if( type === 'title') {
|
||
const odlPdfTitle = document.getElementById("odl-pdf-title");
|
||
odlPdfTitle.innerText = data;
|
||
}
|
||
|
||
if( type === 'setPage') {
|
||
window?.PDFViewerApplication?.eventBus?.dispatch("pagenumberchanged", {
|
||
value: data
|
||
})
|
||
}
|
||
|
||
if( type === '') {
|
||
|
||
}
|
||
});
|
||
|
||
|