修复人工复核必填字段提交
This commit is contained in:
@@ -141,6 +141,7 @@ import type {
|
||||
} from '@/types/reservation'
|
||||
import { normalizeStableCode } from '@/utils/reservationDisplay'
|
||||
import {
|
||||
isReservationFieldRequired,
|
||||
isReservationManualReviewFieldWritable,
|
||||
readReservationFieldValue,
|
||||
} from '@/utils/reservationFieldRules'
|
||||
@@ -184,11 +185,7 @@ const formErrorMessage = ref('')
|
||||
const fieldOverrideInputs = ref<Record<string, string>>({})
|
||||
const isResolved = computed(() => normalizeStableCode(props.reviewStatus) === 'RESOLVED')
|
||||
const reviewStatusLabel = computed(() => props.reviewStatus || t('task.manualResolution.pendingStatus'))
|
||||
const supportedMissingFields = computed(() =>
|
||||
extractMissingFields(props.manualReview)
|
||||
.map((reference) => resolveMissingField(reference))
|
||||
.filter((item): item is ManualResolutionFieldItem => item !== null),
|
||||
)
|
||||
const supportedMissingFields = computed(() => buildReviewFieldItems())
|
||||
const unsupportedMissingFields = computed(() =>
|
||||
extractMissingFields(props.manualReview).filter((reference) => resolveMissingField(reference) === null),
|
||||
)
|
||||
@@ -253,17 +250,58 @@ function resolveMissingField(reference: string): ManualResolutionFieldItem | nul
|
||||
item.legacy_field_path === referenceFieldPath,
|
||||
)
|
||||
if (field && isReservationManualReviewFieldWritable(field)) {
|
||||
return {
|
||||
key: field.field_pointer ?? field.field_path,
|
||||
pointer: field.field_pointer ?? pointer,
|
||||
fieldPath: field.field_path,
|
||||
label: field.display_name,
|
||||
field,
|
||||
}
|
||||
return reviewFieldItemFromField(field, pointer)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function buildReviewFieldItems(): ManualResolutionFieldItem[] {
|
||||
const items: ManualResolutionFieldItem[] = []
|
||||
const seenKeys = new Set<string>()
|
||||
extractMissingFields(props.manualReview).forEach((reference) => {
|
||||
const item = resolveMissingField(reference)
|
||||
if (item) {
|
||||
appendReviewFieldItem(items, seenKeys, item)
|
||||
}
|
||||
})
|
||||
props.fields
|
||||
.filter((field) => isReservationManualReviewFieldWritable(field))
|
||||
.filter((field) => isReservationFieldRequired(field))
|
||||
.filter((field) => isEmptyReviewFieldValue(readReservationFieldValue(field, props.fieldValues)))
|
||||
.forEach((field) => appendReviewFieldItem(items, seenKeys, reviewFieldItemFromField(field)))
|
||||
return items
|
||||
}
|
||||
|
||||
function reviewFieldItemFromField(
|
||||
field: ReservationTaskFieldResult,
|
||||
fallbackPointer?: string,
|
||||
): ManualResolutionFieldItem {
|
||||
return {
|
||||
key: field.field_pointer ?? field.field_path,
|
||||
pointer: field.field_pointer ?? fallbackPointer,
|
||||
fieldPath: field.field_path,
|
||||
label: field.display_name,
|
||||
field,
|
||||
}
|
||||
}
|
||||
|
||||
function appendReviewFieldItem(
|
||||
items: ManualResolutionFieldItem[],
|
||||
seenKeys: Set<string>,
|
||||
item: ManualResolutionFieldItem,
|
||||
): void {
|
||||
const dedupeKeys = [
|
||||
item.pointer,
|
||||
item.fieldPath,
|
||||
item.field?.legacy_field_path,
|
||||
].filter((key): key is string => Boolean(key))
|
||||
if (dedupeKeys.some((key) => seenKeys.has(key))) {
|
||||
return
|
||||
}
|
||||
dedupeKeys.forEach((key) => seenKeys.add(key))
|
||||
items.push(item)
|
||||
}
|
||||
|
||||
function readCurrentFieldValue(item: ManualResolutionFieldItem): string {
|
||||
const value = item.field
|
||||
? readReservationFieldValue(item.field, props.fieldValues)
|
||||
@@ -275,6 +313,19 @@ function fieldPointerToFieldPath(pointer: string): string {
|
||||
return pointer.replace(/^\//, '').replace(/\//g, '.')
|
||||
}
|
||||
|
||||
function isEmptyReviewFieldValue(value: unknown): boolean {
|
||||
if (value === null || value === undefined) {
|
||||
return true
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
return value.trim() === ''
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value.length === 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function formatJson(value: unknown): string {
|
||||
return JSON.stringify(value ?? {}, null, 2)
|
||||
}
|
||||
|
||||
@@ -920,6 +920,17 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
input_editable: 'N',
|
||||
value: null,
|
||||
}),
|
||||
createRequiredField({
|
||||
field_path: 'extracted_fields.room_items.0.room_quantity',
|
||||
field_pointer: '/extracted_fields/room_items/0/room_quantity',
|
||||
legacy_field_path: 'extracted_fields.room_quantity',
|
||||
display_name: '房量',
|
||||
control_type: 'number',
|
||||
edit_scope: 'normal_and_manual_review',
|
||||
write_target: 'draft_payload_and_review_resolution',
|
||||
raw_readonly: false,
|
||||
value: null,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
)
|
||||
@@ -974,12 +985,15 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
expect(wrapper.text()).toContain('人工复核解阻')
|
||||
expect(wrapper.text()).toContain('/extracted_fields/room_items/0/pms_room_type_code')
|
||||
expect(wrapper.text()).toContain('PMS 房型代码')
|
||||
expect(wrapper.text()).toContain('/extracted_fields/room_items/0/room_quantity')
|
||||
expect(wrapper.text()).toContain('房量')
|
||||
expect(wrapper.text()).not.toContain('人工转换')
|
||||
expect(wrapper.text()).not.toContain('保存草稿')
|
||||
expect(wrapper.text()).not.toContain('确认任务')
|
||||
expect(wrapper.text()).not.toContain('OPERA 模拟操作')
|
||||
|
||||
await wrapper.find('input[name="manual_resolution_field_override_0"]').setValue('RM3')
|
||||
await wrapper.find('input[name="manual_resolution_field_override_1"]').setValue('2')
|
||||
await wrapper.find('textarea[name="manual_resolution_reason"]').setValue('确认 PMS 房型代码')
|
||||
await findButton(wrapper, '提交复核结果').trigger('click')
|
||||
await flushPromises()
|
||||
@@ -993,6 +1007,11 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
field_path: 'extracted_fields.room_items.0.pms_room_type_code',
|
||||
value: 'RM3',
|
||||
},
|
||||
{
|
||||
field_pointer: '/extracted_fields/room_items/0/room_quantity',
|
||||
field_path: 'extracted_fields.room_items.0.room_quantity',
|
||||
value: '2',
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(service.fetchReservationTaskDetail).toHaveBeenCalledTimes(2)
|
||||
|
||||
Reference in New Issue
Block a user