feat: 1. 接入CollaboraViewer选中的高亮效果,清除高亮功能,页面销毁自动清除高亮。

2. 合同模板对比接入monaco editor的效果。
3. 添加交叉评查的案卷类型的数据查询。

fix: 1. 修复文档列表的打开模态框蒙板层显示效果。
This commit is contained in:
2025-11-30 19:33:05 +08:00
parent fb67f138dc
commit 4fcc92a381
14 changed files with 1263 additions and 286 deletions
+9 -9
View File
@@ -42,7 +42,7 @@ export async function callPythonScript(
const verbose = options?.verbose ?? true;
if (verbose) {
console.log('[CallCustomScript] 调用 Python 脚本:', { scriptFile, functionName, args });
// console.log('[CallCustomScript] 调用 Python 脚本:', { scriptFile, functionName, args });
}
return new Promise((resolve, reject) => {
@@ -72,7 +72,7 @@ export async function callPythonScript(
cleanup();
if (verbose) {
console.log('[CallCustomScript] 收到 Python 脚本响应:', data);
// console.log('[CallCustomScript] 收到 Python 脚本响应:', data);
}
const result = parseScriptResponse(data, verbose);
@@ -107,7 +107,7 @@ export async function callPythonScript(
};
if (verbose) {
console.log('[CallCustomScript] 发送 PostMessage:', message);
// console.log('[CallCustomScript] 发送 PostMessage:', message);
}
iframeWindow.postMessage(JSON.stringify(message), '*');
@@ -130,12 +130,12 @@ function parseScriptResponse(data: PostMessageResponse, verbose: boolean): Scrip
}
if (verbose) {
console.log('[CallCustomScript] 解析结果:', {
commandName: values.commandName,
unoSuccess: values.success,
resultRaw: values.result,
resultExtracted: resultValue,
});
// console.log('[CallCustomScript] 解析结果:', {
// commandName: values.commandName,
// unoSuccess: values.success,
// resultRaw: values.result,
// resultExtracted: resultValue,
// });
}
if (values.success === false) {
+110 -4
View File
@@ -10,11 +10,11 @@
* @encoding UTF-8
*/
import { useRef, forwardRef, useImperativeHandle, useState } from 'react';
import { useRef, forwardRef, useImperativeHandle, useState, useEffect } from 'react';
import type { CollaboraViewerProps, CollaboraViewerHandle } from './types';
import { useCollaboraConfig, useDocumentReady, useCollaboraUnoCommands } from './hooks';
import { sendUnoCommand } from './Uno';
import { highlightText } from './lib/Highlightselecttext';
import { highlightText as performTextHighlight } from './lib/Highlightselecttext';
import { clearHighlights } from './lib/ClearHighlight';
import {
unoScrollToTop,
@@ -41,10 +41,14 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
mode = 'view',
userId = 'guest',
userName = '',
targetPage,
highlightText,
},
ref
) {
const iframeRef = useRef<HTMLIFrameElement>(null);
// 保存 iframe 的 contentWindow 引用,用于组件卸载时清除高亮
const iframeWindowRef = useRef<Window | null>(null);
// 高亮测试面板状态
const [highlightTextInput, setHighlightTextInput] = useState('');
@@ -89,17 +93,119 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
// 2. 监听文档加载状态
const { isDocumentLoaded } = useDocumentReady(iframeRef);
// 2.5. 保存 iframe window 引用并在文档加载时清除所有高亮
useEffect(() => {
if (isDocumentLoaded && iframeRef.current?.contentWindow) {
iframeWindowRef.current = iframeRef.current.contentWindow;
console.log('[CollaboraViewer] 已保存 iframe window 引用');
// 🔥 文档加载完成后主动清除一次高亮(防止缓存的高亮状态)
console.log('[CollaboraViewer] 🧹 文档加载完成,清除可能存在的缓存高亮');
clearHighlights(iframeRef.current.contentWindow, {
color: 16776960,
timeout: 5000,
}).then((result) => {
if (result.count && result.count > 0) {
console.log(`[CollaboraViewer] ✓ 清除了 ${result.count} 个缓存的高亮区域`);
} else {
console.log('[CollaboraViewer] ✓ 文档无缓存高亮,已确认干净');
}
}).catch(error => {
console.warn('[CollaboraViewer] ⚠️ 清除缓存高亮失败:', error);
});
}
}, [isDocumentLoaded]);
// 3. UNO 命令封装
const unoCommands = useCollaboraUnoCommands(iframeRef);
// 4. 暴露接口给父组件
// 4. 暴露接口给父组件(包括清除高亮方法)
useImperativeHandle(ref, () => ({
unoCommands,
isReady: isDocumentLoaded,
mode,
getIframeWindow: () => iframeRef.current?.contentWindow || null,
clearAllHighlights: async () => {
const savedWindow = iframeWindowRef.current || iframeRef.current?.contentWindow;
if (savedWindow) {
console.log('[CollaboraViewer] 🧹 父组件调用清除高亮');
await clearHighlights(savedWindow, {
color: 16776960,
timeout: 5000,
});
console.log('[CollaboraViewer] ✓ 清除高亮完成');
} else {
console.warn('[CollaboraViewer] ⚠️ 无法清除高亮:iframe window 不可用');
}
},
}), [unoCommands, isDocumentLoaded, mode]);
// 5. 监听 targetPage 和 highlightText 变化,自动跳转并高亮
useEffect(() => {
// 如果文档未加载完成,不执行跳转和高亮
if (!isDocumentLoaded || !iframeRef.current?.contentWindow) {
return;
}
// 如果有高亮文本,执行高亮操作
if (highlightText && highlightText.trim() !== '') {
const performHighlight = async () => {
try {
const iframeWindow = iframeRef.current!.contentWindow!;
const textToHighlight = highlightText.trim();
// 🔥 在高亮新内容之前,先清除之前的所有高亮
console.log('[CollaboraViewer] 清除旧高亮...');
await clearHighlights(iframeWindow, {
color: 16776960, // 黄色
timeout: 5000,
});
// 短暂延迟后执行新高亮,确保清除操作完成
await new Promise(resolve => setTimeout(resolve, 100));
// 执行新高亮
await performTextHighlight(
iframeWindow,
textToHighlight,
{ page: targetPage }
);
console.log(`[CollaboraViewer] 已高亮文本: "${textToHighlight}"${targetPage ? ` (第${targetPage}页)` : ''}`);
} catch (error) {
console.error('[CollaboraViewer] 高亮失败:', error);
}
};
performHighlight();
}
}, [targetPage, highlightText, isDocumentLoaded]);
// 6. 组件销毁时清除所有高亮(使用保存的 window 引用)
useEffect(() => {
// 返回清理函数,在组件卸载时执行
return () => {
const savedWindow = iframeWindowRef.current;
if (savedWindow) {
console.log('[CollaboraViewer] 🔥 组件即将销毁,立即清除所有高亮');
// 立即触发清除操作,不等待异步完成
// 使用 void 关键字表示我们不关心 Promise 的结果
void clearHighlights(savedWindow, {
color: 16776960, // 黄色
timeout: 3000,
}).then(() => {
console.log('[CollaboraViewer] ✓ 组件销毁时高亮清除成功');
}).catch(error => {
console.error('[CollaboraViewer] ✗ 组件销毁时清除高亮失败:', error);
});
// 清空引用
iframeWindowRef.current = null;
} else {
console.warn('[CollaboraViewer] ⚠️ 组件销毁时未找到保存的 window 引用');
}
};
}, []);
// 加载中状态
if (loading) {
@@ -185,7 +291,7 @@ export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewer
return;
}
await highlightText(
await performTextHighlight(
iframeRef.current.contentWindow,
highlightTextInput.trim(),
{ page }
+6
View File
@@ -13,6 +13,12 @@ export {
unoScrollToTop
} from './navigation';
// 缩放功能
export {
unoZoomIn,
unoZoomOut,
unoSetZoom
} from './zoom';
// 页数信息
export {
+37
View File
@@ -0,0 +1,37 @@
/**
* Collabora Online 缩放功能
*
* @encoding UTF-8
*/
import { sendUnoCommand } from '../Uno';
/**
* 放大文档
* @param iframeWindow - iframe 的 contentWindow
*/
export function unoZoomIn(iframeWindow: Window): void {
sendUnoCommand(iframeWindow, '.uno:ZoomPlus');
}
/**
* 缩小文档
* @param iframeWindow - iframe 的 contentWindow
*/
export function unoZoomOut(iframeWindow: Window): void {
sendUnoCommand(iframeWindow, '.uno:ZoomMinus');
}
/**
* 设置缩放比例
* @param iframeWindow - iframe 的 contentWindow
* @param percentage - 缩放比例(例如:100 表示 100%)
*/
export function unoSetZoom(iframeWindow: Window, percentage: number): void {
sendUnoCommand(iframeWindow, '.uno:Zoom', {
Zoom: {
type: 'long',
value: percentage,
},
});
}
+6
View File
@@ -34,6 +34,10 @@ export interface CollaboraViewerProps {
userId?: string;
/** 用户名称 */
userName?: string;
/** 目标页码(用于自动跳转和高亮) */
targetPage?: number;
/** 要高亮的文本内容 */
highlightText?: string;
}
/**
@@ -50,4 +54,6 @@ export interface CollaboraViewerHandle {
mode: 'view' | 'edit';
/** 获取 iframe 的 contentWindow (用于发送 PostMessage) */
getIframeWindow: () => Window | null;
/** 清除所有高亮 */
clearAllHighlights: () => Promise<void>;
}