Files
xh-medical-sign-web/clinical-web/src/views/reports/use-report-dataset.ts
T

112 lines
3.0 KiB
TypeScript

import { computed, ref, watch } from 'vue'
import {
buildReportAnalyticsQuery,
getReportAnalytics,
getReportOptions,
type ReportAnalyticsDataset,
type ReportOptions,
} from '@/api/workbench/report-analytics'
import { toUserMessage } from '@/utils/api-response'
import { resolveDateWindow } from './aggregate'
import { reportFilter } from './filter-store'
const dataset = ref<ReportAnalyticsDataset | null>(null)
const options = ref<ReportOptions | null>(null)
const loading = ref(false)
const errorMessage = ref('')
const optionsError = ref('')
let requestSequence = 0
let pendingOptions: Promise<void> | null = null
let filterWatcherInstalled = false
let debounceTimer: ReturnType<typeof setTimeout> | null = null
export function loadReportOptions(): Promise<void> {
if (options.value) return Promise.resolve()
pendingOptions ??= (async () => {
optionsError.value = ''
try {
options.value = await getReportOptions()
} catch (error) {
optionsError.value = toUserMessage(error, '报表筛选项加载失败')
} finally {
pendingOptions = null
}
})()
return pendingOptions
}
export async function loadReportDataset(): Promise<void> {
const sequence = ++requestSequence
dataset.value = null
const dateWindow = resolveDateWindow(reportFilter)
if (!dateWindow) {
errorMessage.value = ''
loading.value = false
return
}
loading.value = true
errorMessage.value = ''
try {
const query = buildReportAnalyticsQuery(reportFilter, dateWindow)
const result = await getReportAnalytics(query)
if (sequence === requestSequence) dataset.value = result
} catch (error) {
if (sequence === requestSequence) errorMessage.value = toUserMessage(error, '报表数据加载失败')
} finally {
if (sequence === requestSequence) loading.value = false
}
}
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)
},
)
}
export function resetReportDataset(): void {
dataset.value = null
requestSequence++
if (debounceTimer) clearTimeout(debounceTimer)
}
export function useReportDataset() {
installFilterWatcher()
const window = computed(() => resolveDateWindow(reportFilter))
const available = computed(() => dataset.value !== null)
const generatedAt = computed(() => dataset.value?.generatedAt ?? '')
const customRangeIncomplete = computed(
() =>
reportFilter.dateRange === 'custom' && (!reportFilter.customFrom || !reportFilter.customTo),
)
return {
dataset,
options,
window,
available,
generatedAt,
loading,
errorMessage,
optionsError,
customRangeIncomplete,
}
}