PostMessage API 用于在 Collabora Online 的浏览器部分被包含在一个父框架中时，与其进行交互。这对于希望将 Collabora Online 集成到自身应用中的宿主（Host）非常有用。

此 API 主要基于 **WOPI 规范**，并带有少量扩展/修改。所有发送的消息都采用以下形式：

```plain
{
    "MessageId": "",
    "SendTime": "",
    "Values": {
        "": ""
    }
}
```

`SendTime` 是浏览器 `Date.now()` 返回的时间戳。从 WOPI 宿主发送的 Post 消息也应采用相同的格式。

需要注意的是，正如 WOPI 规范中提到的，如果尚未收到 `Host_PostmessageReady` 消息，Collabora Online 框架将忽略所有来自宿主框架的 Post 消息。此外，由于将 Collabora Online 嵌入为 iframe 必须实现 WOPI，因此要求 WOPI 宿主的 `CheckFileInfo` 响应中必须包含 `PostMessageOrigin` 属性。否则，将不会发出任何 Post 消息。

---

## 初始化（Initialization）
### 编辑器（Editor）发送给 WOPI 宿主（WOPI Host）
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **App_LoadingStatus** | `Status:`（状态）   `DocumentLoadedTime:`（文档加载时间）   `Features:`（功能） | **状态 (**`Status`**)：**   - `Frame_Ready`: Collabora Online 框架已加载，可显示 UI。   - `Document_Loaded`: 文档已完全加载，宿主可以开始使用 PostMessage API。   - `Failed`: 文档加载失败，但宿主可显示 Collabora Online 框架以呈现错误。   - `Initialized`: 编辑器中的 PostMessage 监听器已初始化。WOPI 宿主可以开始发送 Post 消息（甚至在 `Frame_Ready` 之前）。      **附加键值：**   - `Features`: 此客户端的功能。支持的值包括：`VersionStates`（通知宿主客户端支持不同的版本状态）。   - `DocumentLoadedTime`: 当 Status 为 `Document_Loaded` 时可用。 |


### WOPI 宿主（WOPI Host）发送给编辑器（Editor）
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Host_PostmessageReady** | _无_ | 详情请参见 WOPI 文档。 |


---

## 查询（Query）
您可以使用 Post 消息 API 从编辑器查询数据。所有响应的 `MessageId` 都以查询消息的 `MessageId` 加上 `_Resp` 后缀返回。

### 查询消息（WOPI 宿主发送给 Editor）
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Get_Views** | _无_ | 查询编辑器中当前活跃的文档视图。响应以 `Get_Views_Resp` 形式返回。 |
| **Get_Export_Formats** | _无_ | 查询编辑器中当前打开文档支持的所有导出格式。响应以 `Get_Export_Formats_Resp` 形式返回。 |
| **Get_User_State** | _无_ | 查询编辑器中当前用户活动状态（是空闲或活跃）。响应以 `Get_User_State_Resp` 形式返回。 |


### 查询响应（Editor 发送给 WOPI Host）
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Get_Views_Resp** | `ViewId:`（视图 ID）   `UserId:`（用户 ID）   `UserName:`（用户名）   `Color:`（颜色）   `ReadOnly:`（只读）   `IsCurrentView:`（是否为当前视图） | 提供使用 `Get_Views` 查询时所有当前视图的详细信息。 |
| **Get_Export_Formats_Resp** | `Label:`（标签）   `Format:`（格式） | 对 `Get_Export_Formats` 查询的响应。   `Label` 包含解释格式的本地化字符串。   `Format` 是请求文档导出时所需的文件扩展名。 |
| **Get_User_State_Resp** | `State:`（状态）   `Elapsed:`（已逝时间） | 对 `Get_User_State` 查询的响应。   `State` 包含用户活动状态的非本地化字符串（“active”或“idle”）。   `Elapsed` 是用户上次活动以来的秒数。 |


---

