单图编辑兼容历史客户端 -preview 尾巴命名,剥尾取来源锚

This commit is contained in:
chenpei 2026-08-28 14:31:01 +08:00
parent 4c08965cc7
commit e9902f9d9d
2 changed files with 41 additions and 0 deletions

View File

@ -206,3 +206,35 @@ describe('旧代预览名(detail-preview-{时间戳}-{序号}-...)兼容', (
expect(aligned).toEqual([0, 1])
})
})
describe('历史客户端 -preview 尾巴命名兼容', () => {
test('剥掉 -preview 尾巴得到来源锚', () => {
expect(parseTaskDetailPreviewFileName('主图3-preview.webp')).toEqual({ label: '主图3', sliceIndex: null })
expect(parseTaskDetailPreviewFileName('4-preview.webp')).toEqual({ label: '4', sliceIndex: null })
expect(parseTaskDetailPreviewFileName('GBSFY-SJZ0030 (1)-preview.webp')).toEqual({ label: 'GBSFY-SJZ0030 (1)', sliceIndex: null })
})
test('真实形态:26 行 -preview 命名主图与 26 条目主锚定直接配对', () => {
const labels = ['主图3 拷贝 3', '主图3 拷贝', '主图3', '主图4', '4', '5', '6', '7',
'主图1 拷贝', '主图1', '主图2', '主图2拷贝', '1', '2', '3 拷贝 2', '3',
'功能主图4', '功能主图5', '功能主图1', '功能主图2', '功能主图3',
'功能主图3-2', '功能主图4-2', '功能主图5-2', '功能主图1-2', '功能主图2-2']
const rows = labels.map((label, index) => row(`r${index}`, `${label}-preview.webp`, index))
const runs = groupPreviewRowsIntoRuns(rows)
expect(runs?.length).toBe(26)
const exts = ['.png', '.png', '.png', '.png', '.png', '.png', '.jpg', '.jpg', '.png', '.png',
'.jpg', '.jpg', '.png', '.png', '.png', '.png', '.png', '.png', '.png', '.png',
'.png', '.png', '.png', '.png', '.png', '.png']
const entries = labels.map((label, i) => label + exts[i])
const matched = matchRunsToZipEntries(runs!, entries)
expect(matched).toEqual(labels.map((_, i) => i))
})
test('新代命名不受 -preview 剥离影响', () => {
// 源文件本身叫 photo-preview.jpg 的新代命名:剥尾后锚对不上条目 → 拒绝而非错配
expect(parseTaskDetailPreviewFileName('photo-preview.webp')).toEqual({ label: 'photo', sliceIndex: null })
const runs = groupPreviewRowsIntoRuns([row('a', 'photo-preview.webp', 0)])
// 单图场景:锚剥错后走「剩余一一配对」兜底,1 对 1 无歧义,仍指向唯一条目
expect(matchRunsToZipEntries(runs!, ['photo-preview.jpg'])).toEqual([0])
})
})

View File

@ -150,6 +150,15 @@ export function parseTaskDetailPreviewFileName(fileName: string): ParsedPreviewN
sliceIndex: Number(sliceMatch[1]),
}
}
// 历史客户端命名 `{原始基础名}-preview.webp`(如 `主图3-preview.webp`):
// 剥掉 -preview 尾巴才是与 ZIP 条目名对应的锚。误剥只会导致配不上被拒绝,
// 不会错配(锚定仍要求条目名唯一命中)。
const previewTailMatch = /^(.+)-preview$/i.exec(withoutExtension)
if (previewTailMatch) {
return { label: previewTailMatch[1], sliceIndex: null }
}
return { label: withoutExtension, sliceIndex: null }
}