MVP底座⑧:数据域四域大卡 —— 项目/客户/情报/供应商

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:05:28 +08:00
co-authored by Claude Fable 5
parent 21b66567bd
commit 10990a1efa
@@ -11,8 +11,7 @@
* 自 `~/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, NList, NRow, Note, PageHead, QueryGate, Sec } from '@web-shared/gov/primitives.tsx';
import { Card, Chip, Clear, Entry, NList, NRow, Note, PageHead, QueryGate, Sec } from '@web-shared/gov/primitives.tsx';
import type { Nav } from '@web-shared/gov/gov-route.ts';
import { useGovLedger, useGovObjects } from '@web-shared/gov/gov-api.ts';
import { domainShort, sortDomains } from '@web-shared/gov/domains.ts';
@@ -34,28 +33,37 @@ export function DataHome({ nav }: HomeProps) {
<QueryGate query={q}>
<>
<Note>
数据<b>不设箱、靠域</b>:域是承载的划分,对象由活动声明物化——最大化合并、只增不破坏。
这里改结构;<b>行数据在运营中心 · 台账看</b>。
数据按<b>经营对象</b>四分:<b>项目</b>是每一单的流转单据(受理记录 → 比价 → 草案 → 报价单),
<b>客户 / 情报 / 供应商</b>是跨单沉淀的资产。域是承载的划分,对象由活动声明物化 ——
最大化合并、只增不破坏。这里改结构;<b>行数据在运营中心 · 台账看</b>。
</Note>
{domains.map((d) => (
<div key={d} className="g-sec">
<div className="g-band">
<Ico name="database" s={13} />
{domainShort(d)}
<span className="g-mono" style={{ fontWeight: 500 }}>
{d}
{domains.map((d) => {
const inDomain = objects.filter((o) => o.domain === d);
return (
<Card
key={d}
ico="database"
title={domainShort(d)}
extra={
<span className="g-mono">
{d} · {inDomain.length} 对象
</span>
<span className="x">{objects.filter((o) => o.domain === d).length} 个对象 · 发布即入运营台账</span>
</div>
<NList>
{objects
.filter((o) => o.domain === d)
.map((o) => (
<ObjectSchemaRow key={`${o.domain}.${o.object}`} domain={o.domain} object={o.object} nav={nav} />
}
>
<div className="g-entries">
{inDomain.map((o) => (
<Entry
key={o.object}
ico="table"
title={o.object}
desc="点开看列结构与主键;行数据在运营中心"
onClick={() => nav.push({ k: 'obj', id: `${o.domain}.${o.object}` })}
/>
))}
</NList>
</div>
))}
</Card>
);
})}
{objects.length === 0 && (
<Clear>还没有物化的对象 —— 活动第一次写入时,系统按它的声明把表建出来,然后出现在这里。</Clear>
)}
@@ -64,26 +72,6 @@ export function DataHome({ nav }: HomeProps) {
);
}
/** 一个对象的结构一行:列数 / 主键 —— 点开看完整模式,仍不含行数据 */
function ObjectSchemaRow({ domain, object, nav }: { domain: string; object: string; nav: Nav }) {
const page = useGovLedger(domain, object);
const columns = page.data?.columns ?? [];
const pk = page.data?.primaryKey ?? [];
return (
<NRow
tone="brand"
ico="table"
title={object}
sub={`${domain}.${object}`}
cols={[
{ k: '列', v: columns.length === 0 ? '—' : String(columns.length) },
{ k: '主键', v: pk.length === 0 ? '—' : pk.join(', ') },
]}
onClick={() => nav.push({ k: 'obj', id: `${domain}.${object}` })}
/>
);
}
/* ==================== 运营侧:台账(某一个域页签) ==================== */
/**