MVP底座⑦:活动库卡片化 —— 六槽位卡

卡上只报查得到的事实(范式/分类/包版本/资产生效版/上架):
清单里没有「实现到没到位」的可靠依据,不在卡上编一个章 —— 槽位状态记在 debt.md。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-28 02:04:11 +08:00
co-authored by Claude Fable 5
parent 06b9cbde04
commit 21b66567bd
@@ -5,7 +5,8 @@
* DOM 结构、类名(`g-*` + 色调 `t-*`)与文案原样保留,mock 常量换成服务端投影(README 平移规则 1/2/4)。
* 区首页只负责导航,治理动作一律落在下钻详情页的**就地确认带**(影响预览三必答)。
*/
import { Card, Chip, Clear, Entry, NList, NRow, Note, PageHead, QueryGate, St } from '@web-shared/gov/primitives.tsx';
import { Ico } from '@web-shared/Ico.tsx';
import { Card, Chip, Clear, Entry, Note, PageHead, QueryGate, St } from '@web-shared/gov/primitives.tsx';
import { PARA } from '@web-shared/gov/tone.ts';
import type { Nav } from '@web-shared/gov/gov-route.ts';
import {
@@ -20,37 +21,56 @@ export function LibraryHome({ nav }: HomeProps) {
const activities = q.data?.activities ?? [];
return (
<QueryGate query={q}>
<>
<Note>
活动是任务的<b>定义</b>:编排引用一个活动,运行时就长出一个任务。业务分类 × 活动类型两维平级;
每活动两条版本序列——包版本走安装两审,资产版本走进化管线。
</Note>
<NList>
{activities.map((a) => {
const effective = a.assetVersions.filter((v) => v.effective);
return (
<NRow
key={a.activityId}
tone={PARA[a.paradigm].tone}
ico={PARA[a.paradigm].ico}
title={a.name}
sub={`${a.activityId} · ${a.category}`}
cols={[
{ k: '类型', v: PARA[a.paradigm].label },
{ k: '包版本', v: <span className="g-mono">{a.packageVersions.map((p) => p.version).join(', ')}</span> },
{ k: '资产生效版', v: <span className="g-mono">{effective.length}</span> },
]}
right={
<St tone={a.enabled ? 'ok' : 'mute'} ico={a.enabled ? 'circle-check' : 'power'}>
{a.enabled ? '已启用' : '已停用'}
</St>
}
onClick={() => nav.push({ k: 'act', id: a.activityId })}
/>
);
})}
</NList>
</>
<>
<Note>
活动是任务的<b>定义</b>:编排引用一个活动,运行时就长出一个任务。业务分类 × 活动类型两维平级;
每活动两条版本序列——包版本走安装两审,资产版本走进化管线。
<b>审批点与网关不在这里</b>:它们是流程层的系统内置要素,零开发、不入库。
</Note>
{activities.length === 0 ? (
<Clear>货架是空的 —— 装一个活动进来,编排里才引用得到它。</Clear>
) : (
<div className="g-shelf">
{activities.map((a) => {
const para = PARA[a.paradigm];
const latest = a.packageVersions[a.packageVersions.length - 1];
const effective = a.assetVersions.filter((v) => v.effective).length;
return (
<button
key={a.activityId}
className={'g-tile t-' + para.tone}
onClick={() => nav.push({ k: 'act', id: a.activityId })}
>
<span className="g-tile-h">
<span className="g-tile-i">
<Ico name={para.ico} s={16} />
</span>
<span className="g-tile-t">
<b>{a.name}</b>
<em>{a.activityId}</em>
</span>
<Chip tone={para.tone}>{para.label}</Chip>
</span>
<span className="g-tile-m">
<Chip ico="boxes">{a.category}</Chip>
<Chip ico="git-commit">包 v{latest?.version ?? '—'}</Chip>
</span>
<span className="g-tile-f">
{/*
只报查得到的事实:资产生效版数与上架状态。
「实现到没到位」这一层,清单里没有可靠依据 —— 不在卡上编一个章。
*/}
<St tone={a.enabled ? 'ok' : 'mute'} ico={a.enabled ? 'circle-check' : 'power'}>
{a.enabled ? '已上架' : '已停用'}
</St>
<span className="r">资产生效 {effective}</span>
</span>
</button>
);
})}
</div>
)}
</>
</QueryGate>
);
}