diff --git a/apps/api/src/modules/publish/publish.service.ts b/apps/api/src/modules/publish/publish.service.ts index dc1a8af..fa077cd 100644 --- a/apps/api/src/modules/publish/publish.service.ts +++ b/apps/api/src/modules/publish/publish.service.ts @@ -107,7 +107,11 @@ export interface PublishSiteContentResult { dryRun: boolean /** dry-run = 随机 token(输出给操作者);confirm = 实际传入值 */ confirmToken: string | null - /** 候选清单(查询起点:current 非空且 published≠current) */ + /** + * 候选清单(查询起点:current 非空且 published≠current;typeKey/slug/locale 三键 + * 排序稳定呈现)。confirm 期 candidates 是**事务前快照**,权威数以 publishedCount + * 为准(并发窗口下两者可能不一致)。 + */ candidates: PublishCandidate[] /** 实际发布条数(dry-run 恒 0;confirm = 事务内 UPDATE 实际行数) */ publishedCount: number @@ -143,7 +147,7 @@ function upToDatePredicate(siteId: string) { ) } -/** 候选清单查询(entry_locales ⋈ content_entries;typeKey/slug 排序钉死清单呈现稳定) */ +/** 候选清单查询(entry_locales ⋈ content_entries;typeKey/slug/locale 排序钉死清单呈现稳定——locale 决胜同 slug 多 locale 场景) */ async function queryCandidates(db: PublishDb, siteId: string): Promise { const rows = await db .select({ @@ -157,7 +161,7 @@ async function queryCandidates(db: PublishDb, siteId: string): Promise ({ contentEntryId: r.contentEntryId, diff --git a/scripts/sf.ts b/scripts/sf.ts index e860e64..e9274b9 100644 --- a/scripts/sf.ts +++ b/scripts/sf.ts @@ -34,6 +34,9 @@ import { const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..') +/** confirm 输出的发布清单行数上限(超出以 "…and M more" 截断——192 条真实数据面可读性) */ +const CONFIRM_LIST_CAP = 20 + /** 探测报告摘要(stdout):版本块之外的计数/清洗/耗时 + 致命错误 */ function printProbeSummary(report: WxrAdapterReport): void { console.log(` rows=${report.totals.rows} terms=${report.totals.terms} unsupported=${report.totals.unsupported} failed=${report.totals.failed}`) @@ -271,6 +274,16 @@ program if (result.publishedCount === 0) { console.log(' 无待发布条目(no-op)') } else { + // 发布清单(事务前快照面;与 dry-run 同行格式——修订对 published→current) + const listed = result.candidates.slice(0, CONFIRM_LIST_CAP) + for (const c of listed) { + console.log( + ` ${c.typeKey}/${c.slug} [${c.locale}] ${c.publishedRevisionId === null ? 'NULL' : `${c.publishedRevisionId.slice(0, 8)}…`} → ${c.currentRevisionId.slice(0, 8)}…`, + ) + } + if (result.candidates.length > listed.length) { + console.log(` …and ${result.candidates.length - listed.length} more`) + } console.log(` audit: action=content.publish actor=${opts.actor}`) if (result.siteConfigRevision !== null) { console.log(