/** * Collabora 文档保存功能模块 * * 使用 PostMessage 协议实现文档保存,支持保存参数配置和状态监听 * * @encoding UTF-8 */ /** * 保存选项接口 */ export interface SaveOptions { /** * 保存后不关闭编辑模式 * @default false */ dontTerminateEdit?: boolean; /** * 如果文档未修改则不保存 * @default false */ dontSaveIfUnmodified?: boolean; /** * 是否显示保存通知 * @default true */ notify?: boolean; /** * 扩展数据(可选) */ extendedData?: string; } /** * 保存响应接口 */ export interface SaveResponse { /** * 是否保存成功 */ success: boolean; /** * 结果代码(失败时提供) */ result?: string; /** * 错误消息(失败时提供) */ errorMsg?: string; /** * 保存时间戳 */ timestamp: number; } /** * Collabora PostMessage 数据类型 */ interface CollaboraMessageData { MessageId?: string; msgId?: string; Values?: { success?: boolean; result?: string; errorMsg?: string; [key: string]: unknown; }; args?: { success?: boolean; result?: string; errorMsg?: string; [key: string]: unknown; }; [key: string]: unknown; } /** * 解析 PostMessage 数据 * @param data - PostMessage 原始数据 * @returns 解析后的消息对象 */ function parseMessageData(data: unknown): CollaboraMessageData { if (typeof data === 'string') { return JSON.parse(data) as CollaboraMessageData; } return data as CollaboraMessageData; } /** * 保存文档 * * 使用 PostMessage 协议发送 Action_Save 命令,并监听 Action_Save_Resp 响应。 * 支持自定义保存参数,如保存后是否关闭编辑、是否显示通知等。 * * @param iframeWindow - Collabora iframe 的 contentWindow * @param options - 保存选项(可选) * @returns Promise,解析为保存响应信息 * * @example * ```typescript * // 基本保存 * const result = await saveDocument(iframeWindow); * if (result.success) { * console.log('保存成功'); * } * * // 带参数保存 * const result = await saveDocument(iframeWindow, { * dontTerminateEdit: true, // 保存后不关闭编辑 * dontSaveIfUnmodified: true, // 未修改则不保存 * notify: true // 显示通知 * }); * ``` */ export async function saveDocument( iframeWindow: Window, options?: SaveOptions ): Promise { return new Promise((resolve, reject) => { // 超时设置(10秒,保存操作可能需要较长时间) const timeout = setTimeout(() => { cleanup(); reject(new Error('保存操作超时')); }, 10000); /** * 消息监听器 */ const handleMessage = (event: MessageEvent) => { try { // 验证消息来源 if (event.source !== iframeWindow) { return; } // 解析消息数据 const data = parseMessageData(event.data); // 监听 Action_Save_Resp 响应 // bundle.js 中的响应格式: { MessageId: 'Action_Save_Resp', args: { success, result, errorMsg } } if (data.MessageId === 'Action_Save_Resp' || data.msgId === 'Action_Save_Resp') { clearTimeout(timeout); cleanup(); // 获取响应数据(可能在 Values 或 args 中) const responseData = data.Values || data.args || {}; const success = responseData.success === true; if (success) { // 保存成功 const response: SaveResponse = { success: true, timestamp: Date.now(), }; resolve(response); } else { // 保存失败 const response: SaveResponse = { success: false, result: responseData.result as string | undefined, errorMsg: responseData.errorMsg as string | undefined, timestamp: Date.now(), }; resolve(response); } } } catch (error) { clearTimeout(timeout); cleanup(); reject(error); } }; /** * 清理函数 */ const cleanup = () => { window.removeEventListener('message', handleMessage); }; // 注册消息监听器 window.addEventListener('message', handleMessage); // 构建保存请求消息 const message = { MessageId: 'Action_Save', SendTime: Date.now(), Values: { DontTerminateEdit: options?.dontTerminateEdit || false, DontSaveIfUnmodified: options?.dontSaveIfUnmodified || false, Notify: options?.notify !== false, // 默认显示通知 ExtendedData: options?.extendedData || '', }, }; console.log('[DocumentSave] 发送保存命令:', message); // 发送保存请求 iframeWindow.postMessage(JSON.stringify(message), '*'); }); }