Archived
卡上只报查得到的事实(范式/分类/包版本/资产生效版/上架): 清单里没有「实现到没到位」的可靠依据,不在卡上编一个章 —— 槽位状态记在 debt.md。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
136 lines
5.2 KiB
TypeScript
136 lines
5.2 KiB
TypeScript
/**
|
||
* feature `gov-activity` —— 活动库:两维分类 × 包版本 × 资产版本
|
||
*
|
||
* 自 `~/coding/JCAI_PRD/governance/_components/Governance.tsx` 平移:
|
||
* DOM 结构、类名(`g-*` + 色调 `t-*`)与文案原样保留,mock 常量换成服务端投影(README 平移规则 1/2/4)。
|
||
* 区首页只负责导航,治理动作一律落在下钻详情页的**就地确认带**(影响预览三必答)。
|
||
*/
|
||
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 {
|
||
useGovActivities,
|
||
useGovMemory,
|
||
} from '@web-shared/gov/gov-api.ts';
|
||
|
||
export type HomeProps = { tab: string; nav: Nav };
|
||
|
||
export function LibraryHome({ nav }: HomeProps) {
|
||
const q = useGovActivities();
|
||
const activities = q.data?.activities ?? [];
|
||
return (
|
||
<QueryGate query={q}>
|
||
<>
|
||
<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>
|
||
);
|
||
}
|
||
|
||
/* ---------------- ⑥ 工具管理 ---------------- */
|
||
|
||
export function ActPage({ id, nav }: { id: string; nav: Nav }) {
|
||
const q = useGovActivities();
|
||
const memory = useGovMemory(id);
|
||
const a = (q.data?.activities ?? []).find((x) => x.activityId === id);
|
||
if (a === undefined) return <Note>活动不存在。</Note>;
|
||
return (
|
||
<>
|
||
<PageHead
|
||
ico={PARA[a.paradigm].ico}
|
||
tone={PARA[a.paradigm].tone}
|
||
kicker={`活动 · ${a.activityId}`}
|
||
title={a.name}
|
||
chips={
|
||
<>
|
||
<Chip tone={PARA[a.paradigm].tone}>{PARA[a.paradigm].label}</Chip>
|
||
<Chip ico="tag">{a.category}</Chip>
|
||
<Chip tone={a.enabled ? 'ok' : 'mute'}>{a.enabled ? '已启用' : '已停用'}</Chip>
|
||
</>
|
||
}
|
||
desc={PARA[a.paradigm].full + ' —— 活动是系统外开发、经此安装的外装件。'}
|
||
/>
|
||
<Card ico="package" title="包版本 · 安装两审">
|
||
<div className="g-rows">
|
||
{a.packageVersions.map((p) => (
|
||
<div key={p.version}>
|
||
<em>v{p.version}</em>
|
||
<b className="mono">
|
||
{p.state} · {p.installedAt.slice(0, 16).replace('T', ' ')}
|
||
</b>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</Card>
|
||
<Card ico="trending-up" title="资产版本 · 进化管线">
|
||
<div className="g-rows">
|
||
{a.assetVersions.map((v, i) => (
|
||
<div key={i}>
|
||
<em>
|
||
{v.kind} v{v.version}
|
||
</em>
|
||
<b className="mono">{v.effective ? '生效中' : '历史'}</b>
|
||
</div>
|
||
))}
|
||
{a.assetVersions.length === 0 && <Clear>尚无资产版本。</Clear>}
|
||
</div>
|
||
</Card>
|
||
<Entry
|
||
ico="layers"
|
||
title="活动记忆"
|
||
desc={`四层条目 · 当前 ${(memory.data?.entries ?? []).length} 条`}
|
||
onClick={() => nav.jump('knowledge', 'layers')}
|
||
/>
|
||
</>
|
||
);
|
||
}
|
||
|