数据目录 F2b:助手「建议更新数据目录」卡片补上服务端对一项的说明(新增的关联关系没写基数、又推算不出来时 PatchChange 带的 note),写在那一项下面;解析时保留 note;补检查脚本的断言

This commit is contained in:
ThearchyHelios
2026-10-04 02:19:38 +08:00
parent 737c7454d5
commit a5a68488f0
5 changed files with 23 additions and 3 deletions
+2
View File
@@ -2529,6 +2529,8 @@ export const CATALOG_UI_TEXT = {
savedImpact: (n: number) => `已保存。${formatNumber(n)} 个已发布模板引用这张表,下次正式运行时会提示数据目录有变化`,
savedImpactShow: '查看模板',
savedImpactDismiss: '收起这条提示',
// ---- 助手「建议更新数据目录」卡片:服务端对一项的说明(新增的关联关系推算不出基数)
patchNote: '说明',
}
// ===========================================================================
+9 -2
View File
@@ -1,11 +1,11 @@
import { useCallback, useState } from 'react'
import { Link } from 'react-router-dom'
import { BookMarked, Check, ExternalLink, RotateCw } from 'lucide-react'
import { BookMarked, Check, ExternalLink, Info, RotateCw } from 'lucide-react'
import clsx from 'clsx'
import { ApiError, api } from '../api/client'
import { Notice, Spinner, toast } from '../components/ui'
import { CatalogImpactList } from '../components/CatalogImpact'
import { CATALOG_PATCH_TEXT as T, CATALOG_STATUS_LABEL } from '../lib/terms'
import { CATALOG_PATCH_TEXT as T, CATALOG_STATUS_LABEL, CATALOG_UI_TEXT as UT } from '../lib/terms'
import type { CatalogPatchChange } from '../types'
import {
catalogTableHref, codeMeaning, patchSubmit, patchTarget, patchValueText, patchWhere, type CatalogPatch,
@@ -198,6 +198,13 @@ function ChangeRow({ change: c, dense }: { change: CatalogPatchChange; dense: bo
</>
)}
</dl>
{/* 服务端的说明(新增关系推算不出基数时):保存照样能存,但要让人知道哪一处空着、影响哪条检查 */}
{c.note && (
<p className="mt-1 flex items-start gap-1 text-2xs leading-relaxed text-dim" data-patch-note="">
<Info size={11} className="mt-0.5 shrink-0" style={{ color: 'var(--st-waiting)' }} aria-hidden />
<span className="min-w-0 break-words"><span className="text-faint">{UT.patchNote}:</span>{c.note}</span>
</p>
)}
</li>
)
}
+1
View File
@@ -61,6 +61,7 @@ function changeOf(x: unknown): CatalogPatchChange | null {
value: 'value' in c ? c.value : c.after,
reason: typeof c.reason === 'string' ? c.reason : '',
state: typeof c.state === 'string' && STATES.has(c.state) ? c.state as CatalogPatchChange['state'] : 'change',
...(typeof c.note === 'string' && c.note.trim() ? { note: c.note.trim() } : {}),
}
}
+2
View File
@@ -2761,6 +2761,8 @@ export interface CatalogPatchChange {
reason: string
/** change 值有变化;confirm 值相同、还不是已确认(保存即确认);same 已经是这个值且已确认 */
state: 'change' | 'confirm' | 'same'
/** 服务端对这一项的说明(目前只有:新增的关联关系没写基数、又推算不出来)。没有时不给 */
note?: string
}
/** 保存、预览提案时交回的一项:路径、原样取值、理由 */
+9 -1
View File
@@ -1149,7 +1149,12 @@ await section('助手改图:一步撤销、回执、只回话、失败退回
{ op: 'model', model: 'fake-model' },
{ op: 'catalog_patch', source: 'shop', source_id: 'src-shop', table: 'orders', table_label: '订单', version: 2, changes: [
{ path: 'columns.status.codes', before: { 1: '已支付' }, before_status: 'confirmed', after: { 1: '已支付', 9: '作废' },
value: { 9: '作废' }, reason: '用户说明 status=9 表示作废', state: 'change' }] },
value: { 9: '作废' }, reason: '用户说明 status=9 表示作废', state: 'change' },
// 新增的关联关系没写基数、又推算不出来:服务端(PatchChange.as_dict)带一句说明
{ path: 'relations.rmember-id-members-id', before: null, before_status: null,
after: { columns: ['member_id'], to_table: 'members', to_columns: ['id'], cardinality: null },
value: { columns: ['member_id'], to_table: 'members', to_columns: ['id'] }, reason: '用户说明 member_id 对应会员', state: 'change',
note: '没有写明基数,表结构里也查不到两端的主键和唯一约束,基数暂时空着;一对多关联后重复计算的检查用不上这条关系' }] },
{ op: 'reply', text: '已整理成数据目录的修改建议。' },
]
const patchSent = []
@@ -1169,6 +1174,9 @@ await section('助手改图:一步撤销、回执、只回话、失败退回
const patchCard = page.locator('[data-catalog-patch="orders"]').last()
check('助手栏里有「建议更新数据目录」卡片', await patchCard.waitFor({ timeout: 3000 }).then(() => true, () => false)
&& (await patchCard.innerText()).includes('列 status 的码值'))
const noteRow = patchCard.locator('[data-patch-change="relations.rmember-id-members-id"]')
check('……服务端对一项的说明(新增关系推算不出基数)写在那一项下面', (await noteRow.locator('[data-patch-note]').innerText().catch(() => ''))
.includes('没有写明基数') && await patchCard.locator('[data-patch-note]').count() === 1, await noteRow.innerText().catch(() => ''))
await patchCard.locator('[data-patch-save]').click()
await patchCard.locator('[data-patch-done]').waitFor({ timeout: 3000 })
check('保存带版本和原样取值', patchSent[0]?.if_version === 2 && JSON.stringify(patchSent[0]?.changes?.[0]?.value) === '{"9":"作废"}',