From ff114a2246fc0b9229a345399ebe136e5c59d1a3 Mon Sep 17 00:00:00 2001 From: 18628386721 <18628386721@163.com> Date: Tue, 28 Jul 2026 14:50:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=81=E7=A8=8B=E8=AF=A6=E6=83=85:=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8D=A1=E4=B8=8E=E5=9B=BE=E5=B9=B3=E9=BD=90=20+=20?= =?UTF-8?q?=E6=98=BE=E5=BC=8F=E3=80=8C=E6=96=B0=E5=BB=BA=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E3=80=8D+=20=E8=8A=82=E7=82=B9=E5=B1=9E=E6=80=A7=E6=88=90?= =?UTF-8?q?=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 三处走查反馈: ① 版本列改成**固定高度卡片,与右侧的图等高**(grid stretch): 头部 = 标题 + 版本数 + 「新建版本」;中段版本行,多了在卡内滚,不把页面撑长; 卡尾一句常驻说明(恰一个生效;在途按启动版本跑完)。实测两侧 591px 对 591px,顶对齐。 ② 版本从此有**显式的新建入口** —— 之前只能靠改图保存来隐式长版本。 「新建版本」= 以当前看的版本为底克隆一版(服务端定版号并即刻生效)。 与「激活」分工明确:激活只是切生效指针,不长版本;新建才长 —— 把旧版本的画法复活成最新版、或在现状上另起一版接着画,都走这儿。 画布有未保存改动时确认卡会明说「克隆不带未保存的改动」。 实测:以 v3 为底建 v4 → v4 生效、v3 自动停用、列表实时刷新。 ③ 节点属性从裸块改成**卡片**(与页面其它卡同一形制),标题右侧带状态 (只读 / 有改动待保存 / 点节点就地填写)。 typecheck ✓ lint ✓ depcruise ✓ api:check ✓ 498 测试 ✓ Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m --- apps/web/src/app/styles/console.css | 11 +- .../features/gov-process/internal/panel.tsx | 177 +++++++++++------- 2 files changed, 121 insertions(+), 67 deletions(-) diff --git a/apps/web/src/app/styles/console.css b/apps/web/src/app/styles/console.css index 727cd83..60eb626 100644 --- a/apps/web/src/app/styles/console.css +++ b/apps/web/src/app/styles/console.css @@ -507,8 +507,15 @@ /* ── 流程详情:左版本列 + 右画布(补充)────────────────────────────── 版本收在流程内部:左列是这条流的全部版本(恰一个生效),点谁看谁的图; 属性区从右侧窄栏挪到图下整行(g-wide),声明式契约细节再往下。 */ -.g-flowlab { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(0, 2.2fr); gap: 12px; align-items: start; } -.g-vers { position: sticky; top: 2px; display: flex; flex-direction: column; gap: 8px; } +.g-flowlab { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(0, 2.2fr); gap: 12px; align-items: stretch; } +/* 版本卡:与右侧的图**等高**(grid stretch),版本多了在卡内滚,不把页面撑长 */ +.g-vercard { display: flex; flex-direction: column; min-height: 0; background: var(--card); border: 1px solid var(--cline); border-radius: 13px; box-shadow: var(--cshadow); overflow: hidden; } +.g-vercard-h { flex: none; display: flex; align-items: center; gap: 8px; padding: 11px 13px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; font-weight: 800; color: var(--ink-2); } +.g-vercard-h svg { color: var(--ink-4); } +.g-vercard-h .n { font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--ink-4); } +.g-vercard-h .g-ver-act { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; } +.g-vercard-list { flex: 1; min-height: 0; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; } +.g-vercard-f { flex: none; padding: 9px 13px; border-top: 1px dashed var(--line-soft); font-size: 11px; line-height: 1.6; color: var(--ink-3); } .g-ver { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: var(--card); border: 1px solid var(--cline); border-radius: 11px; cursor: pointer; font: inherit; text-align: left; transition: border-color var(--t-fast), box-shadow var(--t-fast); } .g-ver:hover { border-color: #c9d6e6; } .g-ver.on { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-wash); } diff --git a/apps/web/src/features/gov-process/internal/panel.tsx b/apps/web/src/features/gov-process/internal/panel.tsx index e0f7c99..20246c2 100644 --- a/apps/web/src/features/gov-process/internal/panel.tsx +++ b/apps/web/src/features/gov-process/internal/panel.tsx @@ -435,6 +435,48 @@ function FlowLab({ }, }); + /** + * 新建版本 = **以当前看的版本为底克隆一版**(服务端定版号并即刻生效)。 + * 与「激活」分工明确:激活只是把生效指针切过去,不产生新版本; + * 新建版本才长一版 —— 把旧定义复活成最新版、或在现状上另起一版接着画,都走这儿。 + */ + const cloneVersion = useMutation({ + mutationFn: () => call<{ pkg: ProcessPackage; report: ClosureReport }>(saveProcessRoute, { body: { pkg } }), + onSuccess: (out) => { + setReport(out.report); + void queryClient.invalidateQueries({ queryKey: ['gov', 'process'] }); + void queryClient.invalidateQueries({ queryKey: ['gov', 'process-reports'] }); + setAsk(undefined); + onSaved(); + }, + }); + + const askClone = () => + setAsk({ + spec: { + title: `新建版本:以 v${pkg.version} 为底 → v${nextVersion}`, + note: + dirty && !readOnly ? ( + + 画布上有未保存的改动,新建版本不会带上它们(克隆的是已存的 v{pkg.version})。 + 想连改动一起走,用下面的「保存并生效」。 + + ) : ( + + 把 v{pkg.version} 的定义原样复制成 v{nextVersion} 并即刻生效 + {readOnly ? ' —— 这就是「把旧版本的画法复活成最新版」的路' : ',再在新版上接着画'}。 + + ), + impact: { + who: `此后新起的工作流走 v${nextVersion}`, + undo: '版本并存,可把生效切回任一版', + when: '确认即建并生效', + }, + okLabel: `建 v${nextVersion} 并生效`, + onOk: () => cloneVersion.mutate(), + }, + }); + const askActivate = (v: ProcessPackage) => setAsk({ spec: { @@ -588,69 +630,73 @@ function FlowLab({ } >
-