f08d68bebf
Co-Authored-By: Claude Code <noreply@anthropic.com>
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
/**
|
||
* 批量隐藏结果汇总(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<typeof useI18n>['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)
|
||
}
|