diff --git a/frontend/src/pages/catalog/DraftDialog.tsx b/frontend/src/pages/catalog/DraftDialog.tsx index ab588758..c9fba7fc 100644 --- a/frontend/src/pages/catalog/DraftDialog.tsx +++ b/frontend/src/pages/catalog/DraftDialog.tsx @@ -36,13 +36,29 @@ interface Outcome { model: string | null failure: string | null stopped: boolean + /** 这一次勾了「用模型起草」 */ + modelAsked: boolean + /** 模型给了可用内容(model_items > 0)的表有几张;服务端没给 model_items(老服务端)时 modelItemsKnown 为假 */ + modelItems: number + modelItemsKnown: boolean } -const fresh = (total: number): Outcome => ({ +const fresh = (total: number, modelAsked = false): Outcome => ({ done: 0, total, added: 0, updated: 0, removed: 0, tableErrors: [], modelErrors: [], modelSkipped: null, model: null, - failure: null, stopped: false, + failure: null, stopped: false, modelAsked, modelItems: 0, modelItemsKnown: false, }) +/** + * 一项都没写进去时怎么说。「没有变化」只在确实是「起草出了内容、和现有目录一致」时说:有表没起草、模型在某些表上 + * 没给出内容(model_error),或者勾了用模型、却没有一张表拿到模型的可用内容(模型整体用不了、model_items 都是 0), + * 都说「目录没有更新」,原因写在下面 + */ +function nothingWrittenText(out: Outcome): string { + const failed = out.modelErrors.length > 0 || out.tableErrors.length > 0 + const modelEmpty = out.modelAsked && (!!out.modelSkipped || (out.modelItemsKnown && out.modelItems === 0)) + return failed || modelEmpty ? CT.draftNothingWritten : CT.draftNoChange +} + export function DraftDialog({ sourceId, rows, visible, selected, filtered, onClose, onDrafted }: { sourceId: string /** 全部表(服务端的顺序:使用次数多的在前) */ @@ -81,7 +97,7 @@ export function DraftDialog({ sourceId, rows, visible, selected, filtered, onClo stopRef.current = false setStopping(false) setPhase('running') - const acc = fresh(tables.length) + const acc = fresh(tables.length, useModel) setOut({ ...acc }) const touched: string[] = [] let withModel = useModel @@ -96,6 +112,8 @@ export function DraftDialog({ sourceId, rows, visible, selected, filtered, onClo acc.removed += r.total.removed acc.tableErrors.push(...r.tables.filter((t) => t.error)) acc.modelErrors.push(...r.tables.filter((t) => !t.error && t.model_error)) + acc.modelItems += r.tables.filter((t) => !t.error && (t.model_items ?? 0) > 0).length + if (r.tables.some((t) => t.model_items !== undefined)) acc.modelItemsKnown = true if (r.model) acc.model = r.model // 模型整体用不了(没配置、已停用……):后面的批次不再请模型,免得每批都撞一次同样的错 if (withModel && r.model_error && !r.model_used) { acc.modelSkipped = r.model_error; withModel = false } @@ -181,7 +199,7 @@ export function DraftDialog({ sourceId, rows, visible, selected, filtered, onClo

{out.added + out.updated + out.removed === 0 && phase === 'done' && !out.failure - ? CT.draftNoChange + ? nothingWrittenText(out) : CT.draftSummary(out.added, out.updated, out.removed)}

{out.model &&

{CT.draftModelUsed(out.model)}

} diff --git a/scripts/check-catalog.mjs b/scripts/check-catalog.mjs index 1c2960dd..1b68bc84 100644 --- a/scripts/check-catalog.mjs +++ b/scripts/check-catalog.mjs @@ -761,6 +761,33 @@ await section('数据目录 · 起草', async () => { check('……写出用的是哪个模型', (await draftBox(page).innerText()).includes('模型:check-model')) await page.locator('[data-draft-close]').click() + // 一项都没写进去:只有「模型给了内容、只是和现有目录一致」才说「没有变化」,模型没给出内容要说「目录没有更新」 + const emptyReply = ({ items, modelError }) => (route, ctx) => json({ + tables: ctx.body.tables.map((n) => ({ table_name: n, added: 0, updated: 0, removed: 0, version: 1, error: null, + model_error: modelError, model_items: items })), + total: { added: 0, updated: 0, removed: 0 }, model_used: true, model: 'check-model', model_error: null, + })(route) + const draftOnce = async (reply) => { + replies.draft.push(reply, reply) + await page.locator('[data-catalog-draft]').first().click() + await draftBox(page).locator('[data-draft-model] input').check() + await page.locator('[data-draft-start]').click() + await until(async () => (await draftBox(page).getAttribute('data-draft-dialog')) === 'done', 8000) + const summary = await draftBox(page).locator('[data-draft-summary]').innerText() + const notice = await draftBox(page).locator('[data-draft-table-model-errors]').innerText().catch(() => '') + await page.locator('[data-draft-close]').click() + return { summary, notice } + } + const noContent = await draftOnce(emptyReply({ items: null, modelError: '模型没有给出这张表的可用内容' })) + check('模型没给出内容(每张表记 model_error):不说「没有变化」,说「目录没有更新」并列出原因', + noContent.summary === '目录没有更新:模型没有给出可用的内容,原因见下方' && noContent.notice.includes('模型没有给出这张表的可用内容'), + JSON.stringify(noContent)) + const zeroItems = await draftOnce(emptyReply({ items: 0, modelError: null })) + check('……模型一项可用内容都没给(model_items 都是 0):同样不说「没有变化」', zeroItems.summary === '目录没有更新:模型没有给出可用的内容,原因见下方', + JSON.stringify(zeroItems)) + const same = await draftOnce(emptyReply({ items: 3, modelError: null })) + check('……模型给了内容、只是和现有目录一致:才说「没有变化」', same.summary === '没有变化:起草出的内容与现有目录一致', JSON.stringify(same)) + // 中途停止:当前这一批做完后不再发下一批 replies.draft.push(async (route, ctx) => { await sleep(900); return draftReply(state)(route, ctx) }) await page.locator('[data-catalog-draft]').first().click()