/** * Collabora 页数信息获取模块 * * @encoding UTF-8 */ /** * 页数信息接口 */ export interface PageInfo { totalPages: number; currentPage: number; timestamp: number; } /** * Collabora PostMessage 数据类型 */ interface CollaboraMessageData { MessageId?: string; msgId?: string; // bundle.js _postMessage 发送的格式 Values?: { Command?: string; Status?: string; totalPages?: number; currentPage?: number; timestamp?: number; pages?: number; [key: string]: unknown; }; // 原始插件返回的格式 args?: { Command?: string; Status?: string; totalPages?: number; currentPage?: number; timestamp?: number; [key: string]: unknown; }; [key: string]: unknown; } /** * 解析 PostMessage 数据 */ function parseMessageData(data: unknown): CollaboraMessageData { if (typeof data === 'string') { return JSON.parse(data) as CollaboraMessageData; } return data as CollaboraMessageData; } /** * 通过 PostMessage 请求页数信息 * * 使用自定义 custompostMessage 插件获取文档页数。 * 注意: Collabora 的页码是从 0 开始的。 * * @param iframeWindow - iframe 的 contentWindow * @returns Promise,解析为页数信息 * * @example * ```typescript * const info = await requestPageInfo(iframeWindow); * console.log(`文档共 ${info.totalPages} 页,当前在第 ${info.currentPage + 1} 页`); * ``` */ export async function requestPageInfo(iframeWindow: Window): Promise { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { cleanup(); reject(new Error('请求页数信息超时')); }, 5000); const handleMessage = (event: MessageEvent) => { try { if (event.source !== iframeWindow) { return; } const data = parseMessageData(event.data); // bundle.js 的 _postMessage 会将消息转换为: // { MessageId: 'custompostMessage_Resp', Values: { Command: 'GET_PAGE_INFO', ... } } // 所以我们需要监听 MessageId 而不是 msgId if ( data.MessageId === 'custompostMessage_Resp' && data.Values?.Command === 'GET_PAGE_INFO' && data.Values?.Status === 'success' ) { clearTimeout(timeout); cleanup(); const info: PageInfo = { totalPages: data.Values.totalPages || 0, currentPage: data.Values.currentPage || 0, timestamp: data.Values.timestamp || Date.now(), }; resolve(info); } } catch (error) { clearTimeout(timeout); cleanup(); reject(error); } }; const cleanup = () => { window.removeEventListener('message', handleMessage); }; window.addEventListener('message', handleMessage); // 发送请求消息 const message = { MessageId: 'custompostMessage', Values: { Command: 'GET_PAGE_INFO', Args: {}, }, }; iframeWindow.postMessage(JSON.stringify(message), '*'); }); }