/** * feature `gov-blueprint` —— 设计中心首页:企业蓝图。 * * 一屏回答两个问题:**这家企业被定义成什么样**,**哪里还没定义完**。 * * 因果链:流程包(战略)→ 活动库(方法)→ 工具箱(能力)→ 数据域(对象)。 * 四库各自有页,但「为什么是这四库、它们怎么相互决定」得有一屏能讲 —— 就是这一屏。 * * 这里**不出现任何运行态数字**(在跑几单、30 天起单数、死信数)。 * 设计者看的是定义完不完整,不是今天忙不忙 —— 混进运行数字,这页就退化成第二个驾驶舱。 */ import { Ico } from '@web-shared/Ico.tsx'; import { Clear, Sec, Todo } from '@web-shared/gov/primitives.tsx'; import type { Nav } from '@web-shared/gov/gov-route.ts'; import { useGovActivities, useGovObjects, useGovPackages, useGovPkgReports, useGovTools, useGovTriggers, } from '@web-shared/gov/gov-api.ts'; export type HomeProps = { tab: string; nav: Nav }; export function BlueprintHome({ nav }: HomeProps) { const pkgs = useGovPackages(); const acts = useGovActivities(); const tools = useGovTools(); const objs = useGovObjects(); const trgs = useGovTriggers(); const packages = pkgs.data?.packages ?? []; const reports = useGovPkgReports(packages); const reportOf = (id: string, version: number) => reports.data?.get(`${id}@${version}`); const drafts = packages.filter((p) => p.state !== 'published'); const draftBad = drafts.filter((p) => reportOf(p.id, p.version)?.publishable === false); const activities = acts.data?.activities ?? []; const toolRows = tools.data?.tools ?? []; const objectRows = objs.data?.objects ?? []; const domains = [...new Set(objectRows.map((o) => o.domain))]; const triggers = trgs.data?.triggers ?? []; /** 编排里引用了、但活动库装不出来的活动 —— 图画得通,活儿没人干 */ const referenced = [ ...new Set( packages.flatMap((p) => p.nodes.flatMap((n) => (n.kind === 'activity' && n.activityId !== undefined ? [n.activityId] : [])), ), ), ]; const missingActivities = referenced.filter((id) => !activities.some((a) => a.activityId === id)); /** 没有任何触发器指向的流程包 —— 定义完整,但没人调得起来 */ const uncalled = [...new Set(packages.map((p) => p.id))].filter( (id) => !triggers.some((t) => t.processPackageId === id), ); const gaps = draftBad.length + missingActivities.length + uncalled.length; // 因果链是这一屏的主角:四库以真箭头相连 —— 箭头编码的是真实依赖 // (流程包引用活动、活动调工具、活动物化数据),节点卡即入口,点卡即入库。 return ( <>
{gaps === 0 ? ( 没有缺口 —— 流程包全部闭合,引用的活动都装好了,每条流也都有触发器调得起来。 ) : (
{draftBad.map((p) => ( v.message).join(';') || '存在未通过闭合校验的声明' } acts={[ { label: '去编排', ico: 'route', onClick: () => nav.push({ k: 'pkg', id: `${p.id}@${p.version}` }) }, { label: '看边映射', ico: 'git-merge', onClick: () => { nav.push({ k: 'pkg', id: `${p.id}@${p.version}` }); nav.push({ k: 'edges', id: `${p.id}@${p.version}` }); }, }, ]} /> ))} {missingActivities.map((id) => ( nav.jump('library', 'shelf') }]} /> ))} {uncalled.map((id) => ( p.id === id)?.name ?? id} 没有任何调起规则`} desc="流程定义完整,但没人调得起来 —— 给它配一条周期 / 事件 / 登记触发器。" acts={[{ label: '去配规则', ico: 'zap', onClick: () => nav.jump('workflows', 'rules') }]} /> ))}
)}
); }