diff --git a/clinical-web/src/views/reports/use-report-dataset.ts b/clinical-web/src/views/reports/use-report-dataset.ts index b00f3c8..789129d 100644 --- a/clinical-web/src/views/reports/use-report-dataset.ts +++ b/clinical-web/src/views/reports/use-report-dataset.ts @@ -1,4 +1,4 @@ -import { computed, ref, watch } from 'vue' +import { computed, effectScope, ref, watch } from 'vue' import { buildReportAnalyticsQuery, @@ -61,24 +61,38 @@ export async function loadReportDataset(): Promise { } } +/** + * 筛选监听挂在游离作用域上,不随第一个打开的报表页销毁。 + * + * 四个报表页共用一份 `reportFilter`,所以只需要一个监听、也只应有一个。但它必须 + * 由「模块」持有,而不是由「第一个调用 `useReportDataset()` 的组件」持有:在后端菜单 + * 资源没有开启缓存(`cacheable`)时,页面组件切走就会被卸载,普通 `watch` 会跟着组件 + * 的 effect scope 一起停掉;而 `filterWatcherInstalled` 已置为 true,之后任何页面都 + * 不会重新注册 —— 表现是离开过报表页之后,改筛选不再触发重查,看起来像「筛选不起效果」。 + * `effectScope(true)` 是游离作用域,生命周期与模块一致,切页面不受影响。 + */ +const filterWatcherScope = effectScope(true) + function installFilterWatcher() { if (filterWatcherInstalled) return filterWatcherInstalled = true - watch( - () => [ - reportFilter.dateRange, - reportFilter.customFrom, - reportFilter.customTo, - reportFilter.campus, - reportFilter.department, - reportFilter.category, - reportFilter.method, - ], - () => { - if (debounceTimer) clearTimeout(debounceTimer) - debounceTimer = setTimeout(() => void loadReportDataset(), 250) - }, - ) + filterWatcherScope.run(() => { + watch( + () => [ + reportFilter.dateRange, + reportFilter.customFrom, + reportFilter.customTo, + reportFilter.campus, + reportFilter.department, + reportFilter.category, + reportFilter.method, + ], + () => { + if (debounceTimer) clearTimeout(debounceTimer) + debounceTimer = setTimeout(() => void loadReportDataset(), 250) + }, + ) + }) } export function resetReportDataset(): void {