接入V4任务卡目录查询

This commit is contained in:
andy
2026-07-19 15:35:58 +07:00
parent 8b37232ac9
commit d808732107
16 changed files with 803 additions and 38 deletions

View File

@@ -68,6 +68,41 @@
</div>
</section>
<section class="th-section side-section">
<div class="th-section-header">
<h2 class="th-section-title">
{{ t('order.v4TaskTimeline') }}
</h2>
</div>
<div class="side-section__body">
<p
v-if="!v4OrderTasks.length"
class="side-empty"
>
{{ t('order.v4TaskTimelineEmpty') }}
</p>
<template v-else>
<RouterLink
v-for="item in v4OrderTasks"
:key="item.order_task_id"
class="v4-timeline-item"
:to="`/reservation/order-tasks/${item.order_task_id}`"
>
<span>
<strong>{{ v4OrderReference(item) }}</strong>
<small>{{ item.source_message_summary?.subject ?? '-' }}</small>
</span>
<ReservationStatusBadge :status="item.order_task_status" />
<small>
{{ t('taskList.cardCountsTotal', { total: item.card_counts.total_count }) }}
·
{{ formatReservationDateTime(item.latest_activity_at ?? item.updated_at ?? item.created_at) }}
</small>
</RouterLink>
</template>
</div>
</section>
<section class="th-section source-gap">
<h2>{{ t('task.evidence') }}</h2>
<template v-if="activeTask">
@@ -134,7 +169,7 @@ import ReservationTaskDetailPanel from '@/components/reservation/ReservationTask
import ReservationTaskQueue from '@/components/reservation/ReservationTaskQueue.vue'
import { fetchReservationOrderDetail } from '@/services/reservationService'
import { useAuthStore } from '@/stores/authStore'
import type { ReservationOrderDetailResult } from '@/types/reservation'
import type { ReservationOrderDetailResult, ReservationV4OrderTaskTimelineItem } from '@/types/reservation'
import { formatReservationDateTime } from '@/utils/reservationFormat'
const route = useRoute()
@@ -147,6 +182,7 @@ const activeTaskId = ref('')
const orderId = computed(() => String(route.params.orderId ?? ''))
const activeTask = computed(() => detail.value?.tasks.find((task) => task.task_id === activeTaskId.value) ?? null)
const v4OrderTasks = computed(() => detail.value?.v4_order_tasks ?? [])
watch(
orderId,
@@ -181,6 +217,10 @@ async function loadOrder(nextOrderId: string): Promise<void> {
loading.value = false
}
}
function v4OrderReference(item: ReservationV4OrderTaskTimelineItem): string {
return item.order_ref?.trim() || item.source_message_summary?.subject?.trim() || `#${item.order_task_id}`
}
</script>
<style scoped>
@@ -295,6 +335,48 @@ async function loadOrder(nextOrderId: string): Promise<void> {
line-height: 1.6;
}
.side-empty {
margin: 0;
color: var(--th-color-slate-500);
font-size: 13px;
line-height: 1.6;
}
.v4-timeline-item {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 8px;
border: 1px solid var(--th-color-slate-200);
border-radius: var(--th-radius-sm);
background: var(--th-color-white);
color: inherit;
padding: 10px;
text-decoration: none;
}
.v4-timeline-item > span {
display: grid;
gap: 3px;
min-width: 0;
}
.v4-timeline-item strong {
color: var(--th-color-slate-900);
font-size: 13px;
overflow-wrap: anywhere;
}
.v4-timeline-item small {
color: var(--th-color-slate-500);
font-size: 12px;
font-weight: 700;
overflow-wrap: anywhere;
}
.v4-timeline-item > small {
grid-column: 1 / -1;
}
.source-gap dl {
display: grid;
gap: 10px;

View File

@@ -522,6 +522,7 @@ const TaskCardSection = defineComponent({
submittingCardId.value === props.card.card_id,
editableKeys: editableFieldKeys(props.card),
validationErrors: cardFieldErrors.value[props.card.card_id] ?? {},
hotelId: detail.value?.order_task.hotel_id,
'onUpdate:modelValue': (values: ReservationRecord) => setCardValues(props.card, values),
}),
safePayloadRows(props.card.display_payload).length