/** * Collabora Online 文档查看器组件 * * 功能: * - 加载 Collabora Online iframe * - 管理文档加载状态 * - 提供 UNO 命令接口 * - 支持只读和编辑模式 * * @encoding UTF-8 */ 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 const CollaboraViewer = forwardRef( function CollaboraViewer( { fileId, mode = 'view', userId = 'guest', userName = '访客', }, ref ) { const iframeRef = useRef(null); // 调试面板状态 const [unoCmd, setUnoCmd] = useState('.uno:GoToStartOfDoc'); const [unoArgs, setUnoArgs] = useState('{}'); const [unoResult, setUnoResult] = useState(null); // 1. 加载 Collabora 配置 const { config, loading, error } = useCollaboraConfig(fileId, mode, userId, userName); // 2. 监听文档加载状态 const { isDocumentLoaded } = useDocumentReady(iframeRef); // 3. UNO 命令封装 const unoCommands = useCollaboraUnoCommands(iframeRef); // 4. 暴露接口给父组件 useImperativeHandle(ref, () => ({ unoCommands, isReady: isDocumentLoaded, mode, getIframeWindow: () => iframeRef.current?.contentWindow || null, }), [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) { return (

加载文档配置中...

); } // 错误状态 if (error || !config) { return (

{error || '加载配置失败'}

请刷新页面重试或联系管理员

); } // 发送 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; } } } }; return (
{/* UNO 命令测试面板 */} {/*
setUnoCmd(e.target.value)} placeholder="UNO 命令" aria-label="UNO 命令" /> setUnoArgs(e.target.value)} placeholder="UNO Args (JSON)" aria-label="UNO Args (JSON)" /> {unoResult && {unoResult}}
*/} {/* 文档加载提示 */} {!isDocumentLoaded && (

正在加载文档...

{config.fileName}

)} {/* Collabora iframe */}