mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
perf: 全栈查询优化、前端缓存去重与页面可见性优化
后端: - SQL count 查询统一改用 func.count() 子查询替代 query.count() - Dashboard/Audit 等页面多次独立查询合并为单次聚合查询 - Provider summary 列表改为批量查询消除 N+1 问题 - DailyStats 逐天循环查询改为 CASE 分桶单次查询 - 使用 load_only() 减少不必要的列加载 - cache_decorator 支持嵌套属性路径解析(dotted vary_by) - 多个管理/公共端点新增 @cache_result 缓存装饰 前端: - cache.ts 新增 in-flight 请求复用、dedupedRequest、buildCacheKey - 大量 API 调用添加前端缓存或去重 - 多个页面定时器在标签页隐藏时暂停、可见时恢复 - Auth 检查从 setInterval 改为 storage + visibilitychange 事件驱动 - 请求竞态防护(requestId 模式) 数据库: - Usage 表新增 idx_usage_status_user_created 复合索引
This commit is contained in:
@@ -911,6 +911,8 @@ const showDetail = ref(false)
|
||||
const selectedTask = ref<AsyncTaskDetail | null>(null)
|
||||
const detailAutoRefresh = ref(false)
|
||||
let detailRefreshInterval: ReturnType<typeof setInterval> | null = null
|
||||
const isPageVisible = ref(typeof document === 'undefined' ? true : !document.hidden)
|
||||
let overviewRefreshInFlight = false
|
||||
|
||||
// 使用记录详情抽屉状态
|
||||
const usageDetailOpen = ref(false)
|
||||
@@ -953,6 +955,16 @@ async function fetchStats() {
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshOverview() {
|
||||
if (overviewRefreshInFlight) return
|
||||
overviewRefreshInFlight = true
|
||||
try {
|
||||
await Promise.all([fetchTasks(), fetchStats()])
|
||||
} finally {
|
||||
overviewRefreshInFlight = false
|
||||
}
|
||||
}
|
||||
|
||||
// 打开任务详情
|
||||
async function openTaskDetail(task: AsyncTaskItem) {
|
||||
try {
|
||||
@@ -993,22 +1005,27 @@ function toggleDetailAutoRefresh() {
|
||||
|
||||
// 开始详情自动刷新
|
||||
function startDetailAutoRefresh() {
|
||||
if (!isPageVisible.value) return
|
||||
if (detailRefreshInterval) return
|
||||
// 立即刷新一次
|
||||
refreshTaskDetail()
|
||||
detailRefreshInterval = setInterval(() => {
|
||||
if (selectedTask.value && showDetail.value) {
|
||||
if (isPageVisible.value && selectedTask.value && showDetail.value) {
|
||||
refreshTaskDetail()
|
||||
}
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
// 停止详情自动刷新
|
||||
function stopDetailAutoRefresh() {
|
||||
function pauseDetailAutoRefresh() {
|
||||
if (detailRefreshInterval) {
|
||||
clearInterval(detailRefreshInterval)
|
||||
detailRefreshInterval = null
|
||||
}
|
||||
}
|
||||
|
||||
// 停止详情自动刷新
|
||||
function stopDetailAutoRefresh() {
|
||||
pauseDetailAutoRefresh()
|
||||
detailAutoRefresh.value = false
|
||||
}
|
||||
|
||||
@@ -1052,8 +1069,7 @@ async function cancelTask(task: AsyncTaskItem | AsyncTaskDetail) {
|
||||
toast({
|
||||
title: '任务已取消',
|
||||
})
|
||||
fetchTasks()
|
||||
fetchStats()
|
||||
await refreshOverview()
|
||||
if (showDetail.value) {
|
||||
closeDetail()
|
||||
}
|
||||
@@ -1222,11 +1238,11 @@ let autoRefreshInterval: ReturnType<typeof setInterval> | null = null
|
||||
const AUTO_REFRESH_INTERVAL = 5000 // 5秒
|
||||
|
||||
function startAutoRefresh() {
|
||||
if (!isPageVisible.value) return
|
||||
if (autoRefreshInterval) return
|
||||
autoRefreshInterval = setInterval(() => {
|
||||
if (hasProcessingTasks.value && !loading.value) {
|
||||
fetchTasks()
|
||||
fetchStats()
|
||||
if (isPageVisible.value && hasProcessingTasks.value && !loading.value) {
|
||||
refreshOverview()
|
||||
}
|
||||
}, AUTO_REFRESH_INTERVAL)
|
||||
}
|
||||
@@ -1240,19 +1256,35 @@ function stopAutoRefresh() {
|
||||
|
||||
// 监听是否有进行中的任务,动态启停自动刷新
|
||||
watch(hasProcessingTasks, (has) => {
|
||||
if (has) {
|
||||
if (has && isPageVisible.value) {
|
||||
startAutoRefresh()
|
||||
} else {
|
||||
stopAutoRefresh()
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
function handleVisibilityChange() {
|
||||
isPageVisible.value = !document.hidden
|
||||
if (!isPageVisible.value) {
|
||||
stopAutoRefresh()
|
||||
pauseDetailAutoRefresh()
|
||||
return
|
||||
}
|
||||
if (hasProcessingTasks.value) {
|
||||
startAutoRefresh()
|
||||
}
|
||||
if (detailAutoRefresh.value && selectedTask.value && showDetail.value) {
|
||||
startDetailAutoRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchTasks()
|
||||
fetchStats()
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange)
|
||||
refreshOverview()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange)
|
||||
stopAutoRefresh()
|
||||
stopDetailAutoRefresh()
|
||||
clearTimeout(filterTimeout)
|
||||
|
||||
Reference in New Issue
Block a user