优化
This commit is contained in:
@@ -17,6 +17,7 @@ import OperationErrorToast from '@/shared/components/OperationErrorToast.vue'
|
||||
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
|
||||
import SmartDispatchDialog from '../components/SmartDispatchDialog.vue'
|
||||
import FbaAppointmentFields from '../components/FbaAppointmentFields.vue'
|
||||
import type { PlanningSourceLookup } from '@/modules/appointment-calendar'
|
||||
import { createAppointmentForm, appointmentPayload, appointmentFormError } from '../appointmentForm'
|
||||
import { createFbaAppointment, getFbaAppointment, listInboundOrders, updateFbaAppointment, updateInboundPlan, type InboundOrderSummaryDto } from '../api/inboundOrders'
|
||||
import { listReceivingOverseasWarehouses, type ReceivingOverseasWarehouseDto } from '../api/pallets'
|
||||
@@ -59,6 +60,9 @@ const appointmentFbaWarehouse = ref('—')
|
||||
const appointmentVersion = ref(0)
|
||||
const appointmentForm = reactive(createAppointmentForm())
|
||||
const appointmentTimezone = ref<string | null>(null)
|
||||
const appointmentSources = ref<PlanningSourceLookup[]>([])
|
||||
const confirmationReady = ref(false)
|
||||
const appointmentFields = ref<InstanceType<typeof FbaAppointmentFields> | null>(null)
|
||||
const pendingAppointment = ref<{appointmentNo: string | null; version: number; originWarehouseId: string; fbaWarehouseCode: string; lineIds: string[]; details: ReturnType<typeof appointmentPayload>; idempotencyKey: string} | null>(null)
|
||||
const appointmentViewOnly = ref(false)
|
||||
const appointmentReplacementNos = ref<string[]>([])
|
||||
@@ -132,13 +136,15 @@ function selectionError() {
|
||||
return ''
|
||||
}
|
||||
|
||||
function openAppointment() {
|
||||
if (!access.can(permission.inboundOrderAppointment) || !canLeaveAppointment()) return
|
||||
async function openAppointment() {
|
||||
if (!access.can(permission.inboundOrderAppointment) || !await canLeaveAppointment()) return
|
||||
appointmentViewOnly.value = false
|
||||
appointmentReplacementNos.value = []
|
||||
const error = selectionError()
|
||||
if (error) { ElMessage.warning(error); return }
|
||||
appointmentMode.value = 'create'; editingAppointmentNo.value = ''
|
||||
confirmationReady.value = false
|
||||
appointmentSources.value = selectedRows.value.map(row => ({ orderId: row.orderId, customerId: row.customerId, destinationKey: `FBA:${row.fbaWarehouse}` }))
|
||||
appointmentSelectedCount.value = selectedRows.value.length; appointmentFbaWarehouse.value = selectedRows.value[0]?.fbaWarehouse || '—'
|
||||
appointmentVersion.value = 0
|
||||
Object.assign(appointmentForm, createAppointmentForm()); appointmentTimezone.value = null; pendingAppointment.value = null
|
||||
@@ -152,7 +158,7 @@ function openSmartDispatch() {
|
||||
}
|
||||
|
||||
async function openAppointmentEdit(source: object, readOnly = false) {
|
||||
if (!canLeaveAppointment()) return
|
||||
if (!await canLeaveAppointment()) return
|
||||
const row = source as InboundOrderListItem
|
||||
if (row.appointmentStatus === '多批预约') { openMultipleAppointments(row); return }
|
||||
if (!row.appointmentNo || row.appointmentNo === '—') return
|
||||
@@ -166,24 +172,27 @@ async function openAppointmentEdit(source: object, readOnly = false) {
|
||||
appointmentSelectedCount.value = detail.selectedCount
|
||||
appointmentFbaWarehouse.value = detail.fbaWarehouseCode || row.fbaWarehouse
|
||||
appointmentVersion.value = detail.version
|
||||
confirmationReady.value = false
|
||||
appointmentSources.value = detail.items.map(item => ({ sourceKey: item.sourceKey, customerId: item.customerId, destinationKey: item.destinationKey || `FBA:${item.fbaWarehouseCode}` }))
|
||||
Object.assign(appointmentForm, createAppointmentForm(detail)); appointmentTimezone.value = detail.timezone || null; pendingAppointment.value = null
|
||||
} catch (caught) {
|
||||
appointmentOpen.value = false
|
||||
mutationError.value = getApiErrorDetails(caught, 'FBA 预约详情加载失败,请重试')
|
||||
} finally { appointmentLoading.value = false }
|
||||
}
|
||||
function openMultipleAppointments(row: InboundOrderListItem) {
|
||||
if (!canLeaveAppointment() || !access.can('platform:appointment:list')) return
|
||||
async function openMultipleAppointments(row: InboundOrderListItem) {
|
||||
if (!await canLeaveAppointment() || !access.can('platform:appointment:list')) return
|
||||
if (!row.orderId || !row.customerId || !row.fbaWarehouse || row.fbaWarehouse === '—') { ElMessage.warning('原货源或客户范围缺失,请重新读取入库单'); return }
|
||||
void router.push({ path: '/appointment-calendar', query: { orderId: row.orderId, customerId: row.customerId, destinationKey: `FBA:${row.fbaWarehouse}` } })
|
||||
}
|
||||
|
||||
function canLeaveAppointment() {
|
||||
async function canLeaveAppointment() {
|
||||
if (!appointmentOpen.value) return true
|
||||
if (saving.value || pendingAppointment.value) { ElMessage.warning('请先核实本次预约保存结果,再关闭或切换'); return false }
|
||||
return true
|
||||
return await appointmentFields.value?.canLeave?.() ?? true
|
||||
}
|
||||
function closeAppointment() { if (canLeaveAppointment()) appointmentOpen.value = false }
|
||||
function beforeCloseAppointment(done: () => void) { if (canLeaveAppointment()) done() }
|
||||
async function closeAppointment() { if (await canLeaveAppointment()) appointmentOpen.value = false }
|
||||
async function beforeCloseAppointment(done: () => void) { if (await canLeaveAppointment()) { appointmentOpen.value = false; done() } }
|
||||
onBeforeRouteLeave(canLeaveAppointment)
|
||||
onBeforeRouteUpdate(canLeaveAppointment)
|
||||
async function submitAppointment() {
|
||||
@@ -191,6 +200,9 @@ async function submitAppointment() {
|
||||
if (appointmentMode.value === 'create') { const error = selectionError(); if (error) { ElMessage.warning(error); return } }
|
||||
const validation = appointmentFormError(appointmentForm)
|
||||
if (!pendingAppointment.value && validation) { ElMessage.warning(validation); return }
|
||||
if (!pendingAppointment.value && appointmentForm.appointmentStatus === 'SUCCESS' && !confirmationReady.value) { ElMessage.warning('请先在“正式确认前”区域补齐并保存每票货物资料,再保存预约安排'); return }
|
||||
if (!pendingAppointment.value && appointmentFields.value?.canLeave && !await appointmentFields.value.canLeave()) return
|
||||
if (saving.value || appointmentReadOnly.value) return
|
||||
saving.value = true; mutationError.value = null
|
||||
try {
|
||||
pendingAppointment.value ||= {appointmentNo: appointmentMode.value === 'edit' ? editingAppointmentNo.value : null, version: appointmentVersion.value, originWarehouseId: selectedRows.value[0]?.originWarehouseId || '', fbaWarehouseCode: selectedRows.value[0]?.fbaWarehouse || '', lineIds: selectedRows.value.map(row => row.lineId), details: appointmentPayload(appointmentForm), idempotencyKey: crypto.randomUUID()}
|
||||
@@ -247,7 +259,7 @@ onMounted(() => { void load() })
|
||||
<section class="density-dialog-section" data-tone="summary" aria-label="预约范围核对"><h3 class="density-dialog-section__title">预约范围</h3><table class="density-table"><tbody><tr><th scope="row">已选择</th><td>{{ appointmentSelectedCount }} 条</td><th scope="row">FBA仓库</th><td>{{ appointmentFbaWarehouse }}</td></tr></tbody></table></section>
|
||||
<el-alert v-if="appointmentReplacementNos.length" :title="`原批次已被替代,当前只读。替代预约:${appointmentReplacementNos.join('、')}`" type="warning" :closable="false" show-icon />
|
||||
<LoadErrorState v-if="mutationError" compact title="预约保存失败" :message="mutationError.message" :loading="saving" :show-retry="!appointmentReadOnly" :retry-text="pendingAppointment ? '重试本次保存' : '重新提交'" @retry="submitAppointment"><template #details><ApiErrorMeta :details="mutationError" /></template></LoadErrorState>
|
||||
<FbaAppointmentFields continuous :model="appointmentForm" :appointment-no="editingAppointmentNo || undefined" :timezone="appointmentTimezone" :disabled="appointmentReadOnly || appointmentLoading || saving || !!pendingAppointment" />
|
||||
<FbaAppointmentFields continuous v-if="appointmentOpen && !appointmentLoading" ref="appointmentFields" :sources="appointmentSources" @confirmation-ready="confirmationReady = $event" :model="appointmentForm" :appointment-no="editingAppointmentNo || undefined" :timezone="appointmentTimezone" :disabled="appointmentReadOnly || appointmentLoading || saving || !!pendingAppointment" />
|
||||
</div>
|
||||
</AppDialog>
|
||||
<SmartDispatchDialog v-model="smartDispatchOpen" :orders="selectedRows" @created="selectedRows = []; load()" />
|
||||
|
||||
Reference in New Issue
Block a user