## 会话管理（Session Management）
### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Action_RemoveView** | `ViewId:`（视图 ID） | 移除会话。 |
| **Reset_Access_Token** | `token:`（令牌） | 重置访问令牌。从现在起将使用新的令牌。 |


### Editor 发送给 WOPI Host
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **View_Added** | `ViewId:`   `UserId:`   `UserName:`   `Color:`   `ReadOnly:` | **已弃用 (Deprecated: true)**; 新成员已添加。   _注：此消息已弃用，请转而实现对 _`Views_List`_ 的处理，其有效载荷与 _`Get_Views_Resp`_ 相同。_ |
| **View_Removed** | `ViewId:`（视图 ID） | **已弃用 (Deprecated: true)**; `ViewId` 对应的视图已关闭文档。   _注：此消息已弃用，请转而实现对 _`Get_Views_Resp`_ 或 _`Views_List`_ 的处理。_ |
| **Session_Closed** | `Reason:`（原因） | 会话已关闭。`Reason` 字段详细说明了来源：`OwnerTermination` (所有者终止), `DocumentIdle` (文档空闲), `OOM` (内存不足), `ShuttingDown` (服务器维护关机), `DocumentDisconnected` (文档问题)。 |
| **Views_List** | _参见 Get_Views_Resp_ | 关于当前连接视图的完整信息。 |
| **User_Idle** | _无_ | 指示用户进入空闲状态。发生在配置文件 `/etc/coolwsd/coolwsd.xml` 中定义的较长非活动时间之后。 |
| **User_Active** | _无_ | 指示用户再次变为活跃状态。发生在用户点击空闲屏幕之后。 |


---

## 动作（Actions）
### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Action_Save** | `DontTerminateEdit:`（不终止编辑）   `DontSaveIfUnmodified:`（未修改不保存）   `Notify:`（通知）   `ExtendedData:`（扩展数据） | 保存文档。   - `DontTerminateEdit`: 与电子表格相关，设置 true 不会终止编辑模式。   - `DontSaveIfUnmodified`: 如果文档未修改，则阻止保存到存储。   - `Notify`: 如果为 true，则在保存文档时通知宿主（参见 `Action_Save_Resp`）。   - `ExtendedData`: 可选数据，通过 `X-COOL-WOPI-ExtendedData` 头部传递给 WOPI 宿主。 |
| **Action_SaveAs** | `Filename:`（文件名）   `Notify:`（通知） | 以给定 `Filename` 创建文档副本。 |
| **Action_FollowUser** | `Follow:`（跟随）   `ViewId:`（视图 ID） | 开启或关闭跟随用户功能。   - `Follow`: `true` 开启跟随，`false` 关闭。   - `ViewId`: 指定要跟随的用户。未定义时，跟随当前编辑器。 |
| **Action_Close** | _无_ | 关闭文档。 |
| **Close_Session** | _无_ | 允许在文档完全加载之前关闭会话。 |
| **Action_Fullscreen** | _无_ | 切换到全屏模式。 |
| **Action_FullscreenPresentation** | `StartSlideNumber:`（起始幻灯片编号）   `CurrentSlide:`（当前幻灯片） | 在 Impress 中开始演示。   - `StartSlideNumber`: 可选，指定起始幻灯片（从 0 开始）。   - `CurrentSlide`: 如果为 true，则从当前幻灯片开始演示。 |
| **Action_Print** | _无_ | 打印文档。 |
| **Action_Export** | `Format:`（格式）   `Notify:`（通知） | 以下载指定 `Format` 的文档（`Format` 必须来自 `Get_Export_Formats` 列表）。 |
| **Action_InsertGraphic** | `url:` | 从 URL 下载图像并将其插入到文档中。通常是对 `UI_InsertGraphic` 的响应。 |
| **Action_InsertLink** | `url:` | 在文档中插入链接。通常是对 `UI_PickLink` 的响应。 |
| **Action_InsertMultimedia** | `url:` | _24.04.10 版本新增。_ 从 URL 下载多媒体并插入。可能是对 `UI_InsertFile` 的响应。 |
| **Action_ShowBusy** | `Label:`（标签） | 显示一个进行中的覆盖层，带有给定的 `Label`。 |
| **Action_HideBusy** | _无_ | 隐藏任何进行中的覆盖层。 |
| **Action_ChangeUIMode** | `Mode:`（模式） | 更改用户界面：`'classic'` (经典工具栏) 或 `'notebookbar'` (笔记本栏)。 |
| **Action_Paste** | `Mimetype:`（MIME 类型）   `Data:`（数据） | 将数据直接粘贴到文档中，绕过内部粘贴机制。   示例：`{Mimetype: "text/plain;charset=utf-8", Data: "foo"}`。 |


