fix: 扫描缓存与真实大小计算,解决页面加载慢与数据虚增
- scanner: 大小改为统计实际 .tgz 文件(兼容 {version}.tgz 与 {pkg}-{version}.tgz 命名),
不再用 unpackedSize 兜底虚增数倍
- server: 扫描结果内存缓存(首次懒扫描,后续请求秒回),新增 POST /api/scan 手动重扫,
/api/packages 返回 scannedAt 时间戳,clean/删版本后自动失效缓存
- 前端: 概览页新增「重新扫描」按钮 + 「基于 xxx 扫描」时间展示;Top30 在真实环境
(无访问统计)降级为「缓存占用 Top 30」按大小排序
- compose: 数据卷改 named volume,修复非 root 容器 SQLITE_CANTOPEN
This commit is contained in:
@@ -12,6 +12,7 @@ const state = reactive({
|
||||
threshold: { versionThreshold: 15, sizeThreshold: 500, exceptions: [] },
|
||||
logs: [],
|
||||
loading: false,
|
||||
scannedAt: null,
|
||||
storageDir: localStorage.getItem('vcm-storage-dir') || '',
|
||||
})
|
||||
|
||||
@@ -23,8 +24,13 @@ const stats = computed(() => {
|
||||
const cleanable = valid.filter(p => p.status === 'warn').reduce((s, p) => s + p.size, 0)
|
||||
const maxPkg = [...valid].sort((a, b) => b.size - a.size)[0] || null
|
||||
const oldestPkg = [...valid].sort((a, b) => (a.lastUpdated || '').localeCompare(b.lastUpdated || ''))[0] || null
|
||||
const top30 = [...valid].sort((a, b) => (b.visits || 0) - (a.visits || 0)).slice(0, 30)
|
||||
// 真实环境无访问统计(visits 全 0)时,Top30 降级为「缓存占用 Top 30」
|
||||
const hasVisits = valid.some(p => (p.visits || 0) > 0)
|
||||
const top30 = [...valid]
|
||||
.sort((a, b) => (hasVisits ? (b.visits || 0) - (a.visits || 0) : b.size - a.size))
|
||||
.slice(0, 30)
|
||||
const maxVisit = Math.max(...top30.map(p => p.visits || 0), 1)
|
||||
const maxSize = Math.max(...top30.map(p => p.size), 1)
|
||||
return {
|
||||
pkgCount: valid.length,
|
||||
totalSize,
|
||||
@@ -34,7 +40,13 @@ const stats = computed(() => {
|
||||
cleanableText: fmtSize(cleanable),
|
||||
maxPkg,
|
||||
oldestPkg,
|
||||
top30: top30.map(p => ({ ...p, heat: Math.round(((p.visits || 0) / maxVisit) * 100) })),
|
||||
top30: top30.map(p => ({
|
||||
...p,
|
||||
heat: hasVisits
|
||||
? Math.round(((p.visits || 0) / maxVisit) * 100)
|
||||
: Math.round((p.size / maxSize) * 100),
|
||||
})),
|
||||
top30By: hasVisits ? 'visits' : 'size',
|
||||
}
|
||||
})
|
||||
|
||||
@@ -46,7 +58,16 @@ function fmtSize(mb) {
|
||||
const fmtSizeFn = fmtSize
|
||||
|
||||
async function refreshPackages(keyword = '') {
|
||||
state.packages = await api.getPackages(keyword)
|
||||
const { packages, scannedAt } = await api.getPackages(keyword)
|
||||
state.packages = packages
|
||||
if (scannedAt) state.scannedAt = scannedAt
|
||||
}
|
||||
|
||||
/** 手动重新扫描缓存目录 */
|
||||
async function scanNow() {
|
||||
const res = await api.scanNow()
|
||||
if (res.ok) await refreshAll()
|
||||
return res
|
||||
}
|
||||
|
||||
async function refreshThresholds() {
|
||||
@@ -113,6 +134,7 @@ export function useStore() {
|
||||
refreshPackages,
|
||||
refreshThresholds,
|
||||
refreshLogs,
|
||||
scanNow,
|
||||
saveThresholds,
|
||||
ignorePkg,
|
||||
unignorePkg,
|
||||
|
||||
Reference in New Issue
Block a user