🐛 修复生命周期取件次数占位符

This commit is contained in:
2026-06-05 15:33:14 +08:00
parent f7108f5b44
commit 90321a5ca4
3 changed files with 94 additions and 13 deletions
+86 -13
View File
@@ -83,6 +83,7 @@ const hourInMilliseconds = 60 * 60 * 1000
const dayInMilliseconds = 24 * 60 * 60 * 1000
const adminPageSizeOptions = [5, 10, 20, 50, 100] as const
const defaultAdminPageSize = 10
const legacyUsedCountTimelineKeys = new Set(['legacy-used-count', 'legacy_used_count'])
type DetailPolicyActionOption = {
action: AdminFilePolicyAction
@@ -595,45 +596,109 @@ export function useAdminFiles() {
}
}
const normalizeTimelineNumber = (value: unknown) => {
if (typeof value === 'number' && Number.isFinite(value)) return value
if (typeof value === 'string' && value.trim() !== '') {
const numberValue = Number(value)
if (Number.isFinite(numberValue)) return numberValue
}
return null
}
const hasNumericTimelineValue = (item: AdminFileDetailTimelineItem) =>
normalizeTimelineNumber(item.value) !== null
const isLegacyUsedCountTimelineValue = (value: unknown) =>
typeof value === 'string' && legacyUsedCountTimelineKeys.has(value.trim())
const normalizeTimelineItem = (
item: AdminFileDetailTimelineItem,
fallbackUsedCount: number
) => {
const normalizedItem = { ...item }
if (legacyUsedCountTimelineKeys.has(normalizedItem.key)) {
normalizedItem.key = 'retrieved'
}
if (isLegacyUsedCountTimelineValue(normalizedItem.value)) {
normalizedItem.value = fallbackUsedCount > 0 ? fallbackUsedCount : null
}
return normalizedItem
}
const getTimelineTranslationKey = (item: AdminFileDetailTimelineItem) => {
if (
(item.key === 'retrieved' ||
item.key === 'retrieved_event' ||
legacyUsedCountTimelineKeys.has(item.key)) &&
!hasNumericTimelineValue(item) &&
!item.detail
) {
return 'retrieved_event_unknown'
}
return item.key
}
const formatTimelineValue = (item: AdminFileDetailTimelineItem) => {
if (item.key === 'download_limit') {
if (item.status === 'unlimited') return t('fileManage.unlimited')
if (typeof item.value === 'number') return t('fileManage.remaining', { count: item.value })
const numericValue = normalizeTimelineNumber(item.value)
if (numericValue !== null) return t('fileManage.remaining', { count: numericValue })
}
if (item.key === 'retrieved' && typeof item.value === 'number') {
return `${item.value} ${t('common.times')}`
if ((item.key === 'retrieved' || item.key === 'retrieved_event') && hasNumericTimelineValue(item)) {
return `${normalizeTimelineNumber(item.value)} ${t('common.times')}`
}
if (item.key === 'expiration_policy') {
if (item.status === 'unlimited') return t('send.expiration.units.forever')
if (typeof item.value === 'number') {
const duration = formatDuration(Math.abs(item.value), (key) => t(key))
return item.value <= 0
const numericValue = normalizeTimelineNumber(item.value)
if (numericValue !== null) {
const duration = formatDuration(Math.abs(numericValue), (key) => t(key))
return numericValue <= 0
? t('fileManage.timeline.expiration_policy.overdue', { time: duration })
: t('fileManage.timeline.expiration_policy.remaining', { time: duration })
}
}
if (item.detail) return item.detail
if (item.value !== null && item.value !== undefined) return String(item.value)
const numericValue = normalizeTimelineNumber(item.value)
if (numericValue !== null) return String(numericValue)
return ''
}
const createTimelineViewItems = (items: AdminFileDetailTimelineItem[] = []) =>
items.map((item) => {
const formatTimelineTitleValue = (item: AdminFileDetailTimelineItem, valueText: string) => {
if (item.key === 'retrieved_event') {
const numericValue = normalizeTimelineNumber(item.value)
return numericValue === null ? '' : String(numericValue)
}
return valueText
}
const createTimelineViewItems = (
items: AdminFileDetailTimelineItem[] = [],
fallbackUsedCount = 0
) =>
items.map((rawItem) => {
const item = normalizeTimelineItem(rawItem, fallbackUsedCount)
const timelineKey = getTimelineTranslationKey(item)
const timestampText = item.timestamp ? formatTimestamp(item.timestamp) : ''
const valueText = formatTimelineValue(item)
const titleValue = formatTimelineTitleValue(item, valueText)
const metaParts = [timestampText, valueText].filter(Boolean)
return {
...item,
severity: normalizeInsightSeverity(item.severity),
displayTitle: t(`fileManage.timeline.${item.key}.title`, {
displayTitle: t(`fileManage.timeline.${timelineKey}.title`, {
status: t(`fileManage.timeline.status.${item.status || 'pending'}`),
detail: item.detail || '',
value: valueText || item.value || ''
value: titleValue
}),
displayDescription: t(`fileManage.timeline.${item.key}.description`, {
displayDescription: t(`fileManage.timeline.${timelineKey}.description`, {
status: t(`fileManage.timeline.status.${item.status || 'pending'}`),
detail: item.detail || '',
value: valueText || ''
@@ -701,6 +766,14 @@ export function useAdminFiles() {
(viewItem.isExpiredFile ? 'expired' : isPermanentFile ? 'permanent' : 'available')
const statusInsightNextAction =
statusInsights?.nextAction ?? statusInsights?.next_action ?? 'monitor'
const usedCountValue = normalizeCount(
detail.usedCount ??
detail.used_count ??
statusInsights?.metrics?.usedCount ??
statusInsights?.metrics?.used_count ??
file.usedCount ??
file.used_count
)
const metadata = detail.metadata ?? detail.meta
const metadataNote = detail.note ?? metadata?.note ?? ''
const metadataTags = normalizeMetadataTags(detail.tags ?? metadata?.tags)
@@ -742,7 +815,7 @@ export function useAdminFiles() {
statusInsightNextAction,
statusInsightReasons: statusInsights?.reasons || [],
statusInsightMetrics: statusInsights?.metrics,
detailTimeline: createTimelineViewItems(detail.timeline || [])
detailTimeline: createTimelineViewItems(detail.timeline || [], usedCountValue)
}
}
+4
View File
@@ -618,6 +618,10 @@ export default {
retrieved_event: {
title: 'Retrieval #{value}',
description: 'This retrieval is complete; current status is {status}.'
},
retrieved_event_unknown: {
title: 'Retrieval History',
description: 'This retrieval is complete; current status is {status}.'
}
},
headers: {
+4
View File
@@ -615,6 +615,10 @@ export default {
retrieved_event: {
title: '第 {value} 次取件',
description: '本次取件已完成,当前状态为 {status}。'
},
retrieved_event_unknown: {
title: '取件记录',
description: '本次取件已完成,当前状态为 {status}。'
}
},
headers: {