### Editor 发送给 WOPI 宿主（响应）
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Action_Load_Resp** | `success:`（成功）   `result:`（结果）   `errorMsg:`（错误消息）   `errorType:`（错误类型） | 加载完成时的确认。   - `success`: COOL 是否成功加载文档。   - `result`: 文档未加载的原因。   - `errorMsg`: 详细的错误消息。   - `errorType`: 可选的错误标识符。 |
| **Action_Save_Resp** | `success:`（成功）   `result:`（结果）   `errorMsg:`（错误消息）   `fileName:`（文件名） | 保存完成时的确认。仅当 `Action_Save` 包含 `Notify` 参数时发出。   - `result`: 文档未保存的原因（例如，'unmodified'）。   - `fileName`: 如果成功为 true，则包含保存的文件名。 |
| **FollowUser_Changed** | `FollowedViewId:`（被跟随视图 ID）   `IsFollowUser:`（是否跟随用户）   `IsFollowEditor:`（是否跟随编辑器） | 当前跟随状态的通知。 |
| **Action_ChangeUIMode_Resp** | `Mode:`（模式） | 关于 UI 模式切换（标签式/紧凑式）的通知。 |


---

## 版本恢复（Version Restore）
### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Host_VersionRestore** | `Status:`（状态） | 唯一可能的值是 `Pre_Restore`。在实际恢复文档之前发送，以便 Online 可以在恢复前保存任何未保存的更改。 |


### Editor 发送给 WOPI Host
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **App_VersionRestore** | `Status:`（状态） | 对 `Host_VersionRestore` 消息的回复。可能的值（目前）是：`Pre_Restore_Ack`。意味着宿主可以继续将文档恢复到较早的版本。 |


> **注意：** 仅当 `App_LoadingStatus` 中的 `Features` 包含 `VersionStates` 时，才会发出这些消息。否则，宿主可以立即将版本恢复到较早的修订。
>

---

