Why: A single run re-registering one deliverable left three identical report files side by side (storage is append-only by design and the prompt even teaches revisions-as-new-versions); the panel listed every row. Per the owner ruling, storage keeps all versions - the panel now groups by name, shows only the latest row, badges multi-version groups with the count, and expands (Collapsible primitive) to list history with per-version preview/download. Evidence: tsc clean; vitest 99/99 including new grouping tests (latest selection by updatedAt, ordering, cross-name independence, empty); knip unchanged. Impact: Frontend-only display logic; no storage, API, or prompt changes. Refs: Dev task fix/artifact-version-dedupe
24 lines
817 B
TypeScript
24 lines
817 B
TypeScript
// 同名工件版本分组(2026-10-11 实测事故的修复语义,用户裁定:存储保留版本、
|
|
// 界面去重):组内按 updated_at 新→旧,latest 为面板显示行,其余为历史版本。
|
|
import type { Artifact } from './contracts'
|
|
|
|
export interface ArtifactGroup {
|
|
latest: Artifact
|
|
versions: Artifact[]
|
|
}
|
|
|
|
export function groupArtifactsByName(list: Artifact[]): ArtifactGroup[] {
|
|
const byName = new Map<string, Artifact[]>()
|
|
for (const a of list) {
|
|
const arr = byName.get(a.name) ?? []
|
|
arr.push(a)
|
|
byName.set(a.name, arr)
|
|
}
|
|
const out: ArtifactGroup[] = []
|
|
for (const versions of byName.values()) {
|
|
versions.sort((x, y) => (x.updatedAt < y.updatedAt ? 1 : x.updatedAt > y.updatedAt ? -1 : 0))
|
|
out.push({ latest: versions[0], versions })
|
|
}
|
|
return out
|
|
}
|