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)
|
|||
|
|
}
|