三面拆分⑫:UI 打磨 —— 补 10 枚缺失图标,蓝图改因果链,台账收成一个模块

图标注册表缺 arrow-left-right/columns/table/tag 等 10 名,用到即渲染成空 SVG —— 补齐;
蓝图四库改真箭头相连的因果链节点卡(卡即入口,删重复的入库段);
驾驶舱终态分布改五色堆叠条;运营数据收成左轨一枚「台账」,域下沉为 2-3 字短名页签
(受理→寻源→定价→议价→替代→共享,按流程序),进模块自动落首域。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-27 22:02:49 +08:00
co-authored by Claude Fable 5
parent 4a19690389
commit 34e207c3e8
11 changed files with 266 additions and 170 deletions
@@ -2,7 +2,7 @@
* feature `gov-data` —— 数据的两副面孔,各归其台:
*
* `DataHome`(设计中心 · 数据域):**定义面** —— 域 × 对象的结构:有哪些列、主键是什么、谁声明了它。
* `LedgersHome`(运营中心 · 台账 · 某域):**运营面** —— 这张表现在有多少行、里面是什么。
* `LedgersHome`(运营中心 · 台账 · 某域页签):**运营面** —— 这张表现在有多少行、里面是什么。
*
* 分开的理由:改 schema 和查行数据是两种心智。
* 设计者问「这个对象定义全不全」,运营者问「今天这张表有几条」——
@@ -15,6 +15,7 @@ import { Ico } from '@web-shared/Ico.tsx';
import { Card, Chip, Clear, 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';
export type HomeProps = { tab: string; nav: Nav };
@@ -27,7 +28,7 @@ export type HomeProps = { tab: string; nav: Nav };
export function DataHome({ nav }: HomeProps) {
const q = useGovObjects();
const objects = q.data?.objects ?? [];
const domains = [...new Set(objects.map((o) => o.domain))].sort();
const domains = sortDomains([...new Set(objects.map((o) => o.domain))]);
return (
<QueryGate query={q}>
@@ -40,8 +41,11 @@ export function DataHome({ nav }: HomeProps) {
<div key={d} className="g-sec">
<div className="g-band">
<Ico name="database" s={13} />
{d}
<span className="x">{objects.filter((o) => o.domain === d).length} 个对象 · 发布即在运营中心长出一位</span>
{domainShort(d)}
<span className="g-mono" style={{ fontWeight: 500 }}>
{d}
</span>
<span className="x">{objects.filter((o) => o.domain === d).length} 个对象 · 发布即入运营台账</span>
</div>
<NList>
{objects
@@ -80,10 +84,10 @@ function ObjectSchemaRow({ domain, object, nav }: { domain: string; object: stri
);
}
/* ==================== 运营侧:台账(某一个域) ==================== */
/* ==================== 运营侧:台账(某一个域页签) ==================== */
/**
* 台账的一个域 —— 壳层把左轨选中的域名当页签传进来。
* 台账的一个域 —— 壳层把选中的域页签(键)传进来;没带域时壳层已落到首域。
* 这里看的是运营事实:这张表现在多少行,点进去逐行看。
*/
export function LedgersHome({ tab, nav }: HomeProps) {
@@ -95,8 +99,8 @@ export function LedgersHome({ tab, nav }: HomeProps) {
<QueryGate query={q}>
<>
<Note>
<b>{domain}</b> 域的台账:行数据、主键与列结构。结构要改去设计中心 · 数据域;
这里做的是运营动作 —— 查行、看版本、追引用。
<b>{domainShort(domain)}</b>域(<span className="g-mono">{domain}</span>)的行数据、主键与列结构。
结构要改去设计中心 · 数据域;这里做的是运营动作 —— 查行、看版本、追引用。
</Note>
{inDomain.length === 0 ? (
<Clear>这个域还没有对象 —— 对象随活动首次写入而物化,建好就出现在这里。</Clear>
@@ -112,7 +116,7 @@ export function LedgersHome({ tab, nav }: HomeProps) {
);
}
/** 一个台账对象一行:行数是运营侧最想先看到的那个数 */
/** 一个数据对象一行:行数是运营侧最想先看到的那个数 */
function LedgerObjectRow({ domain, object, nav }: { domain: string; object: string; nav: Nav }) {
const page = useGovLedger(domain, object);
const total = page.data?.total;