feat: add dashboard health actions

This commit is contained in:
Lan
2026-06-03 06:15:15 +08:00
parent a573f1f5cc
commit 47edefbdd7
8 changed files with 394 additions and 39 deletions
+45 -2
View File
@@ -46,6 +46,8 @@ const emptySummary = (): AdminFileSummary => ({
expiringSoonCount: 0,
storageIssueCount: 0,
neverRetrievedCount: 0,
healthyCount: 0,
permanentCount: 0,
storageUsed: 0,
usedCount: 0
})
@@ -219,7 +221,12 @@ export function useAdminFiles() {
{
value: 'healthy',
label: t('fileManage.healthFilters.healthy'),
count: Math.max(summary.value.totalFiles - summary.value.healthAttentionCount, 0)
count: summary.value.healthyCount
},
{
value: 'permanent',
label: t('fileManage.healthFilters.permanent'),
count: summary.value.permanentCount
}
])
@@ -305,6 +312,8 @@ export function useAdminFiles() {
neverRetrievedCount: files.filter((file) =>
file.statusInsightReasons.includes('never_retrieved')
).length,
healthyCount: files.filter((file) => file.statusInsightSeverity === 'success').length,
permanentCount: files.filter((file) => file.statusInsightState === 'permanent').length,
storageUsed: files.reduce((totalSize, file) => totalSize + normalizeCount(file.size), 0),
usedCount: files.reduce(
(totalUsed, file) => totalUsed + normalizeCount(file.usedCount ?? file.used_count),
@@ -312,6 +321,40 @@ export function useAdminFiles() {
)
})
const normalizeSummary = (
rawSummary: Partial<AdminFileSummary> | undefined,
files: AdminFileViewItem[],
total: number
): AdminFileSummary => {
const fallback = buildFallbackSummary(files, total)
if (!rawSummary) return fallback
return {
totalFiles: normalizeCount(rawSummary.totalFiles ?? fallback.totalFiles),
activeCount: normalizeCount(rawSummary.activeCount ?? fallback.activeCount),
expiredCount: normalizeCount(rawSummary.expiredCount ?? fallback.expiredCount),
textCount: normalizeCount(rawSummary.textCount ?? fallback.textCount),
fileCount: normalizeCount(rawSummary.fileCount ?? fallback.fileCount),
chunkedCount: normalizeCount(rawSummary.chunkedCount ?? fallback.chunkedCount),
healthAttentionCount: normalizeCount(
rawSummary.healthAttentionCount ?? fallback.healthAttentionCount
),
healthDangerCount: normalizeCount(rawSummary.healthDangerCount ?? fallback.healthDangerCount),
healthWarningCount: normalizeCount(
rawSummary.healthWarningCount ?? fallback.healthWarningCount
),
expiringSoonCount: normalizeCount(rawSummary.expiringSoonCount ?? fallback.expiringSoonCount),
storageIssueCount: normalizeCount(rawSummary.storageIssueCount ?? fallback.storageIssueCount),
neverRetrievedCount: normalizeCount(
rawSummary.neverRetrievedCount ?? fallback.neverRetrievedCount
),
healthyCount: normalizeCount(rawSummary.healthyCount ?? fallback.healthyCount),
permanentCount: normalizeCount(rawSummary.permanentCount ?? fallback.permanentCount),
storageUsed: normalizeCount(rawSummary.storageUsed ?? fallback.storageUsed),
usedCount: normalizeCount(rawSummary.usedCount ?? fallback.usedCount)
}
}
const normalizeInsightSeverity = (
severity: AdminFileInsightSeverity | undefined
): AdminFileInsightSeverity => {
@@ -684,7 +727,7 @@ export function useAdminFiles() {
tableData.value = res.detail.data.map(createFileViewItem)
params.value.total = res.detail.total
summary.value = res.detail.summary || buildFallbackSummary(tableData.value, res.detail.total)
summary.value = normalizeSummary(res.detail.summary, tableData.value, res.detail.total)
syncSelectedFilesWithCurrentPage()
} catch (error) {
hasLoadError.value = true
+49 -1
View File
@@ -1,6 +1,6 @@
import { computed, ref, reactive } from 'vue'
import { StatsService } from '@/services'
import type { DashboardViewData } from '@/types'
import type { DashboardData, DashboardHealthSummary, DashboardViewData } from '@/types'
import { formatFileSize, getErrorMessage } from '@/utils/common'
type UseDashboardStatsOptions = {
@@ -27,6 +27,14 @@ const emptyDashboardData = (): DashboardViewData => ({
openUpload: 0,
enableChunk: 0,
maxSaveSeconds: 0,
healthAttentionCount: 0,
healthDangerCount: 0,
healthWarningCount: 0,
expiringSoonCount: 0,
storageIssueCount: 0,
neverRetrievedCount: 0,
healthyCount: 0,
permanentCount: 0,
topSuffixes: [],
recentFiles: [],
storageUsedText: '0 Bytes',
@@ -37,6 +45,8 @@ const emptyDashboardData = (): DashboardViewData => ({
activeRatio: 0,
textRatio: 0,
fileRatio: 0,
healthyRatio: 0,
healthAttentionRatio: 0,
todaySizeRatio: 0
})
@@ -62,6 +72,34 @@ const normalizeRecentFiles = (recentFiles: DashboardViewData['recentFiles']) =>
usedCount: toNumber(file.usedCount)
}))
const healthSummaryKeys: (keyof DashboardHealthSummary)[] = [
'healthAttentionCount',
'healthDangerCount',
'healthWarningCount',
'expiringSoonCount',
'storageIssueCount',
'neverRetrievedCount',
'healthyCount',
'permanentCount'
]
const normalizeHealthSummary = (detail: DashboardData): DashboardHealthSummary => ({
healthAttentionCount: toNumber(
detail.healthSummary?.healthAttentionCount ?? detail.healthAttentionCount
),
healthDangerCount: toNumber(detail.healthSummary?.healthDangerCount ?? detail.healthDangerCount),
healthWarningCount: toNumber(
detail.healthSummary?.healthWarningCount ?? detail.healthWarningCount
),
expiringSoonCount: toNumber(detail.healthSummary?.expiringSoonCount ?? detail.expiringSoonCount),
storageIssueCount: toNumber(detail.healthSummary?.storageIssueCount ?? detail.storageIssueCount),
neverRetrievedCount: toNumber(
detail.healthSummary?.neverRetrievedCount ?? detail.neverRetrievedCount
),
healthyCount: toNumber(detail.healthSummary?.healthyCount ?? detail.healthyCount),
permanentCount: toNumber(detail.healthSummary?.permanentCount ?? detail.permanentCount)
})
export function useDashboardStats(options: UseDashboardStatsOptions = {}) {
const dashboardData = reactive<DashboardViewData>(emptyDashboardData())
const isLoading = ref(false)
@@ -103,6 +141,10 @@ export function useDashboardStats(options: UseDashboardStatsOptions = {}) {
dashboardData.openUpload = toNumber(detail.openUpload)
dashboardData.enableChunk = toNumber(detail.enableChunk)
dashboardData.maxSaveSeconds = toNumber(detail.maxSaveSeconds)
const healthSummary = normalizeHealthSummary(detail)
healthSummaryKeys.forEach((key) => {
dashboardData[key] = healthSummary[key]
})
dashboardData.topSuffixes = detail.topSuffixes || []
dashboardData.recentFiles = normalizeRecentFiles(detail.recentFiles || [])
@@ -120,6 +162,12 @@ export function useDashboardStats(options: UseDashboardStatsOptions = {}) {
dashboardData.fileRatio = dashboardData.totalFiles
? clampRatio((dashboardData.fileCount / dashboardData.totalFiles) * 100)
: 0
dashboardData.healthyRatio = dashboardData.totalFiles
? clampRatio((dashboardData.healthyCount / dashboardData.totalFiles) * 100)
: 0
dashboardData.healthAttentionRatio = dashboardData.totalFiles
? clampRatio((dashboardData.healthAttentionCount / dashboardData.totalFiles) * 100)
: 0
dashboardData.todaySizeRatio = dashboardData.uploadSizeLimit
? clampRatio((dashboardData.todaySize / dashboardData.uploadSizeLimit) * 100)
: 0