version / 版本管理总览
文档:
vjcad/doc/version/index.md、vjcad/doc/version/versioning.md、vjcad/doc/version/user-auth.md示例:vjcad/example/version/01createbranch.js~06userauthcallback.js
1. 是什么
vjcad 的服务端版本管理是一个 Git 风格 + DWG 语义 的版本系统:
- 每张图纸是一棵 分支树(main / dev / release / feature-xxx)
- 每次保存生成一个 patch(补丁),存储 diff 而非完整图纸
- 分支可以 merge,冲突时返回结构化冲突信息,前端可弹框解决
- 支持 删除补丁 / 删除分支;main 分支不可删(服务端硬性拒绝)
2. 整体心智图
flowchart LR
subgraph base[base 版本]
B[初始图纸]
end
subgraph main
B --> P1[patch1]
P1 --> P2[patch2]
end
subgraph dev
P1 --> D1[patch dev1]
D1 --> D2[patch dev2]
end
subgraph feat
P2 --> F1[patch feat1]
end
D2 -. merge .-> P2
- base:分支链的起点。main 及从
main@base建的分支共用图纸原始base.vcad;从其它分支或其它补丁分叉的分支,base 是创建时生成的分叉点快照(branchBase.vcad) - patch:前端 WASM(
createWebcadDiff)在originalJson↔currentJson之间算出的 RFC 6902 JSON Patch([{op, path, value}]数组),只上传 patch,不是{added/modified/erased}结构;补丁 id 形如p1、p2 - branch:一条线性 patch 链
- merge:服务端计算"共同祖先 → 源分支最新"的整体 diff,作为 一个新 patch 追加到目标分支末尾(不是逐个重放源分支补丁)
3. 核心 API(DrawingManagerService)
const drawingManager = new DrawingManagerService();
// 分支(listBranches 收对象参数;IBranchInfo.name 是分支名)
await drawingManager.listBranches({ type: 'imports', mapid, version });
await drawingManager.createBranch({
type: 'imports', mapid, version, // type 必填
branchName, sourceBranch, sourcePatchId // 注意:sourceBranch/sourcePatchId,不是 parentXxx
});
await drawingManager.deleteBranch({ type: 'imports', mapid, version, branchName });
// 补丁
await drawingManager.saveDrawing({
type: ss.type, // 必填(ss = Engine.currentDoc.serverSource)
mapid, version, branchName,
parentId, originalJson, currentJson // diff 由前端 WASM 计算,只上传 patch
});
await drawingManager.deletePatch({ type: 'imports', mapid, version, branch: branchName, patchId }); // 字段是 branch 不是 branchName
// 合并
await drawingManager.mergeBranch({
type: 'imports', mapid, version, // type 必填
sourceBranch, targetBranch,
/* conflictResolution? */
});
4. 命令对照
| 命令 | 作用 |
|---|---|
OPENFROMSERVER |
图纸浏览器:选分支 / 补丁打开(普通 / 只读 / 瓦片),并内置分支创建 / 删除、合并(含冲突对话框)、删补丁、删图纸 |
SAVESERVER |
把当前 doc 保存为新 patch(冲突时弹 ConflictResolutionDialog;瓦片模式下同时记录编辑区与瓦片透明度) |
| 自定义命令 | 需要业务定制流程 / UI 时再用 DrawingManagerService 自己实现 |
5. 子文档
- 分支创建 / 切换 → branching
- 保存补丁(生成 diff) → save-patch
- 合并 / 冲突解决 → merge-resolve
- 历史浏览 / 删除补丁 → history
- 用户认证(鉴权回调) → user-authentication
6. 与 Git 的对照
| Git | vjcad |
|---|---|
| commit | patch |
| branch | branch |
| merge | mergeBranch |
| conflict | mergeResult.conflict |
| HEAD | serverSource.lastPatchId |
| working tree | Engine.currentDoc |
git diff |
保存时 WASM createWebcadDiff 自动计算(DiffUtils.diff 只用于 DIFF 面板展示) |
红旗
- 保存不必先同步到最新 patch:服务端只检查"
parentId之后的补丁是否也改过本次修改的实体 / 图层",无交集就直接追加到分支末尾;有交集返回conflict,带conflictResolution并以parentId = conflict.latestPatchId重存。parentId填了分支里不存在的 id 时冲突检测会被 静默跳过 serverSource.lastPatchId是当前文档"知道"自己处于哪个补丁的依据;切分支后要更新originalJson必须是 打开时的 baseline,currentJson是当前实时状态;它们一起生成 diff- 删除分支 / 删除 patch 不可逆,UI 上加二次确认;
deletePatch会删除该 patch 及其后全部 patch,base不能删 - main 分支不能用
deleteBranch删(服务端拒绝);只能deleteDrawing删除整张图纸 OPENFROMSERVER的图纸浏览器已内置完整版本管理:只读打开 / 瓦片打开、分支创建与删除、合并(含冲突对话框)、删补丁、删图纸——不一定要自己写 UI
参考(官方文档 MCP)
- 文档:
vjcad/doc/version/index.md、vjcad/doc/version/versioning.md、vjcad/doc/version/user-auth.md - 示例:
vjcad/example/version/01createbranch.js~06userauthcallback.js