perf(frontend): 收敛导航预取并去重首屏请求

- 导航预取仅保留 pointerdown 触发,移除 mouseenter/focus,避免鼠标划过误触发
- 后台预取只做组件懒加载,不再预取各页业务数据,减少首屏资源争抢
- 版本状态检查增加 sessionStorage 缓存(正常 20 分钟 / 错误 5 分钟 TTL)
- fetchModules、必读公告拉取增加请求去重,避免并发重复请求
- 更新检查改用可清理的定时器,组件卸载时清理
- UsageRecordsTable 搜索防抖改为自定义实现,卸载时取消挂起 emit 并补充测试
This commit is contained in:
elky
2026-07-01 20:42:52 +08:00
parent a0f7074e59
commit 2e5ff32e1a
6 changed files with 158 additions and 110 deletions
@@ -1,5 +1,5 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { createApp, defineComponent, h, type App } from 'vue'
import { createApp, defineComponent, h, nextTick, type App } from 'vue'
import UsageRecordsTable from '../UsageRecordsTable.vue'
import type { UsageRecord } from '../../types'
@@ -167,6 +167,7 @@ afterEach(() => {
app.unmount()
root.remove()
}
vi.useRealTimers()
})
describe('UsageRecordsTable', () => {
@@ -314,6 +315,31 @@ describe('UsageRecordsTable', () => {
expect(onUpdateHideUnknownRecords).toHaveBeenCalledWith(true)
})
it('debounces usage search updates', async () => {
vi.useFakeTimers()
const onUpdateFilterSearch = vi.fn()
const root = mountUsageRecordsTable([buildRecord()], {
'onUpdate:filterSearch': onUpdateFilterSearch,
})
const input = root.querySelector<HTMLInputElement>('#usage-records-search')
expect(input).not.toBeNull()
input!.value = 'a'
input!.dispatchEvent(new Event('input'))
input!.value = 'ab'
input!.dispatchEvent(new Event('input'))
input!.value = 'abc'
input!.dispatchEvent(new Event('input'))
await nextTick()
await vi.advanceTimersByTimeAsync(299)
expect(onUpdateFilterSearch).not.toHaveBeenCalled()
await vi.advanceTimersByTimeAsync(1)
expect(onUpdateFilterSearch).toHaveBeenCalledTimes(1)
expect(onUpdateFilterSearch).toHaveBeenCalledWith('abc')
})
it('shows retry and fallback markers together when both flags are set', () => {
const root = mountUsageRecordsTable([buildRecord({
has_fallback: true,