mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-30 12:39:26 +08:00
fix(resource): 修复被 keep-alive 缓存的资源页在后台触发搜索并清空详情页参数的问题
- 路由查询参数监听增加前台页面判断,避免详情页携带的媒体身份参数触发后台资源搜索 - 搜索完成后仅在仍停留本页时清理地址栏参数,防止误删其他页面的 query - 补充回归测试
This commit is contained in:
@@ -931,6 +931,74 @@ describe('resource page search flow', () => {
|
||||
await latestEventSource(4)
|
||||
})
|
||||
|
||||
it('does not run a background search when another route updates the global query while the page is cached', async () => {
|
||||
const rendered = await renderResource({
|
||||
path: '/resource',
|
||||
query: { keyword: '前台搜索', result_type: 'torrent' },
|
||||
})
|
||||
const source = await latestEventSource()
|
||||
finishStream(source, [createTorrent({ title: '前台结果' })])
|
||||
await screen.findByText('前台结果')
|
||||
expect(EventSourceFake.instances).toHaveLength(1)
|
||||
|
||||
// 模拟 keep-alive 缓存页在后台时,媒体详情路由携带与资源搜索一致的媒体身份参数
|
||||
await rendered.router.push({
|
||||
path: '/media',
|
||||
query: {
|
||||
media_source: 'themoviedb',
|
||||
media_id: '42',
|
||||
title: '媒体标题',
|
||||
year: '2025',
|
||||
type: '电视剧',
|
||||
},
|
||||
})
|
||||
await flushAsyncWork()
|
||||
|
||||
expect(EventSourceFake.instances).toHaveLength(1)
|
||||
expect(mocks.apiGet).not.toHaveBeenCalledWith(
|
||||
'search/media/42',
|
||||
expect.objectContaining({ params: expect.objectContaining({ media_source: 'themoviedb' }) }),
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps the query of other routes when a search finishes after navigating away', async () => {
|
||||
const rendered = await renderResource({
|
||||
path: '/resource',
|
||||
query: { keyword: '待完成搜索', result_type: 'torrent' },
|
||||
})
|
||||
await latestEventSource()
|
||||
const replaceSpy = vi.spyOn(rendered.router, 'replace')
|
||||
|
||||
// 搜索未完成时跳转到媒体详情页,模拟详情页路由携带媒体身份参数
|
||||
await rendered.router.push({
|
||||
path: '/media',
|
||||
query: {
|
||||
media_source: 'themoviedb',
|
||||
media_id: '42',
|
||||
title: '媒体标题',
|
||||
year: '2025',
|
||||
type: '电视剧',
|
||||
},
|
||||
})
|
||||
await flushAsyncWork()
|
||||
|
||||
// 完成此刻仍处于打开状态的全部搜索流(含修复前的隐藏搜索流),
|
||||
// 确保任何残留搜索都不会清理其他页面的查询参数
|
||||
for (const source of EventSourceFake.instances) {
|
||||
finishStream(source, [createTorrent({ title: '后台结果' })])
|
||||
}
|
||||
await flushAsyncWork()
|
||||
|
||||
expect(replaceSpy).not.toHaveBeenCalled()
|
||||
expect(rendered.router.currentRoute.value.query).toEqual({
|
||||
media_source: 'themoviedb',
|
||||
media_id: '42',
|
||||
title: '媒体标题',
|
||||
year: '2025',
|
||||
type: '电视剧',
|
||||
})
|
||||
})
|
||||
|
||||
it('does not let a late business failure from an old fallback replace the current empty-state message', async () => {
|
||||
let resolveOldRequest!: (value: unknown) => void
|
||||
mocks.apiGet.mockReturnValueOnce(
|
||||
|
||||
@@ -1060,6 +1060,9 @@ async function fetchData(options: { force?: boolean; params?: SearchParams; sile
|
||||
} else {
|
||||
resetSearchResults()
|
||||
startLoadingProgress()
|
||||
// 记录发起搜索时的页面路径,搜索完成后只清理本页地址栏参数,
|
||||
// 避免用户搜索期间跳转其他页面(如媒体详情)时误删其 query 参数
|
||||
const searchPath = route.path
|
||||
try {
|
||||
await searchByStream(currentSearchParams, requestToken)
|
||||
} catch (error) {
|
||||
@@ -1077,7 +1080,7 @@ async function fetchData(options: { force?: boolean; params?: SearchParams; sile
|
||||
if (requestId !== activeSearchRequestId) return
|
||||
stopLoadingProgress()
|
||||
// 搜索完成后移除地址栏参数,避免分享/刷新残留搜索条件
|
||||
if (Object.keys(route.query).length > 0) {
|
||||
if (route.path === searchPath && Object.keys(route.query).length > 0) {
|
||||
await router.replace({ path: route.path, query: {} })
|
||||
}
|
||||
}
|
||||
@@ -1395,6 +1398,9 @@ watchEffect(() => {
|
||||
watch(
|
||||
() => route.query,
|
||||
query => {
|
||||
// 页面被 keep-alive 缓存后仍会响应全局路由变化;只有本页处于前台时才消费查询参数,
|
||||
// 否则详情页等路由携带的媒体身份参数会触发后台资源搜索
|
||||
if (route.path !== '/resource') return
|
||||
if (Object.keys(query).length === 0) return
|
||||
|
||||
const nextSearchParams = createSearchParams(query)
|
||||
|
||||
Reference in New Issue
Block a user