fix: finish all patient related upgrades

This commit is contained in:
voltsrage
2026-06-23 18:17:13 +08:00
parent 7751d6df06
commit 5d46200941
20 changed files with 985 additions and 19 deletions
@@ -8,6 +8,7 @@ import { useAlertStore } from '@/stores/alerts'
import { useScoringStore } from '@/stores/scoring'
import * as encountersApi from '@/api/encounters'
import * as clinicalApi from '@/api/clinical'
import PatientBanner from '@/components/patient/PatientBanner.vue'
import VitalsPanel from '@/components/patient/VitalsPanel.vue'
import ScoresPanel from '@/components/patient/ScoresPanel.vue'
import SofaScorePanel from '@/components/patient/SofaScorePanel.vue'
@@ -19,6 +20,7 @@ import News2History from '@/components/charts/News2History.vue'
import GcsHistory from '@/components/charts/GcsHistory.vue'
import QsofaHistory from '@/components/charts/QsofaHistory.vue'
import SofaHistory from '@/components/charts/SofaHistory.vue'
import EncounterTimeline from '@/components/patient/EncounterTimeline.vue'
import ReplayControls from '@/components/replay/ReplayControls.vue'
import AlertReasoning from '@/components/alerts/AlertReasoning.vue'
import Skeleton from '@/components/ui/Skeleton.vue'
@@ -56,6 +58,7 @@ const sofaHistory = ref([])
const medications = ref([])
const sepsisBundle = ref(null)
const orders = ref([])
const timelineEvents = ref([])
const selectedAlert = ref(null)
let nextAlertIndex = 0
@@ -67,6 +70,10 @@ const replayObservations = computed(() =>
observations.value.filter(o => isAtOrBefore(o.recordedAt)),
)
const replayMedications = computed(() =>
medications.value.filter(m => isAtOrBefore(m.administeredAt)),
)
const replayNews2History = computed(() =>
news2History.value.filter(h => isAtOrBefore(h.calculatedAt)),
)
@@ -83,6 +90,10 @@ const replaySofaHistory = computed(() =>
sofaHistory.value.filter(h => isAtOrBefore(h.calculatedAt)),
)
const replayTimelineEvents = computed(() =>
timelineEvents.value.filter(e => isAtOrBefore(e.timestamp)),
)
function collectScenarioTimes() {
return [
...observations.value.map(o => new Date(o.recordedAt).getTime()),
@@ -90,6 +101,7 @@ function collectScenarioTimes() {
...gcsHistory.value.map(h => new Date(h.calculatedAt).getTime()),
...qsofaHistory.value.map(h => new Date(h.evaluatedAt).getTime()),
...sofaHistory.value.map(h => new Date(h.calculatedAt).getTime()),
...timelineEvents.value.map(e => new Date(e.timestamp).getTime()),
...alerts.value.map(a => new Date(a.triggeredAt).getTime()),
].filter(Number.isFinite)
}
@@ -109,7 +121,7 @@ async function loadAll() {
const id = route.params.encounterId
loading.value = true
try {
const [enc, obs, history, gcsHist, qsofaHist, sofaHist, meds, bundle, ord] = await Promise.all([
const [enc, obs, history, gcsHist, qsofaHist, sofaHist, meds, bundle, ord, timeline] = await Promise.all([
encountersApi.fetchEncounter(id),
encountersApi.fetchObservations(id),
clinicalApi.fetchNews2History(id).catch(() => []),
@@ -119,6 +131,7 @@ async function loadAll() {
clinicalApi.fetchMedications(id).catch(() => []),
clinicalApi.fetchSepsisBundle(id),
clinicalApi.fetchOrders(id).catch(() => ({ items: [] })),
encountersApi.fetchTimeline(id).catch(() => ({ events: [] })),
])
await alertStore.loadAlerts(id)
encounter.value = enc
@@ -130,6 +143,7 @@ async function loadAll() {
medications.value = meds
sepsisBundle.value = bundle
orders.value = ord.items ?? ord
timelineEvents.value = timeline.events ?? []
scoringStore.startPolling(id)
syncReplayBounds()
} finally {
@@ -174,7 +188,7 @@ watch(openAlerts, (list) => {
}
})
watch([observations, news2History, gcsHistory, qsofaHistory, sofaHistory, alerts], syncReplayBounds, { deep: true })
watch([observations, news2History, gcsHistory, qsofaHistory, sofaHistory, timelineEvents, alerts], syncReplayBounds, { deep: true })
onBeforeUnmount(() => {
stopPlayback()
@@ -189,11 +203,10 @@ onBeforeUnmount(() => {
<RouterLink to="/ward" class="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
&larr; Ward
</RouterLink>
<h1 class="text-xl font-bold dark:text-white">
{{ encounter.patient?.firstName }} {{ encounter.patient?.lastName }}
</h1>
</div>
<PatientBanner :encounter="encounter" />
<div class="grid min-w-0 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<div class="space-y-4">
<ScoresPanel />
@@ -227,8 +240,10 @@ onBeforeUnmount(() => {
:sofa="sofa"
/>
<EncounterTimeline :events="replayTimelineEvents" />
<div id="clinical-review" class="w-full min-w-0 space-y-8">
<TrendsGrid :observations="replayObservations" />
<TrendsGrid :observations="replayObservations" :medications="replayMedications" />
<News2History v-if="replayNews2History.length" :history="replayNews2History" />
<QsofaHistory v-if="replayQsofaHistory.length" :history="replayQsofaHistory" />
<ReplayControls