版本栏三改:显示完整 · 动作统一住顶部 · 「实现」明确为链接自活动库

· 栏宽 132 → 196–224:一版一行排满「v4 生效 10 节点 · 14 边」,不再挤成三行。
  · 激活/停用 · 改名 · 删除收成**顶部动作条**(右端注明作用对象 v几,
    换版看,条上的钮跟着换语义);行里只剩事实,不在行内展开小钮。
    改名输入就地在动作条下方展开,不再吊在卡底。
  · 「实现」行改口:标签「实现 · 链接自活动库」,空选项写
    「从活动库链接一个活动 —— 未链接,激活会被拦」—— 节点不含实现,
    链接才算装载,这层语义直接写在控件上。

五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-29 18:48:25 +08:00
co-authored by Claude Opus 5
parent 9c947950ce
commit 541b1c816e
2 changed files with 73 additions and 65 deletions
@@ -661,61 +661,46 @@ function FlowLab({
{/* 编排工作区:左 1/3 版本列表 + 右 2/3 画布 —— 版本收在流程内部,不平铺台面 */}
<Sec ico="route" title="编排工作区">
<div className="g-flowlab">
{/* 左栏窄:一版一行只放「v几 + 状态」;动作(激活/停用/改名/删除)只在选中行展开 */}
{/*
* 左栏:版本。**动作统一住顶部**(作用于正看的这一版),行里只放事实
* (v几 · 状态 · 点边计数)—— 完整显示,不在行内再展开一排小钮。
*/}
<aside className="g-vercard g-verslim">
<div className="g-vercard-h">
版本
<button className="g-ver-new" onClick={askClone} disabled={cloneVersion.isPending} title="以当前版为底克隆一版">
<Ico name="plus" s={11} />
<Ico name="plus" s={11} /> 新建
</button>
</div>
<div className="g-vercard-list">
{versions.map((v) => {
const isActive = v.version === activeVersion;
const isShown = v.version === pkg.version;
return (
<div key={v.version} className={'g-verrow' + (isShown ? ' on' : '') + (isActive ? ' live' : '')}>
<button className="g-verrow-h" onClick={() => onPick(v.version)}>
<b>v{v.version}</b>
<span className={'st' + (isActive ? ' live' : '')}>{isActive ? '生效' : '停用'}</span>
<span className="cnt">
{v.nodes.length}点·{v.edges.length}边
</span>
</button>
{isShown && (
/* 动作只在**看着的那一版**上出现:窄栏放不下每行一排钮,也不该让人误点别版 */
<div className="g-verrow-a">
{isActive ? (
<button className="g-ver-act" onClick={() => askRetire(v)}>
停用
</button>
) : (
<button
className="g-ver-act t-go"
/* 不闭合点不了:结构闭合 + 活动装载两面清零才亮 */
disabled={closedOf(v.version) !== true}
title={closedOf(v.version) === true ? `激活 v${v.version}` : '还不闭合 —— 属性面会列出差哪几条'}
onClick={() => askActivate(v)}
>
激活
</button>
)}
<button className="g-ver-act" onClick={() => setRenaming(true)} title="改这条流的名字(所有版本同名)">
改名
</button>
<button
className="g-ver-act t-bad"
disabled={isActive || dropVersion.isPending}
title={isActive ? '生效版删不掉 —— 先停用' : `删掉 v${v.version}`}
onClick={() => askDrop(v)}
>
删除
</button>
</div>
)}
</div>
);
})}
{/* 动作条:激活/停用 · 改名 · 删除 —— 全部作用于下面列表里选中的那一版 */}
<div className="g-veracts">
{pkg.version === activeVersion ? (
<button className="g-ver-act" onClick={() => askRetire(pkg)}>
停用
</button>
) : (
<button
className="g-ver-act t-go"
/* 不闭合点不了:结构闭合 + 活动装载两面清零才亮 */
disabled={closedOf(pkg.version) !== true}
title={closedOf(pkg.version) === true ? `激活 v${pkg.version}` : '还不闭合 —— 属性面会列出差哪几条'}
onClick={() => askActivate(pkg)}
>
激活
</button>
)}
<button className="g-ver-act" onClick={() => setRenaming(true)} title="改这条流的名字(所有版本同名)">
改名
</button>
<button
className="g-ver-act t-bad"
disabled={pkg.version === activeVersion || dropVersion.isPending}
title={pkg.version === activeVersion ? '生效版删不掉 —— 先停用' : `删掉 v${pkg.version}`}
onClick={() => askDrop(pkg)}
>
删除
</button>
<span className="who">v{pkg.version}</span>
</div>
{renaming && (
<div className="g-verrename">
@@ -732,6 +717,25 @@ function FlowLab({
<span className="t">回车改名 · Esc 取消 —— 名字是这条流的身份,各版本同名</span>
</div>
)}
<div className="g-vercard-list">
{versions.map((v) => {
const isActive = v.version === activeVersion;
const isShown = v.version === pkg.version;
return (
<button
key={v.version}
className={'g-verrow' + (isShown ? ' on' : '') + (isActive ? ' live' : '')}
onClick={() => onPick(v.version)}
>
<b>v{v.version}</b>
<span className={'st' + (isActive ? ' live' : '')}>{isActive ? '生效' : '停用'}</span>
<span className="cnt">
{v.nodes.length} 节点 · {v.edges.length} 边
</span>
</button>
);
})}
</div>
</aside>
<div className="g-canvas" ref={canvasRef}>
@@ -897,14 +901,15 @@ function FlowLab({
)}
{node.kind === 'activity' && node.flavor !== 'approval' && (
<div className="g-tbrow">
<em>实现</em>
{/* 实现 = **从活动库链接一个活动**:节点不含实现,链接才算装载(激活判据之二) */}
<em>实现 · 链接自活动库</em>
<span className="v col">
<select
className="g-tbin sel"
value={refAct?.activityId ?? ''}
onChange={(e) => patch((n) => ({ ...n, act: e.target.value === '' ? undefined : e.target.value }))}
>
<option value="">未链接 —— 激活会被「活动装载」拦下</option>
<option value="">从活动库链接一个活动 —— 未链接,激活会被拦</option>
{activities.map((a) => (
<option key={a.activityId} value={a.activityId}>
{a.name} · {a.activityId}