# 保存与打开文档

先保存 JSON，再加入校验、异步状态和 DOCX 文件转换。

编辑器负责修改内容，应用负责把内容保存到哪里。本章先实现产品自己的 JSON 备份，再解释打开文件时的校验，以及 DOCX 与备份的区别。

## 1. 在保存按钮中读取内容

```ts [保存时读取 JSON]
const content = editor.getJSON()
```

返回值包含节点、属性和文字格式。你可以把它交给数据库、接口或浏览器存储。保存时另外记录版本和模型名，例如 `version: 1`、`model: 'generic-v1'`，以后才能识别需要迁移的旧文件。

完整示例的 `files/repository.ts` 把备份写到 `localStorage`。这是浏览器本地存储，适合演示或本地草稿；跨设备同步需要你自己的服务端。

## 2. 保存成功时确认保存的是哪一版

用户可能在等待保存时继续输入。开始保存时记录当时的文档，只有当前内容仍是这一版，才能清除“有未保存修改”的提示。

保存失败时保留正文和未保存状态，显示错误以便重试。浏览器存储也可能因空间不足而失败，因此必须等实际写入成功后再显示成功。

`session.ts` 负责协调这些状态，正文仍由 Editor 保存，不需要另外复制成一份可编辑的 Vue 数据。

## 3. 先校验，再恢复

收到文件后先检查备份版本和模型，再用当前 Schema 检查节点、标记、属性和子内容。全部通过后，再替换编辑器中的文档：

```ts [恢复已验证的完整文档]
editor.commands.replaceDocument(content)
```

`replaceDocument()` 用于完整文件恢复，也会恢复文档顶层属性；普通正文替换可以使用 `setContent()`。检查失败时保留原文件和当前草稿，避免把不认识的节点丢掉以后又覆盖备份。

完整验证实现位于 `files/backup.ts`。打开文件前，示例会要求先保存当前修改。

## 4. 避免迟到的加载覆盖新编辑

读取文件和格式转换可能是异步的。等结果返回时，用户可能已经打开别的文档、继续输入、切换到只读，或离开页面。

提交前检查当前实例、这次加载任务以及文档是否仍与开始时一致。失效的结果不再提交。示例的 `session.ts` 在一个地方处理这些检查，避免每个文件按钮各自遗漏一种情况。

## 5. 接入 DOCX

JSON 备份保存你的产品模型；DOCX 是另一种文件格式，需要对应的转换规则。Word 工作区通过 `@quirekit/classic-docx/docx` 的公开入口按需加载转换能力，`files/docx.ts` 负责字节和转换结果，`session.ts` 负责决定是否提交。

自建工作区可以复用这些转换入口；使用 Classic 产品时，可直接安装 `createClassicWordDocxPlugin()`，通过 `instance.importDocument()` 和 `exportDocument()` 调用文件服务。

转换可能产生不支持内容的诊断，界面应保留并展示它。图片还需要媒体存储，不能只保存 JSON 中的引用就认为图片文件也已经保存。

完整文件按用途收在[工程参考](/build/reference)。下一章说明[图片、字体与其他产品能力](/build/resources)。
