唯杰地图 logo唯杰地图
VJMAP
EN

创建 / 列出分支

vjcad/references/version/branching.md 6.7 KB163 行
原文

文档:vjcad/doc/version/versioning.md 示例:vjcad/example/version/01createbranch.js ⚠️ 已按 d.ts 核对:listBranches 收参数对象返回 IBranchInfo[];createBranch 字段是 sourceBranch/sourcePatchId(不是 parentBranch/parentPatchId)。

1. 列出已有分支

const drawingManager = new DrawingManagerService();

// 参数是对象:{ type: 'imports'|'designs', mapid?, version?, designPath? }
const branches = await drawingManager.listBranches({ type: 'imports', mapid, version });
// IBranchInfo[]: [{ name, createdAt, createdBy, description?, patchCount, latestPatchId,
//                  sourceInfo?: IBranchSourceInfo, patches?: IPatchInfo[] }]

branches.forEach(b => {
    console.log(`${b.name}(最新 ${b.latestPatchId}),共 ${b.patchCount} 个补丁`);
    // b.patches[]: { id, parentId?, time?, author?, remark?, editAreas?, editLayers?, tileAlpha? }
});

listBranches 返回所有分支以及每个分支的 patch 链。常用于:

  • 切分支前列出可选项
  • 历史浏览(参见 history)

2. 创建分支

2.1 命令式(弹出 BranchCreateDialog)

class CreateBranchByDialogCommand {
    async main() {
        const drawingManager = new DrawingManagerService();
        const dialog = new BranchCreateDialog();
        const src = Engine.currentDoc.serverSource;

        // IBranchCreateDialogConfig: {type, mapid?, version?, designPath?, fromBranchName, fromPatchId}
        const result = await dialog.showDialog({
            type: 'imports',
            mapid:   src.mapid,
            version: src.version,
            fromBranchName: src.branchName,
            fromPatchId:    src.lastPatchId
        });

        // IBranchCreateDialogResult: {action:'create'|'cancel', newBranchName?, mapid?, version?, fromBranchName?, fromPatchId?}
        if (result && result.action === 'create') {
            const res = await drawingManager.createBranch({
                type: 'imports',
                mapid: result.mapid,
                version: result.version,
                branchName: result.newBranchName,      // 结果里叫 newBranchName
                sourceBranch: result.fromBranchName,   // 入参叫 sourceBranch/sourcePatchId
                sourcePatchId: result.fromPatchId
            });
            // ICreateBranchResponse: {status, error?, errorCode?, branchName?}
            if (res.status) message.success(`分支 ${res.branchName} 创建成功`);
        }
    }
}

2.2 API 式(自定义业务流程)

await drawingManager.createBranch({
    type: 'imports',
    mapid:        'test',
    version:      'v1',
    branchName:   'feature-abc',           // 新分支名
    sourceBranch: 'main',                  // 来源分支(字段名是 sourceBranch)
    sourcePatchId: 'base'                  // 来源补丁('base' 表示初始)
});

完整代码:vjcad/example/version/01createbranch.js

3. 切换到某分支

vjcad 没有"切分支"命令;切分支等同于 重新打开图纸到该分支:

// 用 OPENFROMSERVER 命令
await Engine.editor.executerWithOp('OPENFROMSERVER');
// 在弹框里选 mapid / version / branch / patch

// 或 API:drawingManager.openDrawing 支持 branch / patchId,然后喂给 openDbDoc
const r = await drawingManager.openDrawing({
    type: 'imports', mapid: 'test', version: 'v1',
    branch: 'feature-abc',       // IOpenDrawingParams.branch
    patchId: 'p3'                // 指定补丁;为空取最新
});
if (r.success) {
    const f = new File([r.webcadJson], 'd.webcad', { type: 'application/json' });
    await Engine.view.openDbDoc(f, r.webcadData);   // 签名是 (File, dbData, readonly?)
    // openDbDoc 新建的文档没有 serverSource,必须手动设置,且要在 setOriginalJson 之前
    Engine.currentDoc.serverSource = {
        type: 'imports', mapid: 'test', version: 'v1',
        branchName: 'feature-abc',
        lastPatchId: r.latestPatchId || 'base'
    };
    await Engine.currentDoc.setOriginalJson(r.webcadJson);   // 无 serverSource 时直接返回 false
}

openDrawing + openDbDoc 不会 自动设置 serverSource(只有 OPENFROMSERVER 命令内部会设);漏设则后续 SAVESERVER / saveDrawing 不知道分支和父补丁。

4. 删除分支

// IDeleteBranchParams: {type, mapid?, version?, designPath?, branchName}
await drawingManager.deleteBranch({
    type: 'imports', mapid: 'test', version: 'v1',
    branchName: 'feature-abc'
});

⚠️ 不可逆。常见 UI 加二次确认 / 输入分支名校对。

5. 字段说明

createBranch 入参 ICreateBranchParams:

字段 说明
type 'imports' | 'designs'
mapid / version / designPath 图纸定位(imports 用 mapid+version,designs 用 designPath)
branchName 新分支名(不能与已有重名;必须匹配 ^[a-zA-Z0-9_-]+$)
sourceBranch 源分支(如 main)
sourcePatchId 源补丁 id('pN');'base' 表示从源分支的 base 出发;不支持 'latest'
author? / description? 元数据

listBranches 返回 IBranchInfo[]:

{
    name: string;                  // 分支名(不是 branchName)
    createdAt?: string;
    createdBy?: string;
    description?: string;
    patchCount: number;
    latestPatchId: string;         // 分支最新补丁(不是 parentPatchId)
    sourceInfo?: IBranchSourceInfo;
    patches?: IPatchInfo[];        // { id, parentId?, time?, author?, remark? }
}

红旗

  • 分支名 必须 匹配 ^[a-zA-Z0-9_-]+$,否则服务端直接拒绝(Invalid branch name...);中文 / 空格 / 点号都不行
  • sourcePatchId 只接受 'base' 或具体补丁 id('p1'、'p2'…);没有 'latest'(会报 Invalid patch ID),要从最新出发先 listBranches 取 latestPatchId。'base' 指 源分支 的 base:从 main@base 建的分支共用原始 base.vcad,其它情况会在新分支下生成分叉点快照 branchBase.vcad 作为它的 base
  • 创建分支不会自动切到该分支;继续在原分支保存依然是原分支的补丁
  • listBranches 返回的 name 字段,不要再访问 branchName/parentBranch/parentPatchId(不存在)
  • 大分支历史可能很长,listBranches 返回数据量较大时考虑后端分页
  • 删除分支前请确认是否有人在用(可能引起他人本地 serverSource.lastPatchId 失效)

参考(官方文档 MCP)

  • 文档:vjcad/doc/version/versioning.md
  • 示例:vjcad/example/version/01createbranch.js