## 杂项（Miscellaneous）
### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Insert_Button** | `id:`（ID）   `imgurl:`（图像 URL）   `hint:`（提示）   `accessKey:`（访问键）   `mobile:`（移动端）   `tablet:`（平板端）   `label:`（标签）   `insertBefore:`（插入到之前）   `unoCommand:`（UNO 命令） | 在顶部工具栏插入一个按钮。如果未设置 `unoCommand`，则在点击时响应 `Clicked_Button` Post 消息事件。 |
| **Insert_ContextualButton** | `id:`   `imgurl:`   `hint:`   `unoCommand:` | _25.04.5.3 版本新增。_ 在上下文工具栏（选中时出现）中插入按钮。如果未设置 `unoCommand`，则在点击时响应 `Clicked_ContextualButton`。 |
| **Hide_Button** | `id:`（ID） | 从工具栏隐藏按钮。 |
| **Show_Button** | `id:`（ID） | 在工具栏显示按钮。 |
| **Remove_Button** | `id:`（ID） | 从工具栏移除按钮。 |
| **Hide_Command** | `id:`（ID） | 隐藏某个命令的 UI（包括菜单项、上下文菜单项和工具栏按钮）。 |
| **Show_Command** | `id:`（ID） | 显示某个命令的 UI。 |
| **Hide_NotebookTab** | `id:`（ID） | _24.04.11.1 版本新增。_ 永久隐藏特定的笔记本栏选项卡。 |
| **Show_NotebookTab** | `id:`（ID） | _24.04.11.1 版本新增。_ 显示特定的笔记本栏选项卡。 |
| **Collapse_Notebookbar** | _无_ | 隐藏笔记本栏按钮。 |
| **Extend_Notebookbar** | _无_ | 显示笔记本栏按钮。 |
| **Hide_StatusBar** | _无_ | 隐藏状态栏。 |
| **Show_StatusBar** | _无_ | 显示状态栏。 |
| **Remove_Statusbar_Element** | `id:`（ID） | 从状态栏移除元素。 |
| **Hide_Menubar** | _无_ | 隐藏菜单栏。 |
| **Show_Menubar** | _无_ | 显示菜单栏。 |
| **Grab_Focus** | _无_ | 将焦点恢复到应用程序。 |
| **Hide_Ruler** | _无_ | 隐藏水平文档标尺（仅限 Writer）。 |
| **Show_Ruler** | _无_ | 显示水平文档标尺（仅限 Writer）。 |
| **Hide_Menu_Item** | `id:`（ID） | 隐藏菜单项。`id` 在 `browser/src/control/Control.Menubar.js` 中定义。 |
| **Show_Menu_Item** | `id:`（ID） | 显示菜单项。 |
| **Show_Sidebar** | `id:`（ID） | _24.04.10 版本新增。_ 显示侧边栏。可选 `id`：`Navigator`, `ModifyPage`, `SlideChangeWindow`, `CustomAnimation`, `MasterSlidesPanel`。 |
| **Hide_Sidebar** | _无_ | _24.04.10 版本新增。_ 隐藏侧边栏。 |
| **Disable_Default_UIAction** | `action:`（动作）   `disable:`（禁用） | 禁用 UI 命令的默认处理程序和动作（例如 `UI_Save`、`UI_Close`）。当 `disable` 为 true 时，仅发出 Post 消息。 |
| **Send_UNO_Command** | `Command:`（命令）   `Args:`（参数） | 向编辑器发送 UNO 命令。 |
| **Error_Messages** | `list:`（列表） | 用于覆盖编辑器中错误消息的对象列表（`{type: , msg: }`）。 |
| **Hint_OnscreenKeyboard** | _无_ | 指示设备使用屏幕键盘（例如平板）。 |
| **Hint_NoOnscreenKeyboard** | _无_ | 指示设备不是平板。 |


#### 查找工具栏按钮 ID
工具栏按钮 ID 在以下文件中的 `getToolItems`/`create` 函数中定义：

+ `Control.TopToolbar.js` (桌面/平板顶部工具栏)
+ `Control.MobileTopBar.ts` (智能手机顶部工具栏)
+ `Control.MobileBottomBar.js` (智能手机底部工具栏)
+ `Control.StatusBar.js` (桌面状态栏)

#### 查找状态栏元素 ID
状态栏按钮 ID 在 `Control.StatusBar.js` 中的 `onDocLayerInit` 函数中定义。

