feature: Clinical Review Mode: Charts, Replay Controls & Alert Reasoning

This commit is contained in:
voltsrage
2026-06-20 14:17:58 +08:00
parent 2ca0078223
commit ebd53f2df6
19 changed files with 939 additions and 9 deletions
@@ -0,0 +1,16 @@
export function formatTime(iso) {
if (!iso) return ''
return new Date(iso).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
}
const CODE_COLORS = {
HEART_RATE: '#ef4444',
RESP_RATE: '#3b82f6',
SYSTOLIC_BP: '#8b5cf6',
SPO2: '#06b6d4',
TEMP_C: '#f59e0b',
}
export function getColorForCode(code) {
return CODE_COLORS[code] ?? '#6b7280'
}
@@ -0,0 +1,26 @@
import { computed } from 'vue'
import { formatTime, getColorForCode } from './chartFormat'
export function useChartData(observations, code) {
const source = computed(() =>
(typeof observations === 'function' ? observations() : observations) ?? [])
const chartData = computed(() => {
const filtered = source.value
.filter(o => o.observationCode === code)
.sort((a, b) => new Date(a.recordedAt) - new Date(b.recordedAt))
return {
labels: filtered.map(o => formatTime(o.recordedAt)),
datasets: [{
label: code,
data: filtered.map(o => o.value),
borderColor: getColorForCode(code),
tension: 0.3,
pointRadius: 4,
}],
}
})
return { chartData }
}
@@ -0,0 +1,30 @@
import { ref, computed } from 'vue'
export function useReplayControls() {
const isPaused = ref(false)
const speed = ref(60)
const currentOffsetMinutes = ref(0)
const scenarioDurationMinutes = ref(0)
const progress = computed(() =>
scenarioDurationMinutes.value > 0
? (currentOffsetMinutes.value / scenarioDurationMinutes.value) * 100
: 0
)
const formattedTime = computed(() => {
const h = Math.floor(currentOffsetMinutes.value / 60)
const m = Math.floor(currentOffsetMinutes.value % 60)
return `${h}:${String(m).padStart(2, '0')}`
})
function pause() { isPaused.value = true }
function resume() { isPaused.value = false }
function setSpeed(s) { speed.value = s }
function jumpToOffset(offset) {
currentOffsetMinutes.value = offset
}
return { isPaused, speed, currentOffsetMinutes, scenarioDurationMinutes, progress, formattedTime, pause, resume, setSpeed, jumpToOffset }
}