/** * 批量隐藏结果汇总(P4a A16 逐项部分成功语义,纯函数供 vitest 覆盖) * * - 汇总:成功/失败计数 + 失败明细(photoId + 错误码)——toast 文案与 * 失败详情弹窗共用同一份归集结果 * - 错误码本地化:apiMsg 有词条用词条(PHOTO_NOT_PUBLIC/PHOTO_NOT_FOUND), * 未知码原样展示(契约 code 为开放枚举,服务端后续扩充不破前端) * - 行内回显归集:结果 photoId → 列表行索引(shallowRef 列表整行替换用) */ import type { useI18n } from 'vue-i18n' /** 批量隐藏结果归集 */ export interface BatchHideSummary { /** 成功项数 */ okCount: number /** 失败项数 */ failCount: number /** 失败明细(与结果同序) */ failures: Array<{ photoId: string; code: string }> } /** 逐项结果 → 汇总(ok 计成功;ok=false 收 code,缺 code 兜底 UNKNOWN) */ export function summarizeBatchHideResults(results: Api.Album.BatchHideItem[]): BatchHideSummary { const failures: BatchHideSummary['failures'] = [] let okCount = 0 for (const item of results) { if (item.ok) { okCount += 1 } else { failures.push({ photoId: item.photoId, code: item.code ?? 'UNKNOWN' }) } } return { okCount, failCount: failures.length, failures } } /** 失败码 → 本地化文案(apiMsg 词条优先,未知码原样;t 为 i18n 翻译函数) */ export function localizeBatchHideCode(t: ReturnType['t'], code: string): string { const key = `apiMsg.${code}` const text = t(key) // vue-i18n 缺词条时回退键名本身(apiMsg.${code})——非词条原样展示 code return text === key ? code : text } /** 结果 photoId → 列表行索引(不在当前页的结果忽略——换页/过滤竞态兜底) */ export function indexOfPhotoId(items: Api.Album.AdminPhoto[], photoId: string): number { return items.findIndex((item) => item.photoId === photoId) }