### Editor 发送给 WOPI Host
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Clicked_Button** | `id:`（ID） | 点击通过 `Insert_Button` 添加的自定义按钮时发出。 |
| **Clicked_ContextualButton** | `id:`（ID） | 点击通过 `Insert_ContextualButton` 添加的自定义按钮时发出。 |
| **Download_As** | `Type:`（类型）   `URL:` | 当用户选择 'Print'、'Show slideshow' 或 'Download As...' 且 CheckFileInfo 中的 `DownloadAsPostMessage` 为 true 时发出。`Type` 值: `'print'`, `'slideshow'`, `'export'`。 |
| **UI_OpenDocument** | _无_ | 请求 WOPI 宿主打开一个弹出窗口，用户可在其中选择要查看和编辑的另一个文档。 |
| **UI_CreateFile** | `DocumentType:`（文档类型） | 请求 WOPI 宿主打开一个新浏览器标签并创建新文档。`DocumentType` 可以是 `'text'`, `'spreadsheet'`, `'presentation'` 或 `'drawing'`。 |
| **UI_SaveAs** | `Args: {format: ''}`（参数） | 请求 WOPI 宿主创建相应的 UI，供用户选择路径和文件名以创建当前文件的副本。对该查询的响应通过 `Action_SaveAs` 消息发送。 |
| **UI_InsertGraphic** | _无_ | 请求 WOPI 宿主打开弹出窗口供用户选择图像插入。成功后，WOPI 宿主将发送 `Action_InsertGraphic` Post 消息。 |
| **UI_PickLink** | _无_ | 请求 WOPI 宿主打开弹出窗口供用户选择链接插入。成功后，WOPI 宿主将发送 `Action_InsertLink` Post 消息。 |
| **UI_InsertFile** | `callback:`（回调）   `mimeTypeFilter:`（MIME 类型过滤器） | _24.04.10 版本新增。_ 请求 WOPI 宿主打开弹出窗口供用户选择文件插入。成功后，WOPI 宿主将发送 `callback` 参数中定义的 Post 消息。 |
| **UI_InsertAIContent** | _无_ | _24.04.12 版本新增。_ 请求 WOPI 宿主打开弹出窗口供用户选择插入 AI 生成的内容。 |
| **UI_Cancel_Password** | _无_ | 通知 WOPI 宿主用户在打开受密码保护的文件时点击了“取消”。 |
| **UI_Hyperlink** | _无_ | 通知 WOPI 宿主用户点击了超链接并确认要离开文档以跟随该超链接。 |
| **UI_Paste** | _无_ | 在移动端请求粘贴时发送。允许嵌入的移动应用程序处理剪贴板内容。 |
| **Doc_ModifiedStatus** | `Values.Modified`（已修改值） | 通知以更新文档的修改状态。`Values.Modified` 为 true 表示自上次保存以来已修改，否则为 false。 |


---

## 调用 Python 脚本（Calling Python scripts）
### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **CallPythonScript** | `ScriptFile:`（脚本文件）   `Function:`（函数）   `Values:`（值） | 调用 Python 脚本。`Values` 包含传递给脚本的命名参数对象。 |


### Editor 发送给 WOPI Host
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **CallPythonScript-Result** | `commandName:`（命令名称）   `Values:`（值） | 返回结果。`commandName` 中是调用脚本的 URL。 |


---

## 提及功能（Mentions）
_注意：目前提及功能仅在 Writer 中可用。_

### Editor 发送给 WOPI Host
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **UI_Mention** | `type: autocomplete`（类型: 自动完成）   `text:`（文本） | 当用户输入“@”时，Collabora Online 会发送此 Post 消息，附带部分文本，以获取集成商提供的用户名列表。 |
| **UI_Mention** | `type: selected`（类型: 已选择）   `username:`（用户名） | 当用户从集成商提供的列表中选择一个用户名时触发此消息。 |


### WOPI 宿主发送给 Editor
| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Action_Mention** | `list:`（列表） | 集成商应发送此消息作为对 `UI_Mention` (自动完成类型) 消息的响应。消息必须包含用户对象列表：   `{ username: "...", profile: "...", label: "..." }` |


---

## 嵌入 Iframe（Embedding Iframe）
### Editor 发送给 WOPI Host
Collabora Online 发送 `Iframe_Height` Post 消息给 WOPI 宿主，以动态调整嵌入式 iframe 的高度并防止出现滚动条。

| MessageId | Values（值） | Description（描述） |
| :--- | :--- | :--- |
| **Iframe_Height** | `ContentHeight:`（内容高度） | 使用 `ContentHeight` 值在 UI 中动态设置嵌入式 iframe 的高度。 |


