文件操作
打开、保存、导入导出图纸的完整指南。
概览
| 操作 | 命令方式 | API 方式 |
|---|---|---|
| 从服务端打开 | OPENFROMSERVER |
DrawingManagerService.openDrawing() |
| 保存到服务端 | SAVESERVER |
DrawingManagerService.saveDrawing() |
| 从本地缓存打开 | OPENFROMLOCAL |
localService.loadDrawingById() |
| 保存到本地缓存 | SAVELOCAL |
localService.saveDrawing() |
| 导入 DWG | IMPORTDWG |
service.uploadMap() + openDrawing() |
| 导出 DWG | EXPORTDWG |
drawingManager.exportToDwg() |
| 快速保存 | QSAVE |
下载 WASM 压缩的 .vcad 文件(含 _meta.serverSource) |
| 另存为 | SAVEAS |
下载 .vcad 文件(OPEN 同时接受 .vcad/.webcad;手工 JSON.stringify(toDb()) 得到的是未压缩 .webcad,不等价于 QSAVE) |
命令方式(简单场景)
const { Engine } = vjcad;
await Engine.editor.executerWithOp('OPENFROMSERVER'); // 从服务端打开
await Engine.editor.executerWithOp('SAVESERVER'); // 保存到服务端
await Engine.editor.executerWithOp('OPENFROMLOCAL'); // 从本地缓存打开
await Engine.editor.executerWithOp('SAVELOCAL'); // 保存到本地缓存
await Engine.editor.executerWithOp('IMPORTDWG'); // 导入 DWG
await Engine.editor.executerWithOp('EXPORTDWG'); // 导出 DWG
await Engine.editor.executerWithOp('QSAVE'); // 快速保存
await Engine.editor.executerWithOp('SAVEAS'); // 另存为
服务端文件操作 API
从服务端打开图纸
const { DrawingManagerService, Engine } = vjcad;
const drawingManager = new DrawingManagerService();
const openResult = await drawingManager.openDrawing({
type: 'imports', // 'imports' | 'designs'
mapid: 'drawing-123',
version: 'v1',
branch: 'main',
patchId: 'base', // 可选,不传则使用最新
readOnly: false
});
if (openResult.success) {
const virtualFile = new File(
[openResult.webcadJson], 'drawing.webcad',
{ type: 'application/json' }
);
await Engine.view.openDbDoc(virtualFile, openResult.webcadData);
// 保存来源信息(用于后续保存)
Engine.currentDoc.serverSource = {
type: 'imports',
mapid: 'drawing-123',
version: 'v1',
branchName: 'main',
lastPatchId: openResult.latestPatchId || 'base'
};
await Engine.currentDoc.setOriginalJson(openResult.webcadJson);
}
保存到服务端
const currentDoc = Engine.currentDoc;
const currentJson = JSON.stringify(currentDoc.toDb());
const originalJson = await currentDoc.getOriginalJson();
const src = currentDoc.serverSource;
const saveResult = await drawingManager.saveDrawing({
type: src.type,
mapid: src.mapid,
version: src.version,
branchName: src.branchName,
originalJson: originalJson,
currentJson: currentJson,
parentId: src.lastPatchId,
drawingName: '我的图纸',
author: '作者名',
remark: '修改说明'
});
if (saveResult.status && saveResult.patchId !== 'no_change') { // 无变化时 patchId 为 'no_change',什么都不更新
await currentDoc.setOriginalJson(currentJson);
currentDoc.serverSource.lastPatchId = saveResult.patchId;
}
// 另需处理:saveResult.idMapping(服务端给新增实体重分配 id,须先更新本地实体 id 再存基准)、
// !saveResult.status && saveResult.conflict?.hasConflict(按 conflictingEntities 处理后带 conflictResolution 重存)。
// 推荐直接用 SAVESERVER 命令,详见 file/server.md
本地缓存操作 API
const { getLocalStorageService, Engine } = vjcad;
const localService = getLocalStorageService();
// 保存(serverSource 必填;新图先补 { type: 'designs', designPath: 'local/xxx' },否则抛错返回 success:false)
if (!Engine.currentDoc.serverSource) {
Engine.currentDoc.serverSource = { type: 'designs', designPath: 'local/我的图纸' };
}
const saveResult = await localService.saveDrawing({
serverSource: Engine.currentDoc.serverSource,
webcadJson: JSON.stringify(Engine.currentDoc.toDb()),
drawingName: '我的图纸'
});
// 列表
const drawings = await localService.listDrawings();
// 加载(打开后恢复 serverSource 时要带上 record.originalJsonCompressed,
// 且 record.type === 'tiles' 改回 'imports',否则之后 SAVESERVER 无基准、不做增量 diff)
const loadResult = await localService.loadDrawingById(drawingId);
// 删除
await localService.deleteDrawingById(drawingId);
// 统计
const stats = await localService.getStats();
导入 DWG/DXF
const { DrawingManagerService, MapOpenWay, openMapDarkStyle, Engine } = vjcad;
const input = document.createElement('input');
input.type = 'file';
input.accept = '.dwg,.dxf';
input.onchange = async (e) => {
const file = e.target.files[0];
if (!file) return;
const drawingManager = new DrawingManagerService();
const service = drawingManager.getService();
// 上传文件
const uploadResult = await service.uploadMap(file);
if (uploadResult.error) return;
// 解析 DWG
const mapid = file.name.replace(/\.(dwg|dxf)$/i, '') + '_' + Date.now();
const openResult = await service.openMap({
mapid, fileid: uploadResult.fileid,
uploadname: file.name,
mapopenway: MapOpenWay.Memory,
style: openMapDarkStyle()
}, true);
if (openResult.error) return;
// 获取数据并加载
const drawingResult = await drawingManager.openDrawing({
type: 'imports',
mapid: openResult.mapid,
version: openResult.version,
branch: 'main'
});
if (drawingResult.success) {
const virtualFile = new File(
[drawingResult.webcadJson], 'drawing.webcad',
{ type: 'application/json' }
);
await Engine.view.openDbDoc(virtualFile, drawingResult.webcadData);
}
};
input.click();
导出 DWG
const { DrawingManagerService, Engine } = vjcad;
const drawingManager = new DrawingManagerService();
const service = drawingManager.getService();
const webcadJson = JSON.stringify(Engine.currentDoc.toDb());
const exportResult = await drawingManager.exportToDwg({
type: 'imports',
webcadJson: webcadJson,
mapid: '你的图ID',
version: '图纸版本'
});
// 实际返回 { status: true, path, filename, entityCount } 或 { status: false, error }
// 只返回服务端文件名/路径,不含二进制(没有 success / data 字段;d.ts 里的 downloadUrl 从不赋值)
if (exportResult.status) {
console.log('已导出:', exportResult.filename, exportResult.path, '实体数:', exportResult.entityCount);
// 下载需按服务端路径拼 URL(参考 EXPORTDWG 命令):
// `${SystemConstants.SERVICE_ROOT_URL}<下载目录>/${exportResult.filename}?token=${SystemConstants.ACCESS_TOKEN}`
} else {
console.error('导出失败:', exportResult.error);
}
新建文档
Engine.view.newDocument();
Engine.currentDoc.name = '新图纸';
增量保存说明
WebCAD 使用增量保存机制:
- 原始数据 — 通过
setOriginalJson()保存的基准数据 - 当前数据 — 通过
toDb()获取的当前文档数据 - Diff 计算 — 前端用 WASM
createWebcadDiff比较差异,只上传 patch;缺少原始数据时整图上传(不带parentId,失去冲突检测) - Patch 链 — 每次保存生成 Patch,形成版本历史
| 图纸类型 | 说明 |
|---|---|
imports |
已导入的 DWG 图纸,支持增量 patch |
designs |
从零创建的设计图 |