Files
JX-BPOS/apps/web/src/shared/gov/gov-route.ts
T
ChaiHaoandClaude Opus 5 03eb666ac2 三面拆分⑮:对齐 Mastra 数据流 —— 边只表达顺序,数据按输入/输出字段名流动
用户定的机制对齐:Mastra 的边不传数据,所有约束力靠输入/输出字段(schema 咬合)完成。
照此把「边映射」整个退役:

  · 契约:edge 去 mapping,审批 reject 去 mapping —— 边只剩 顺序 + 条件(读上游
    输出字段)+ 标签/回边。fieldMapping 只留给触发器的起单装配(系统边界)。
    存量包无需迁移:zod 解析时把旧 jsonb 里的 mapping 静默剥掉,图照常有效。
  · 运行时:assemble(边装配)→ flatScope(铺平作用域)——
    起单入参垫底 ← 沿途各输出口字段依次盖上 ← 刚发射的载荷(Mastra 语义:
    下一步的 input 首先是上一步的 output)。下游按自己的契约取字段;
    「__」前缀是运行时自留地,不入业务作用域。审批驳回重开、失败改道同一条路。
  · 闭合校验:边未映射/必填未映射/容忍依赖三条映射类检查退役
    (宽进之下必填有没有着落是运行时补全单的事,不拦激活);
    激活闸只留一条硬伤 —— **同名不同型**:名字即管道,名同型异必坏,
    容忍依赖改按名判。改名映射不存在:名不对改契约,不是加映射。
  · 种子:A2 的入参 material 更名 pn(它就是 PN;上游 A1 发的名就得是它收的名),
    契约 0.3.0、槽位 0.8.0;流程种子边全部去映射。
  · 前端:边属性卡砍掉「映射 · 载荷装配」整节,只剩 E号/方向/条件/标签;
    节点属性卡新增「数据接口 · 按字段名流动」——每个输入字段标出运行时从哪来
    (起单入参 / 上游 X / 补全单),输出口列出发什么名;沿边回溯推导,设计期看得见。
    画布保存与依赖文件导出同步去映射。

E2E 顺带把宽进接进真流:快速归档流的 A3 要 outcome 而流里没人产 ——
测试如实走补全路(等人 → 答卡 outcome=won → 开跑 → completed)。
实测走查:A2 节点卡上 pn←上游A1、rfqRef←起单入参、scenario←补全单,推导全对。

五闸绿;契约快照随本提交入库。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-29 14:25:27 +08:00

