feature: Optional OCR-Assisted Draft Pre-Fill

This commit is contained in:
voltsrage
2026-06-28 01:28:54 +08:00
parent 5039dbb979
commit c160c5f912
42 changed files with 3592 additions and 33 deletions
@@ -12,6 +12,11 @@
<p class="text-sm text-red-700">{{ batch.rejectionReason }}</p>
</div>
<div v-if="ocrConfidence" class="ocr-banner">
Values pre-filled by OCR ({{ ocrConfidence.provider }}).
Colored borders indicate extraction confidence verify each value against the scan.
</div>
<!-- Patient review -->
<fieldset class="border border-gray-200 rounded-md p-4">
<legend class="text-sm font-medium text-gray-700 px-2">Patient Demographics</legend>
@@ -26,7 +31,10 @@
/>
<label class="text-xs text-gray-500">{{ field.label }}</label>
</div>
<p class="text-sm mt-2 pl-8 font-medium">
<p
class="text-sm mt-2 pl-8 font-medium"
:class="fieldConfidenceClass(field.path)"
>
{{ field.value || '(empty)' }}
</p>
</div>
@@ -47,7 +55,10 @@
/>
<label class="text-xs text-gray-500">{{ field.label }}</label>
</div>
<p class="text-sm mt-2 pl-8 font-medium">
<p
class="text-sm mt-2 pl-8 font-medium"
:class="fieldConfidenceClass(field.path)"
>
{{ field.value || '(empty)' }}
</p>
</div>
@@ -68,7 +79,10 @@
/>
<label class="text-xs text-gray-500">{{ field.label }}</label>
</div>
<p class="text-sm mt-2 pl-8 font-medium">
<p
class="text-sm mt-2 pl-8 font-medium"
:class="fieldConfidenceClass(field.path)"
>
{{ field.value || '(empty)' }}
</p>
</div>
@@ -89,7 +103,10 @@
/>
<label class="text-xs text-gray-500">{{ field.label }}</label>
</div>
<p class="text-sm mt-2 pl-8 font-medium">
<p
class="text-sm mt-2 pl-8 font-medium"
:class="fieldConfidenceClass(field.path)"
>
{{ field.value || '(empty)' }}
</p>
</div>
@@ -109,6 +126,7 @@
:readonly="true"
:show-verified="true"
:verified="fieldChecks[`observations[${index}].value`] ?? false"
:value-input-class="observationValueConfidenceClass(obs.observationCode)"
@verify="(_obsId, passed) => toggleCheck(`observations[${index}].value`, passed)"
/>
</div>
@@ -190,6 +208,7 @@ import { ref, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useBatchStore } from '../stores/batches'
import { useToast } from '../composables/useToast'
import { useOcrFieldConfidence } from '../composables/useOcrFieldConfidence'
import ObservationRow from '../components/ObservationRow.vue'
import type { BatchDetailResponse, DraftObservation } from '../types'
@@ -221,6 +240,14 @@ const medicationFields = ref<FieldInfo[]>([])
const encounterFields = ref<FieldInfo[]>([])
const fieldReqs = computed(() => batchStore.currentDraft?.fieldRequirements)
const ocrConfidence = computed(() => batchStore.currentDraft?.ocrConfidence ?? null)
const { fieldConfidenceClass } = useOcrFieldConfidence(ocrConfidence)
function observationValueConfidenceClass(observationCode: string): string {
if (!observationCode) return ''
return fieldConfidenceClass(`observation.${observationCode}.value`)
}
const showAllergies = computed(() => fieldReqs.value?.showAllergies ?? false)
const showMedications = computed(() => fieldReqs.value?.showMedications ?? false)
const showEncounterSummary = computed(() => fieldReqs.value?.showEncounterSummaryFields ?? false)