temp:备份代码
This commit is contained in:
@@ -10,30 +10,63 @@
|
||||
* @encoding UTF-8
|
||||
*/
|
||||
|
||||
import { useRef } from 'react';
|
||||
import type { CollaboraViewerProps } from './types';
|
||||
import { useRef, forwardRef, useImperativeHandle, useState, useEffect } from 'react';
|
||||
import type { CollaboraViewerProps, CollaboraViewerHandle } from './types';
|
||||
import { useCollaboraConfig, useDocumentReady, useCollaboraUnoCommands } from './hooks';
|
||||
import { sendUnoCommand } from './Uno';
|
||||
|
||||
/**
|
||||
* Collabora 文档查看器组件
|
||||
* @param props - 组件属性
|
||||
* @param ref - 父组件传入的 ref,用于暴露命令接口
|
||||
*/
|
||||
export function CollaboraViewer({
|
||||
fileId,
|
||||
mode = 'view',
|
||||
userId = 'guest',
|
||||
userName = '访客',
|
||||
}: CollaboraViewerProps) {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
export const CollaboraViewer = forwardRef<CollaboraViewerHandle, CollaboraViewerProps>(
|
||||
function CollaboraViewer(
|
||||
{
|
||||
fileId,
|
||||
mode = 'view',
|
||||
userId = 'guest',
|
||||
userName = '访客',
|
||||
},
|
||||
ref
|
||||
) {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
|
||||
// 1. 加载 Collabora 配置
|
||||
const { config, loading, error } = useCollaboraConfig(fileId, mode, userId, userName);
|
||||
// 调试面板状态
|
||||
const [unoCmd, setUnoCmd] = useState('.uno:GoToStartOfDoc');
|
||||
const [unoArgs, setUnoArgs] = useState('{}');
|
||||
const [unoResult, setUnoResult] = useState<string | null>(null);
|
||||
|
||||
// 2. 监听文档加载状态
|
||||
const { isDocumentLoaded } = useDocumentReady(iframeRef);
|
||||
// 1. 加载 Collabora 配置
|
||||
const { config, loading, error } = useCollaboraConfig(fileId, mode, userId, userName);
|
||||
|
||||
// 3. UNO 命令封装
|
||||
const unoCommands = useCollaboraUnoCommands(iframeRef);
|
||||
// 2. 监听文档加载状态
|
||||
const { isDocumentLoaded } = useDocumentReady(iframeRef);
|
||||
|
||||
// 3. UNO 命令封装
|
||||
const unoCommands = useCollaboraUnoCommands(iframeRef);
|
||||
|
||||
// 4. 暴露接口给父组件
|
||||
useImperativeHandle(ref, () => ({
|
||||
unoCommands,
|
||||
isReady: isDocumentLoaded,
|
||||
mode,
|
||||
}), [unoCommands, isDocumentLoaded, mode]);
|
||||
|
||||
// 5. 将 sendUnoCommand 挂载到 window 对象,供调试面板和控制台使用
|
||||
useEffect(() => {
|
||||
if (iframeRef.current?.contentWindow) {
|
||||
(window as any).sendUno = (cmd: string, args: any = {}) => {
|
||||
if (iframeRef.current?.contentWindow) {
|
||||
sendUnoCommand(iframeRef.current.contentWindow, cmd, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return () => {
|
||||
delete (window as any).sendUno;
|
||||
};
|
||||
}, [isDocumentLoaded]);
|
||||
|
||||
// 加载中状态
|
||||
if (loading) {
|
||||
@@ -60,8 +93,75 @@ export function CollaboraViewer({
|
||||
);
|
||||
}
|
||||
|
||||
// 发送 UNO 命令的处理函数
|
||||
const sendUno = () => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
setUnoResult('iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(window as any).sendUno) {
|
||||
setUnoResult('window.sendUno 未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
let args: any = {};
|
||||
const raw = (unoArgs || '').trim();
|
||||
if (raw !== '') {
|
||||
try {
|
||||
args = JSON.parse(raw);
|
||||
} catch (err) {
|
||||
try {
|
||||
// fallback: replace single quotes with double quotes and parse
|
||||
args = JSON.parse(raw.replace(/'(.*?)'/g, '"$1"'));
|
||||
} catch (err2) {
|
||||
console.error('解析 UNO Args 失败:', err2);
|
||||
setUnoResult('Args 解析失败,请使用有效 JSON');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 先让 iframe 获得焦点
|
||||
iframeRef.current.focus();
|
||||
console.log('[调试面板] 已聚焦 iframe');
|
||||
|
||||
(window as any).sendUno?.(unoCmd, args);
|
||||
setUnoResult(`已发送: ${unoCmd}`);
|
||||
} catch (e) {
|
||||
console.error('发送 UNO 失败:', e);
|
||||
setUnoResult('发送失败,请查看控制台');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="collabora-viewer relative w-full h-full min-h-[600px]">
|
||||
{/* UNO 命令测试面板 */}
|
||||
<div className="absolute top-2 left-2 z-50 bg-white bg-opacity-90 px-2 py-1 rounded shadow flex items-center gap-2">
|
||||
<input
|
||||
className="px-2 py-1 border rounded text-sm w-48"
|
||||
value={unoCmd}
|
||||
onChange={(e) => setUnoCmd(e.target.value)}
|
||||
placeholder="UNO 命令"
|
||||
aria-label="UNO 命令"
|
||||
/>
|
||||
<input
|
||||
className="px-2 py-1 border rounded text-sm w-64"
|
||||
value={unoArgs}
|
||||
onChange={(e) => setUnoArgs(e.target.value)}
|
||||
placeholder="UNO Args (JSON)"
|
||||
aria-label="UNO Args (JSON)"
|
||||
/>
|
||||
<button
|
||||
className="px-3 py-1 bg-indigo-600 text-white rounded hover:bg-indigo-700 text-sm"
|
||||
onClick={sendUno}
|
||||
>
|
||||
发送 UNO
|
||||
</button>
|
||||
{unoResult && <span className="text-xs text-gray-500 ml-2">{unoResult}</span>}
|
||||
</div>
|
||||
|
||||
{/* 文档加载提示 */}
|
||||
{!isDocumentLoaded && (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-white bg-opacity-90 z-10">
|
||||
@@ -85,10 +185,12 @@ export function CollaboraViewer({
|
||||
allow="clipboard-read; clipboard-write"
|
||||
title={`Collabora Online - ${config.fileName}`}
|
||||
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-modals"
|
||||
tabIndex={0}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 导出 UNO 命令 hook 供父组件使用(如果需要)
|
||||
// 导出类型和 hook
|
||||
export type { CollaboraViewerHandle };
|
||||
export { useCollaboraUnoCommands };
|
||||
|
||||
@@ -19,7 +19,6 @@ export function sendUnoCommand(
|
||||
): void {
|
||||
const message = {
|
||||
MessageId: 'Send_UNO_Command',
|
||||
SendTime: Date.now(),
|
||||
Values: {
|
||||
Command: command,
|
||||
Args: args,
|
||||
@@ -130,10 +129,25 @@ export function unoEscape(iframeWindow: Window): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* 滚动到文档开头
|
||||
* 滚动到文档开头 (带焦点请求)
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
*/
|
||||
export function unoScrollToTop(iframeWindow: Window): void {
|
||||
export async function unoScrollToTop(iframeWindow: Window): Promise<void> {
|
||||
// 1. 先请求 iframe 获取焦点
|
||||
const focusMessage = {
|
||||
MessageId: 'custompostMessage',
|
||||
Values: {
|
||||
Command: 'REQUEST_FOCUS',
|
||||
Args: {},
|
||||
},
|
||||
};
|
||||
console.log('[custompostMessage] 请求焦点 (滚动到顶部)');
|
||||
iframeWindow.postMessage(JSON.stringify(focusMessage), '*');
|
||||
|
||||
// 2. 等待焦点激活
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
// 3. 发送滚动命令
|
||||
sendUnoCommand(iframeWindow, '.uno:GoToStartOfDoc', {});
|
||||
}
|
||||
|
||||
@@ -166,3 +180,64 @@ export function unoGetState(iframeWindow: Window): void {
|
||||
console.log('[UNO] 发送 Get_State (.uno:ModifiedStatus) - 等待命令队列执行完成');
|
||||
iframeWindow.postMessage(JSON.stringify(message), '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* 放大文档(固定步长)
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
*/
|
||||
export function unoZoomPlus(iframeWindow: Window): void {
|
||||
sendUnoCommand(iframeWindow, '.uno:ZoomPlus', {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩小文档(固定步长)
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
*/
|
||||
export function unoZoomMinus(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: 'short',
|
||||
value: percentage,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到指定页面
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
* @param pageNumber - 页码(从1开始)
|
||||
*/
|
||||
export function unoGotoPage(iframeWindow: Window, pageNumber: number): void {
|
||||
sendUnoCommand(iframeWindow, '.uno:GotoPage', {
|
||||
Page: {
|
||||
type: 'long',
|
||||
value: pageNumber,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到第一页
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
*/
|
||||
export function unoFirstPage(iframeWindow: Window): void {
|
||||
sendUnoCommand(iframeWindow, '.uno:FirstPage', {});
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到最后一页
|
||||
* @param iframeWindow - iframe 的 contentWindow
|
||||
*/
|
||||
export function unoLastPage(iframeWindow: Window): void {
|
||||
sendUnoCommand(iframeWindow, '.uno:LastPage', {});
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ import {
|
||||
unoEscape,
|
||||
unoScrollToTop,
|
||||
unoSave,
|
||||
unoZoomPlus,
|
||||
unoZoomMinus,
|
||||
unoSetZoom,
|
||||
unoGotoPage,
|
||||
unoFirstPage,
|
||||
unoLastPage,
|
||||
} from './Uno';
|
||||
import { COLLABORA_URL } from '~/config/api-config';
|
||||
|
||||
@@ -131,9 +137,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 搜索文本: "${text}"`);
|
||||
unoSearchText(iframeRef.current.contentWindow, text);
|
||||
await unoSearchText(iframeRef.current.contentWindow, text);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
},
|
||||
[iframeRef]
|
||||
@@ -175,9 +180,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 替换文本: "${searchText}" -> "${replaceText}"`);
|
||||
unoReplaceText(iframeRef.current.contentWindow, searchText, replaceText);
|
||||
await unoReplaceText(iframeRef.current.contentWindow, searchText, replaceText);
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
},
|
||||
[iframeRef]
|
||||
@@ -192,9 +196,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 高亮文本: "${text}"`);
|
||||
unoHighlightText(iframeRef.current.contentWindow, text, color);
|
||||
await unoHighlightText(iframeRef.current.contentWindow, text, color);
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
},
|
||||
[iframeRef]
|
||||
@@ -209,9 +212,8 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 移除高亮: "${text}"`);
|
||||
unoRemoveHighlight(iframeRef.current.contentWindow, text);
|
||||
await unoRemoveHighlight(iframeRef.current.contentWindow, text);
|
||||
await new Promise((resolve) => setTimeout(resolve, 200));
|
||||
},
|
||||
[iframeRef]
|
||||
@@ -227,7 +229,7 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
}
|
||||
|
||||
console.log('[UNO] 取消选中');
|
||||
unoEscape(iframeRef.current.contentWindow);
|
||||
await unoEscape(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
}, [iframeRef]);
|
||||
|
||||
@@ -241,7 +243,7 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
}
|
||||
|
||||
console.log('[UNO] 滚动到顶部');
|
||||
unoScrollToTop(iframeRef.current.contentWindow);
|
||||
await unoScrollToTop(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}, [iframeRef]);
|
||||
|
||||
@@ -255,10 +257,102 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
}
|
||||
|
||||
console.log('[UNO] 保存文档');
|
||||
unoSave(iframeRef.current.contentWindow);
|
||||
await unoSave(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
}, [iframeRef]);
|
||||
|
||||
/**
|
||||
* 放大文档
|
||||
*/
|
||||
const zoomIn = useCallback(async () => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[UNO] 放大文档');
|
||||
await unoZoomPlus(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}, [iframeRef]);
|
||||
|
||||
/**
|
||||
* 缩小文档
|
||||
*/
|
||||
const zoomOut = useCallback(async () => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[UNO] 缩小文档');
|
||||
await unoZoomMinus(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}, [iframeRef]);
|
||||
|
||||
/**
|
||||
* 设置缩放比例
|
||||
* @param percentage - 缩放百分比 (例如:100 表示 100%)
|
||||
*/
|
||||
const setZoom = useCallback(
|
||||
async (percentage: number) => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 设置缩放比例: ${percentage}%`);
|
||||
await unoSetZoom(iframeRef.current.contentWindow, percentage);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
},
|
||||
[iframeRef]
|
||||
);
|
||||
|
||||
/**
|
||||
* 跳转到指定页面
|
||||
* @param pageNumber - 页码(从1开始)
|
||||
*/
|
||||
const gotoPage = useCallback(
|
||||
async (pageNumber: number) => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[UNO] 跳转到第 ${pageNumber} 页`);
|
||||
await unoGotoPage(iframeRef.current.contentWindow, pageNumber);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
},
|
||||
[iframeRef]
|
||||
);
|
||||
|
||||
/**
|
||||
* 跳转到第一页
|
||||
*/
|
||||
const gotoFirstPage = useCallback(async () => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[UNO] 跳转到第一页');
|
||||
await unoFirstPage(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}, [iframeRef]);
|
||||
|
||||
/**
|
||||
* 跳转到最后一页
|
||||
*/
|
||||
const gotoLastPage = useCallback(async () => {
|
||||
if (!iframeRef.current?.contentWindow) {
|
||||
console.warn('[UNO] iframe 不可用');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[UNO] 跳转到最后一页');
|
||||
await unoLastPage(iframeRef.current.contentWindow);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}, [iframeRef]);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
searchText,
|
||||
@@ -269,6 +363,12 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
escapeSelection,
|
||||
scrollToTop,
|
||||
saveDocument,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
setZoom,
|
||||
gotoPage,
|
||||
gotoFirstPage,
|
||||
gotoLastPage,
|
||||
}),
|
||||
[
|
||||
searchText,
|
||||
@@ -279,6 +379,12 @@ export function useCollaboraUnoCommands(iframeRef: RefObject<HTMLIFrameElement>)
|
||||
escapeSelection,
|
||||
scrollToTop,
|
||||
saveDocument,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
setZoom,
|
||||
gotoPage,
|
||||
gotoFirstPage,
|
||||
gotoLastPage,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,3 +35,30 @@ export interface CollaboraViewerProps {
|
||||
/** 用户名称 */
|
||||
userName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* CollaboraViewer 暴露给父组件的方法接口
|
||||
*/
|
||||
export interface CollaboraViewerHandle {
|
||||
/** UNO 命令方法集合 */
|
||||
unoCommands: {
|
||||
searchText: (text: string) => Promise<void>;
|
||||
locateText: (text: string) => Promise<void>;
|
||||
replaceText: (searchText: string, replaceText: string) => Promise<void>;
|
||||
highlightText: (text: string, color?: number) => Promise<void>;
|
||||
removeHighlight: (text: string) => Promise<void>;
|
||||
escapeSelection: () => Promise<void>;
|
||||
scrollToTop: () => Promise<void>;
|
||||
saveDocument: () => Promise<void>;
|
||||
zoomIn: () => Promise<void>;
|
||||
zoomOut: () => Promise<void>;
|
||||
setZoom: (percentage: number) => Promise<void>;
|
||||
gotoPage: (pageNumber: number) => Promise<void>;
|
||||
gotoFirstPage: () => Promise<void>;
|
||||
gotoLastPage: () => Promise<void>;
|
||||
};
|
||||
/** 文档是否已加载完成 */
|
||||
isReady: boolean;
|
||||
/** 当前模式 */
|
||||
mode: 'view' | 'edit';
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { useState, useEffect, useRef, ChangeEvent } from 'react';
|
||||
import { Document, Page, pdfjs } from 'react-pdf';
|
||||
import { DOCUMENT_URL } from '~/api/axios-client';
|
||||
import { CollaboraViewer } from '~/components/collabora/CollaboraViewer';
|
||||
import { CollaboraViewer, type CollaboraViewerHandle } from '~/components/collabora/CollaboraViewer';
|
||||
|
||||
// 设置worker路径为public目录下的worker文件
|
||||
// 使用已经下载的兼容版本 (pdfjs-dist v2.12.313)
|
||||
@@ -85,10 +85,17 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
const [zoomLevel, setZoomLevel] = useState(100);
|
||||
// const [highlightsVisible, setHighlightsVisible] = useState(true);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const collaboraViewerRef = useRef<CollaboraViewerHandle>(null);
|
||||
const [numPages, setNumPages] = useState<number | null>(null);
|
||||
const [loadError, setLoadError] = useState<string | null>(null);
|
||||
const [pageInputValue, setPageInputValue] = useState<string>('');
|
||||
|
||||
|
||||
// 获取文件类型
|
||||
const real_path = fileContent.path || fileContent.template_contract_path || '';
|
||||
const fileExtension = real_path.split('.').pop()?.toLowerCase();
|
||||
const isDocx = fileExtension === 'docx';
|
||||
const isPdf = fileExtension === 'pdf';
|
||||
|
||||
// 拖拽状态管理
|
||||
const [dragMode, setDragMode] = useState(false); // 是否处于拖拽模式
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
@@ -97,15 +104,35 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 放大文档
|
||||
const handleZoomIn = () => {
|
||||
if (zoomLevel < 200) {
|
||||
setZoomLevel(prevZoom => prevZoom + 10);
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.zoomIn();
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:修改 zoomLevel 状态
|
||||
if (zoomLevel < 200) {
|
||||
setZoomLevel(prevZoom => prevZoom + 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 缩小文档
|
||||
const handleZoomOut = () => {
|
||||
if (zoomLevel > 50) {
|
||||
setZoomLevel(prevZoom => prevZoom - 10);
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.zoomOut();
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:修改 zoomLevel 状态
|
||||
if (zoomLevel > 50) {
|
||||
setZoomLevel(prevZoom => prevZoom - 10);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -243,21 +270,37 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 处理页码跳转
|
||||
const handlePageJump = () => {
|
||||
if (!pageInputValue || !numPages) return;
|
||||
|
||||
if (!pageInputValue) return;
|
||||
|
||||
const targetPageNum = parseInt(pageInputValue, 10);
|
||||
|
||||
// 验证页码是否在有效范围内
|
||||
if (targetPageNum > 0 && targetPageNum <= numPages) {
|
||||
// 找到目标页面元素并滚动到该位置
|
||||
const pageElement = document.getElementById(`page-${targetPageNum}`);
|
||||
if (pageElement) {
|
||||
pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
if (targetPageNum > 0) {
|
||||
collaboraViewerRef.current?.unoCommands.gotoPage(targetPageNum);
|
||||
} else {
|
||||
toastService.warning('请输入有效页码');
|
||||
setPageInputValue('');
|
||||
}
|
||||
} else if (isPdf) {
|
||||
// PDF 文件:验证页码并滚动到目标页面
|
||||
if (!numPages) return;
|
||||
|
||||
if (targetPageNum > 0 && targetPageNum <= numPages) {
|
||||
// 找到目标页面元素并滚动到该位置
|
||||
const pageElement = document.getElementById(`page-${targetPageNum}`);
|
||||
if (pageElement) {
|
||||
pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
} else {
|
||||
// 页码超出范围,显示错误信息或重置输入
|
||||
toastService.warning(`请输入有效页码 (1-${numPages})`);
|
||||
setPageInputValue('');
|
||||
}
|
||||
} else {
|
||||
// 页码超出范围,显示错误信息或重置输入
|
||||
toastService.warning(`请输入有效页码 (1-${numPages})`);
|
||||
setPageInputValue('');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -285,8 +328,18 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 滚动到顶部
|
||||
const handleScrollToTop = () => {
|
||||
if (contentRef.current) {
|
||||
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
if (isDocx) {
|
||||
// DOCX 文件:调用 Collabora UNO 命令
|
||||
if (!collaboraViewerRef.current?.isReady) {
|
||||
toastService.warning('文档尚未加载完成,请稍候...');
|
||||
return;
|
||||
}
|
||||
collaboraViewerRef.current?.unoCommands.scrollToTop();
|
||||
} else {
|
||||
// PDF 文件:滚动容器到顶部
|
||||
if (contentRef.current) {
|
||||
contentRef.current.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -385,8 +438,6 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
|
||||
// 渲染文档内容
|
||||
const renderDocumentContent = () => {
|
||||
const real_path = fileContent.path || fileContent.template_contract_path || '';
|
||||
|
||||
// 如果路径无效,显示错误信息
|
||||
if (!real_path) {
|
||||
if(!fileContent.template_contract_path){
|
||||
@@ -404,9 +455,7 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
}
|
||||
|
||||
// console.log('real_path',real_path);
|
||||
// 获取文件扩展名
|
||||
const fileExtension = real_path.split('.').pop()?.toLowerCase();
|
||||
|
||||
|
||||
// PDF内容渲染
|
||||
const renderPdfContent = () => (
|
||||
<div
|
||||
@@ -470,8 +519,9 @@ export function FilePreview({ fileContent, activeReviewPointResultId, targetPage
|
||||
// DOCX文件使用Collabora Online预览
|
||||
return (
|
||||
<CollaboraViewer
|
||||
ref={collaboraViewerRef}
|
||||
fileId={real_path}
|
||||
mode="view"
|
||||
mode="edit"
|
||||
userId={userInfo?.sub || 'guest'}
|
||||
userName={userInfo?.nick_name || '访客'}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user