248 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 治理台的分级页面路由 —— 自原型 `Governance.tsx` 第 25–90 行平移。
*
* 「不用抽屉、不用弹窗:每一层内容都有自己的页面。」
* 区 → 对象 → 子维度 → 元素,顶部面包屑可回跳任意一级,Esc / 返回退一级。
*/
export type Route =
| { k: 'wf'; id: string }
| { k: 'task'; id: string }
| { k: 'tasklog'; id: string }
| { k: 'apr'; id: string }
| { k: 'emp'; id: string }
| { k: 'role'; id: string }
| { k: 'pkg'; id: string }
| { k: 'trigger'; id: string }
| { k: 'act'; id: string }
| { k: 'tool'; id: string }
| { k: 'obj'; id: string }
| { k: 'mem'; id: string }
| { k: 'llm'; id: string }
| { k: 'chan'; id: string };
/**
* 十一区 —— 分属两个台面(见 `surfaces.ts`):
* 设计中心定义企业(战略 → 方法 → 能力 → 对象),运营中心看企业跑。
* 触发器不再独立成区:定义并入 workflows,启停并入 tasks;
* 记忆一分为二:度量升为 cockpit 首页,活动记忆归 knowledge。
*/
export const GOV_ZONES = [
/*
* 设计中心九区,顺序即设计的次序:
* 蓝图(全局) → 触发器(谁调起) → 流程包(怎么流转) → 活动库(每件事怎么干)
* → 工具箱(能对世界做什么) → 数据域(运营什么) → 知识库(资料,待建)
* → 大模型(模型实例绑在哪) → 测试台(跑一遍看看)
*/
'blueprint',
'triggers',
'workflows',
'library',
'tools',
'data',
'archive',
'models',
'testbed',
// 运营中心 —— 区名即运行时:工作流是流程包的运行时,任务是活动的运行时
'cockpit',
'runs',
'tasks',
'people',
'ledgers',
'knowledge',
'system',
] as const;
export type GovZone = (typeof GOV_ZONES)[number];
export const ZONES: ReadonlyArray<{ key: GovZone; label: string; icon: string }> = [
{ key: 'blueprint', label: '蓝图', icon: 'route' },
{ key: 'triggers', label: '触发器', icon: 'zap' },
{ key: 'workflows', label: '流程包', icon: 'workflow' },
{ key: 'library', label: '活动库', icon: 'boxes' },
{ key: 'tools', label: '工具箱', icon: 'wrench' },
{ key: 'data', label: '数据域', icon: 'database' },
{ key: 'archive', label: '知识库', icon: 'library' },
{ key: 'models', label: '大模型', icon: 'cpu' },
{ key: 'testbed', label: '测试台', icon: 'flask-conical' },
{ key: 'cockpit', label: '驾驶舱', icon: 'gauge' },
{ key: 'runs', label: '工作流', icon: 'activity' },
{ key: 'tasks', label: '任务', icon: 'list-checks' },
{ key: 'people', label: '员工', icon: 'users' },
{ key: 'ledgers', label: '台账', icon: 'table' },
{ key: 'knowledge', label: '数据', icon: 'layers' },
{ key: 'system', label: '系统', icon: 'settings' },
];
/** 区元信息:标题 / 定位说明 / 主色 —— 说明文取自两卷规范,不是装饰 */
export const ZM: Readonly<Record<GovZone, { title: string; desc: string; accent: string; icon: string }>> = {
blueprint: {
title: '企业蓝图',
icon: 'route',
accent: 'linear-gradient(140deg,#4954e6,#232b6e)',
desc: '战略 → 方法 → 能力 → 对象:流程包决定企业以哪些流转运转,活动库决定每件事怎么干,工具箱决定系统能对世界做什么,数据域决定企业运营什么。四库的健康度与待补清单聚在这一屏——设计者看的是定义完不完整,不是今天忙不忙。',
},
cockpit: {
title: '经营驾驶舱',
icon: 'gauge',
accent: 'linear-gradient(140deg,#12b886,#0b7a5c)',
desc: '看企业今天跑得怎样:度量八指标(自主率与纠正率成对读,复合为有效自主率)+ 异常面(异常工作流、需处置件数)。指标零埋点——全部由留痕投影而来,点数字直达处置页。',
},
ledgers: {
title: '台账管理',
icon: 'table',
accent: 'linear-gradient(140deg,#245bdb,#16307a)',
desc: '行数据 · 版本 · 引用——域的结构在设计中心改,这里做运营动作。域即页签,随数据域发布生长:设计侧一发布新域,台账里自动多一个域页签。',
},
knowledge: {
title: '数据',
icon: 'layers',
accent: 'linear-gradient(140deg,#f14ba9,#c92d86)',
desc: '运行沉淀的数据资产:活动记忆四层 + 技能资产 + 候选增量的回放与放行。记忆的终点是成为模型——候选增量必经回放与人放行,这里是那道人工放行口。',
},
runs: {
title: '工作流',
icon: 'activity',
accent: 'linear-gradient(140deg,#3370ff,#245bdb)',
desc: '流程包的运行时:在途工作流的监控,和每个包的运行配置——起单开关、命中后要不要人工确认、谁来确认、每个节点归谁负责。设计中心定义流程长什么样,这里管它今天怎么跑。',
},
tasks: {
title: '任务管理',
icon: 'list-checks',
accent: 'linear-gradient(140deg,#3370ff,#245bdb)',
desc: '活动的运行时:任务 = 活动被调起的一次运行,恰有一名负责人。这里做任务与审批单的在途监控、干预与控制——暂停可恢复、叫停归负责人、终止级联作废。工作流一级去「工作流」区看。',
},
people: {
title: '员工管理',
icon: 'users',
accent: 'linear-gradient(140deg,#2bc7d4,#0e9fd8)',
desc: '员工负载、岗位与授权。权限按岗位授予:客体三类 × 动作三种;停用前置检查——在途任务与待答卡须先改派完毕。',
},
workflows: {
title: '流程包管理',
icon: 'workflow',
accent: 'linear-gradient(140deg,#4954e6,#3a44c9)',
desc: '战略——企业以哪些流转运转。一条流一个包,版本收在包内部:画图不检查、激活才查完整,恰一个生效版本、在途按启动版本跑完。边只表达顺序与条件(对齐 Mastra),数据按输入/输出字段名流动——约束力在两端活动契约上。触发器已独立成区;启停在运营中心。',
},
library: {
title: '活动库',
icon: 'boxes',
accent: 'linear-gradient(140deg,#0aa294,#0a6a64)',
desc: '已安装活动的资产货架:活动是任务的定义——编排引用一个活动,运行时就长出一个任务。审批点与网关是系统内置要素,零开发、不入库。业务分类 × 活动类型两维,每活动两条版本序列。',
},
tools: {
title: '工具箱',
icon: 'wrench',
accent: 'linear-gradient(140deg,#7f3bf5,#5b21cf)',
desc: '能力——系统能对世界做什么。一件事能交给谁办的全集:功能工具(交给系统)、LLM 工具(交给模型)、人类工具(交给人)。读类过程中自由调用,写类只登记动作意向、放行后落地;密钥只存治理台,不入包、不入活动。',
},
data: {
title: '数据域',
icon: 'database',
accent: 'linear-gradient(140deg,#0e9fd8,#245bdb)',
desc: '对象——企业运营什么。域 × 对象的结构定义:声明物化(最大化合并、只增不破坏)与调用接入(事实源在外)。数据可以自生长,权力不可以自生长。行数据不在这里看——那在运营中心的台账。',
},
testbed: {
title: '联调测试台',
icon: 'flask-conical',
accent: 'linear-gradient(140deg,#e8833a,#c25f1a)',
desc: '把定义试着跑一遍:装一次调用、指派每个节点归谁、起单看穿全程。真实任务照旧落到被指派人的工作台,测试台不代答。一次只跑一条流,生命周期跟着仿真状态——停止仿真,这条流连同它派出的任务一起销毁。',
},
triggers: {
title: '触发器',
icon: 'zap',
accent: 'linear-gradient(140deg,#f0a020,#c47a0a)',
desc: '谁调起流程:事件(通道来件命中规则)、登记(人在表单上起一单)、周期(到点自己起)。规则在这里定,起单开关在运营中心。',
},
archive: {
title: '知识库',
icon: 'library',
accent: 'linear-gradient(140deg,#8a5f1c,#5e3f10)',
desc: '企业的资料与文档 —— 规范、图纸、样例、外部材料。待建。',
},
models: {
title: '大模型',
icon: 'cpu',
accent: 'linear-gradient(140deg,#4b4a8c,#2f2e63)',
desc: '模型实例的四元绑定(Provider / URL / Key / Model)。活动只声明用途名,换厂商换型号改这里,活动一行不动;密钥只存这儿,不入包、不入留痕。',
},
system: {
title: '系统管理',
icon: 'settings',
accent: 'linear-gradient(140deg,#46586a,#2b3644)',
desc: '系统边界的配置面:通道实例——归属键规则与默认认领岗位。模型实例已独立成设计中心的「大模型」区。',
},
};
/**
* 区内页签 —— **多数区只有一格**:一区一内容,页签栏此时由壳层收起,不占一行。
* 还留着多格的只有运营侧的任务与员工(它们确实是几个不同维度),
* 以及 `ledgers`:它的页签是数据域,随发布动态生成(壳层运行时铺开),故此表留空。
*/
export const TABS: Readonly<Record<GovZone, ReadonlyArray<{ key: string; label: string; ico: string }>>> = {
blueprint: [{ key: 'map', label: '企业蓝图', ico: 'route' }],
testbed: [{ key: 'run', label: '仿真试跑', ico: 'flask-conical' }],
triggers: [{ key: 'rules', label: '调起规则', ico: 'zap' }],
archive: [{ key: 'docs', label: '资料', ico: 'library' }],
models: [{ key: 'llm', label: '模型实例', ico: 'cpu' }],
workflows: [{ key: 'pkgs', label: '流程包', ico: 'boxes' }],
library: [{ key: 'shelf', label: '活动货架', ico: 'boxes' }],
tools: [{ key: 'catalog', label: '能力目录', ico: 'wrench' }],
data: [{ key: 'domains', label: '数据对象', ico: 'database' }],
cockpit: [{ key: 'dash', label: '驾驶舱', ico: 'gauge' }],
runs: [
{ key: 'board', label: '在途工作流', ico: 'activity' },
{ key: 'conf', label: '运行配置', ico: 'settings' },
],
tasks: [
{ key: 'list', label: '任务', ico: 'list-checks' },
{ key: 'apr', label: '审批单', ico: 'shield-check' },
{ key: 'todo', label: '需处置', ico: 'flag' },
],
people: [
{ key: 'emp', label: '员工', ico: 'users' },
{ key: 'roles', label: '岗位授权', ico: 'key' },
{ key: 'groups', label: '工作组', ico: 'users' },
],
ledgers: [], // 动态:页签即数据域(短名呈现),由壳层按已发布域生成
knowledge: [{ key: 'layers', label: '活动记忆', ico: 'layers' }],
system: [{ key: 'chan', label: '通道实例', ico: 'mail' }],
};
export function routeLabel(r: Route): string {
switch (r.k) {
case 'wf':
return '工作流';
case 'task':
return '任务';
case 'tasklog':
return '任务日志';
case 'apr':
return '审批单';
case 'emp':
return '员工';
case 'role':
return '岗位授权';
case 'pkg':
return '流程包';
case 'trigger':
return '触发器';
case 'act':
return '活动';
case 'tool':
return '工具';
case 'obj':
return '数据对象';
case 'mem':
return '活动记忆';
case 'llm':
return 'LLM 实例';
case 'chan':
return '通道实例';
}
}
export type Nav = {
push: (r: Route) => void;
jump: (z: GovZone, tab: string, r?: Route) => void;
};