UI②:数据对象全用中文名 —— label 随物化落 PG 注释,全链读回

此前 label 在建表那一步就丢了,治理台只剩 project__intake_record 这种键给人看。
用表/列注释而非另建元数据表:名字与表同生共死,不会对不上。
设计台/运营台/对象详情/触发器下拉一律中文名在前、键在后。

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:33:09 +08:00
co-authored by Claude Fable 5
parent 188637cf26
commit ec0b78c550
12 changed files with 113 additions and 26 deletions
@@ -55,8 +55,9 @@ export function DataHome({ nav }: HomeProps) {
<Entry
key={o.object}
ico="table"
title={o.object}
desc="点开看列结构与主键;行数据在运营中心"
// 人读名优先;没登记 label 才退回对象键 —— 治理台不该拿 `intake_record` 给人看
title={o.label ?? o.object}
desc={`${o.domain}.${o.object}`}
onClick={() => nav.push({ k: 'obj', id: `${o.domain}.${o.object}` })}
/>
))}
@@ -95,7 +96,13 @@ export function LedgersHome({ tab, nav }: HomeProps) {
) : (
<NList>
{inDomain.map((o) => (
<LedgerObjectRow key={`${o.domain}.${o.object}`} domain={o.domain} object={o.object} nav={nav} />
<LedgerObjectRow
key={`${o.domain}.${o.object}`}
domain={o.domain}
object={o.object}
label={o.label}
nav={nav}
/>
))}
</NList>
)}
@@ -105,14 +112,14 @@ export function LedgersHome({ tab, nav }: HomeProps) {
}
/** 一个数据对象一行:行数是运营侧最想先看到的那个数 */
function LedgerObjectRow({ domain, object, nav }: { domain: string; object: string; nav: Nav }) {
function LedgerObjectRow({ domain, object, label, nav }: { domain: string; object: string; label?: string | undefined; nav: Nav }) {
const page = useGovLedger(domain, object);
const total = page.data?.total;
return (
<NRow
tone={total !== undefined && total > 0 ? 'brand' : 'mute'}
ico="table"
title={object}
title={label ?? page.data?.label ?? object}
sub={`${domain}.${object}`}
cols={[
{ k: '行数', v: total === undefined ? '…' : String(total) },
@@ -137,8 +144,8 @@ export function ObjPage({ id }: { id: string }) {
<>
<PageHead
ico="table"
kicker={`数据对象 · ${domain}`}
title={object ?? ''}
kicker={`${domainShort(domain ?? '')}域 · ${domain}.${object}`}
title={page.data?.label ?? object ?? ''}
chips={
<>
<Chip ico="columns">{columns.length} 列</Chip>
@@ -152,8 +159,11 @@ export function ObjPage({ id }: { id: string }) {
<div className="g-rows">
{columns.map((c) => (
<div key={c.name}>
<em>{c.name}</em>
<b className="mono">{c.type}</b>
{/* 人读名在前、字段键在后:填表的人看名字,写映射的人看键 */}
<em>{c.label ?? c.name}</em>
<b className="mono">
{c.name} · {c.type}
</b>
</div>
))}
</div>
@@ -167,7 +177,9 @@ export function ObjPage({ id }: { id: string }) {
<thead>
<tr>
{columns.map((c) => (
<th key={c.name}>{c.name}</th>
<th key={c.name} title={`${c.name} · ${c.type}`}>
{c.label ?? c.name}
</th>
))}
</tr>
</thead>
@@ -41,6 +41,7 @@ import {
} from '@web-shared/gov/primitives.tsx';
import type { Nav } from '@web-shared/gov/gov-route.ts';
import { useGovObjects, useGovPackages, useGovTriggers } from '@web-shared/gov/gov-api.ts';
import { domainShort } from '@web-shared/gov/domains.ts';
export type HomeProps = { tab: string; nav: Nav };
@@ -294,7 +295,8 @@ function TriggerForm({
>
{(objects.data?.objects ?? []).map((o) => (
<option key={`${o.domain}.${o.object}`} value={`${o.domain}.${o.object}`}>
{o.domain}.{o.object}
{/* 选表的人认中文名,键跟在后面供对映射 */}
{domainShort(o.domain)}·{o.label ?? o.object}({o.domain}.{o.object})
</option>
))}
</select>