55 lines
7.7 KiB
Vue
55 lines
7.7 KiB
Vue
<script setup lang="ts">
|
||
import type { ArrangeGroup, PreviewGroup } from '../dispatchContracts'
|
||
const groups = defineModel<ArrangeGroup[]>({ required: true })
|
||
defineProps<{ preview: PreviewGroup[]; disabled: boolean }>()
|
||
const serviceLabels: Record<string, string> = { DELIVERY_FEE: '派送费', LOADING_FEE: '装车费', APPOINTMENT_FEE: '买约费' }
|
||
function setCoverage(index: number, fee: PreviewGroup['feeSources'][number], service: string, checked: unknown) {
|
||
const group = groups.value[index]; if (!group) return
|
||
let selection = group.feeCoverage.find(row => row.financeFeeId === fee.financeFeeId)
|
||
if (!selection && checked === true) { selection = { financeFeeId: fee.financeFeeId, sourceVersion: fee.sourceVersion, sourceHash: fee.sourceHash, services: [] }; group.feeCoverage.push(selection) }
|
||
if (!selection) return
|
||
selection.services = checked === true ? [...new Set([...selection.services, service])] : selection.services.filter(value => value !== service)
|
||
group.feeCoverage = group.feeCoverage.filter(row => row.services.length)
|
||
}
|
||
function covered(index: number, preview: PreviewGroup, service: string) {
|
||
if (!preview.cargo.length) return false
|
||
const selections = groups.value[index]?.feeCoverage || []
|
||
return preview.cargo.every(cargo => service === 'DELIVERY_FEE' && preview.externalQuotes.some(quote => quote.customerId === cargo.customerId && quote.inboundCode === cargo.inboundCode)
|
||
|| preview.feeSources.some(fee => fee.customerId === cargo.customerId && fee.sourceKeys.includes(cargo.sourceKey) && selections.some(selection => selection.financeFeeId === fee.financeFeeId && selection.services.includes(service))))
|
||
}
|
||
function required(index: number, preview: PreviewGroup, service: string) {
|
||
const group = groups.value[index]
|
||
return preview.requiredServices.includes(service)
|
||
|| service === 'LOADING_FEE' && ['FLOOR', 'MIXED'].includes(group?.loadingType || '')
|
||
|| service === 'APPOINTMENT_FEE' && group?.appointmentAccount === 'BUY_APPOINTMENT'
|
||
}
|
||
defineExpose({ covered })
|
||
</script>
|
||
<template>
|
||
<section v-for="(previewGroup, index) in preview" :key="previewGroup.groupKey" class="arrange-group">
|
||
<template v-if="groups[index]">
|
||
<h3>{{ previewGroup.customerName || '—' }} · {{ previewGroup.destination.warehouseCode || previewGroup.destination.warehouseName || previewGroup.destination.address || '—' }}</h3>
|
||
<p v-for="reason in previewGroup.blockReasons" :key="reason" role="alert">{{ reason }}</p>
|
||
<div class="arrange-grid">
|
||
<el-form-item label="预计派送时间" required><el-date-picker v-model="groups[index]!.plannedDeliveryAt" :disabled="disabled" type="datetime" value-format="YYYY-MM-DDTHH:mm:ssZ" placeholder="请选择派送时间" /></el-form-item>
|
||
<el-form-item label="派送方式" required><el-select v-model="groups[index]!.deliveryMethod" :disabled="disabled" placeholder="请选择"><el-option label="卡派打托" value="TRUCK_PALLET" /><el-option label="卡派地板" value="TRUCK_FLOOR" /><el-option label="FBA自提" value="FBA_PICKUP" /><el-option label="客户自提" value="CUSTOMER_PICKUP" /><el-option label="快递" value="EXPRESS" /><el-option label="外配" value="OUTSOURCED" /><el-option label="专车直送" value="DEDICATED_TRUCK" /><el-option label="零担派送" value="LTL" /></el-select></el-form-item>
|
||
<el-form-item label="提货方式" required><el-select v-model="groups[index]!.pickupMethod" :disabled="disabled" placeholder="请选择"><el-option label="一提一卸" value="ONE_PICKUP_ONE_DROP" /><el-option label="一提多卸" value="ONE_PICKUP_MULTI_DROP" /><el-option label="多提一卸" value="MULTI_PICKUP_ONE_DROP" /><el-option label="多提多卸" value="MULTI_PICKUP_MULTI_DROP" /><el-option label="仓库自提" value="WAREHOUSE_PICKUP" /></el-select></el-form-item>
|
||
<el-form-item label="装车类型" required><el-select v-model="groups[index]!.loadingType" :disabled="disabled" placeholder="请选择"><el-option label="托盘" value="PALLET" /><el-option label="地板" value="FLOOR" /><el-option label="混装" value="MIXED" /></el-select></el-form-item>
|
||
<el-form-item label="承运商"><el-input v-model="groups[index]!.carrierName" :disabled="disabled" placeholder="请输入承运商(选填)" /></el-form-item><el-form-item label="运单号"><el-input v-model="groups[index]!.waybillNo" :disabled="disabled" placeholder="请输入运单号(选填)" /></el-form-item>
|
||
<el-form-item label="车型"><el-input v-model="groups[index]!.vehicleType" :disabled="disabled" placeholder="请输入本组派送车型(选填)" /></el-form-item><el-form-item label="车辆尺寸"><el-input v-model="groups[index]!.vehicleSize" :disabled="disabled" placeholder="请输入车辆尺寸(选填)" /></el-form-item>
|
||
<el-form-item label="预约账号"><el-select v-model="groups[index]!.appointmentAccount" :disabled="disabled" clearable placeholder="请选择"><el-option label="自有账号" value="SELF" /><el-option label="买约" value="BUY_APPOINTMENT" /></el-select></el-form-item><el-form-item v-if="groups[index]!.appointmentAccount === 'BUY_APPOINTMENT'" label="卖家姓名" required><el-input v-model="groups[index]!.sellerName" :disabled="disabled" placeholder="请输入卖家姓名" /></el-form-item><el-form-item label="备注"><el-input v-model="groups[index]!.remark" :disabled="disabled" placeholder="请输入本组派送备注(选填)" /></el-form-item>
|
||
</div>
|
||
<el-table :data="previewGroup.cargo" border max-height="240"><el-table-column prop="orderNo" label="来源订单" min-width="150" /><el-table-column prop="inboundCode" label="入仓码" min-width="150" /><el-table-column prop="palletNo" label="实物托盘码" min-width="150" /><el-table-column prop="cartonMark" label="来源箱唛" min-width="150" /><el-table-column prop="packages" label="本次箱数" width="100" /></el-table>
|
||
<p v-for="quote in previewGroup.externalQuotes" :key="quote.bookingNo">{{ quote.bookingNo }} · {{ quote.inboundCode }}:{{ quote.currency }} {{ quote.amount }}(外接约定运费)</p>
|
||
<h4>原费用覆盖</h4><p v-if="!previewGroup.feeSources.length">暂无可引用原费用。</p>
|
||
<div v-for="fee in previewGroup.feeSources" :key="fee.financeFeeId"><span>{{ fee.currency }} {{ fee.amount }} · {{ fee.status }}</span><el-checkbox v-for="service in fee.services" :key="service" :disabled="disabled" :model-value="groups[index]!.feeCoverage.some(row => row.financeFeeId === fee.financeFeeId && row.services.includes(service))" @update:model-value="setCoverage(index, fee, service, $event)">已包含{{ serviceLabels[service] || '服务费用' }}</el-checkbox></div>
|
||
<h4>本组新增费用</h4><div class="arrange-grid"><template v-for="fee in groups[index]!.fees.filter(item => required(index, previewGroup, item.feeType))" :key="fee.feeType"><el-form-item v-if="!covered(index, previewGroup, fee.feeType)" :label="`${serviceLabels[fee.feeType] || fee.feeName}(未覆盖部分)`" required><el-input-number v-model="fee.amount" :disabled="disabled" :min="0.01" :precision="2" placeholder="请输入实际新增应收" /><el-select v-model="fee.currency" :disabled="disabled" placeholder="币种"><el-option label="USD" value="USD" /><el-option label="CNY" value="CNY" /></el-select></el-form-item><p v-else>本组{{ serviceLabels[fee.feeType] || fee.feeName }}已全部覆盖,不重复登记。</p></template></div>
|
||
</template>
|
||
</section>
|
||
</template>
|
||
<style scoped>
|
||
.arrange-group { padding-bottom: var(--admin-space-5); border-bottom: 1px solid var(--cc-border); }
|
||
.arrange-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--admin-space-5); }
|
||
.arrange-grid :deep(.el-select), .arrange-grid :deep(.el-date-editor), .arrange-grid :deep(.el-input-number) { width: 100%; }
|
||
</style>
|