> **本文回答**：本地缓存走 `getLocalStorageService()` （IndexedDB）。保存 = `localService.saveDrawing({serverSource, webcadJson, ...})`；打开 = `listDrawings() → loadDrawingById(id) → openDbDoc()`。本地缓存压缩存储，支持离线编辑，重新联网时按 `serverSource` 同步回服务端。

## 一、获取服务

```js
import { getLocalStorageService } from 'vjcad';

const localService = getLocalStorageService();
```

MCP 参考：`vjcad/doc/file/file-operations.md`、`vjcad/example/file/02openfromlocal.js`、`04savelocal.js`。

## 二、保存到本地

```js
const currentJson = JSON.stringify(Engine.currentDoc.toDb());

// serverSource 必填（缓存 key 由 serverSource.type 等拼出）；空白新图没有它会抛错→返回 success:false
// 内置 SAVELOCAL 的做法：先补一个临时 designs 来源
if (!Engine.currentDoc.serverSource) {
  Engine.currentDoc.serverSource = { type: 'designs', designPath: 'local/' + (Engine.currentDoc.name || Date.now()) };
}

const result = await localService.saveDrawing({
  serverSource: Engine.currentDoc.serverSource,   // 关联到原服务端
  webcadJson: currentJson,
  serviceUrl: 'https://api.example.com',
  drawingName: '我的图纸'
});

if (result.success) {
  console.log('已保存! ID:', result.id);
}
```

MCP 参考：`vjcad/doc/file/file-operations.md`、`vjcad/example/file/04savelocal.js`。

## 三、列出 / 加载

```js
const drawings = await localService.listDrawings();   // 全部本地图纸
const drawing  = await localService.loadDrawingById(drawingId);

if (drawing.success) {
  // openDbDoc(file, data, isReadOnly?)：第二参是解析后的 webcad 数据对象
  const webcadData = JSON.parse(drawing.webcadJson);
  const file = new File(
    [drawing.webcadJson],
    'local.webcad',
    { type: 'application/json' }
  );
  await Engine.view.openDbDoc(file, webcadData);

  const rec = drawing.record;
  Engine.currentDoc.serverSource = {
    type: rec.type === 'tiles' ? 'imports' : rec.type,   // 瓦片模式存为 'tiles'，恢复时改回 'imports'
    mapid: rec.mapid,
    version: rec.version,
    designPath: rec.designPath,
    branchName: rec.branchName || 'main',
    originalJsonCompressed: rec.originalJsonCompressed,  // 必带：否则之后 SAVESERVER 无基准、不做增量 diff
    lastPatchId: rec.lastPatchId
  };
}
```

MCP 参考：`vjcad/doc/file/file-operations.md`、`vjcad/example/file/02openfromlocal.js`。

## 四、`LocalStorageService` API 表

| 方法 | 说明 |
|---|---|
| `saveDrawing(params)` | 保存图纸到本地 |
| `loadDrawing(key)` | 按 key 加载 |
| `loadDrawingById(id)` | 按 ID 加载 |
| `listDrawings(type?)` | 列出全部 |
| `deleteDrawing(key)` / `deleteDrawingById(id)` | 删除 |
| `clearAll()` | 清空 |
| `getStats()` | 缓存统计 |
| `exists(key)` | 是否存在 |

MCP 参考：`vjcad/doc/file/file-operations.md`。

## 五、命令版

```js
await Engine.editor.executerWithOp('SAVELOCAL');
await Engine.editor.executerWithOp('OPENFROMLOCAL');
```

## 六、本地缓存特点

- **IndexedDB**：容量大，可存储大型图纸（数十 MB）
- **离线访问**：无网络也能编辑
- **保留 serverSource**：联网后可同步回服务端
- **自动压缩**：使用 vcad 格式压缩，节省空间

MCP 参考：`vjcad/doc/file/file-operations.md`。

## 反例

- 拿 `localStorage` 而不是 IndexedDB：容量上限太小（5MB 左右），存不下图纸。
- 新图没设 `serverSource` 就调 `saveDrawing`：读 `serverSource.type` 抛错，返回 `success: false`（`SAVELOCAL` 命令会自动补 `{type:'designs', designPath:'local/<名>'}`）。
- 从本地恢复时 `serverSource` 漏了 `originalJsonCompressed`（或没把 `'tiles'` 改回 `'imports'`）：之后 `SAVESERVER` 没有基准，走整图保存、失去增量 diff 与冲突检测。
- `clearAll()` 当 "退出登录" 用：会清掉所有用户的离线图纸。

## 参考（官方文档 MCP）

- 文档：`vjcad/doc/file/file-operations.md`
- 示例：`vjcad/example/file/02openfromlocal.js`、`04savelocal.js`
