适配 M002 V3 字段矩阵前端交互

This commit is contained in:
andy
2026-07-12 09:23:03 +08:00
parent db95aece20
commit 9bd6bc1cd0
11 changed files with 515 additions and 66 deletions

View File

@@ -55,14 +55,14 @@
>
<label
v-for="(item, index) in supportedMissingFields"
:key="item.pointer"
:key="item.key"
>
<span>
{{ item.label }}
<small class="th-code">{{ item.pointer }}</small>
<small class="th-code">{{ item.pointer ?? item.fieldPath }}</small>
</span>
<input
v-model="fieldOverrideInputs[item.pointer]"
v-model="fieldOverrideInputs[item.key]"
:name="`manual_resolution_field_override_${index}`"
type="text"
:disabled="busy"
@@ -124,11 +124,15 @@ import type {
ReservationTaskFieldResult,
} from '@/types/reservation'
import { normalizeStableCode } from '@/utils/reservationDisplay'
import { readReservationFieldValue } from '@/utils/reservationFieldRules'
const supportedFieldPointers = [
'/extracted_fields/pms_room_type_code',
'/extracted_fields/room_items/0/pms_room_type_code',
] as const
interface ManualResolutionFieldItem {
key: string
pointer?: string
fieldPath: string
label: string
field?: ReservationTaskFieldResult
}
const props = withDefaults(
defineProps<{
@@ -163,17 +167,14 @@ const isResolved = computed(() => normalizeStableCode(props.reviewStatus) === 'R
const reviewStatusLabel = computed(() => props.reviewStatus || t('task.manualResolution.pendingStatus'))
const supportedMissingFields = computed(() =>
extractMissingFields(props.manualReview)
.filter((pointer) => supportedFieldPointers.includes(pointer as (typeof supportedFieldPointers)[number]))
.map((pointer) => ({
pointer,
label: findFieldLabel(pointer),
})),
.map((reference) => resolveMissingField(reference))
.filter((item): item is ManualResolutionFieldItem => item !== null),
)
const canSubmit = computed(() => {
if (!supportedMissingFields.value.length || !confirmedOrderId.value.trim()) {
return false
}
return supportedMissingFields.value.every((item) => String(fieldOverrideInputs.value[item.pointer] ?? '').trim())
return supportedMissingFields.value.every((item) => String(fieldOverrideInputs.value[item.key] ?? '').trim())
})
watch(
@@ -188,7 +189,7 @@ watch(
(items) => {
const nextInputs: Record<string, string> = {}
items.forEach((item) => {
nextInputs[item.pointer] = fieldOverrideInputs.value[item.pointer] || readCurrentFieldValue(item.pointer)
nextInputs[item.key] = fieldOverrideInputs.value[item.key] || readCurrentFieldValue(item)
})
fieldOverrideInputs.value = nextInputs
},
@@ -206,8 +207,9 @@ function submitResolution(): void {
confirmed_order_id: confirmedOrderId.value.trim(),
reason: reason.value.trim() || undefined,
field_overrides: supportedMissingFields.value.map((item) => ({
field_pointer: item.pointer,
value: String(fieldOverrideInputs.value[item.pointer] ?? '').trim(),
...(item.pointer ? { field_pointer: item.pointer } : {}),
field_path: item.fieldPath,
value: String(fieldOverrideInputs.value[item.key] ?? '').trim(),
})),
})
}
@@ -217,24 +219,37 @@ function extractMissingFields(manualReview: ReservationRecord | null | undefined
if (!Array.isArray(missingFields)) {
return []
}
return missingFields.filter((item): item is string => typeof item === 'string' && item.startsWith('/'))
return missingFields.filter((item): item is string => typeof item === 'string' && item.trim() !== '')
}
function findFieldLabel(pointer: string): string {
const fieldPath = fieldPointerToFieldPath(pointer)
return props.fields.find((field) => field.field_path === fieldPath)?.display_name ?? fieldPath
function resolveMissingField(reference: string): ManualResolutionFieldItem | null {
const pointer = reference.startsWith('/') ? reference : undefined
const referenceFieldPath = pointer ? fieldPointerToFieldPath(pointer) : reference
const field = props.fields.find((item) =>
item.field_pointer === reference ||
item.field_path === referenceFieldPath ||
item.legacy_field_path === referenceFieldPath,
)
if (field) {
return {
key: field.field_pointer ?? field.field_path,
pointer: field.field_pointer ?? pointer,
fieldPath: field.field_path,
label: field.display_name,
field,
}
}
return null
}
function readCurrentFieldValue(pointer: string): string {
const fieldPath = fieldPointerToFieldPath(pointer)
const value = props.fieldValues[fieldPath] ?? props.fields.find((field) => field.field_path === fieldPath)?.value
function readCurrentFieldValue(item: ManualResolutionFieldItem): string {
const value = item.field
? readReservationFieldValue(item.field, props.fieldValues)
: props.fieldValues[item.fieldPath]
return value === undefined || value === null ? '' : String(value)
}
function fieldPointerToFieldPath(pointer: string): string {
if (pointer === '/extracted_fields/room_items/0/pms_room_type_code') {
return 'extracted_fields.pms_room_type_code'
}
return pointer.replace(/^\//, '').replace(/\//g, '.')
}