Files
admin-web/src/modules/overseas-master-data/components/LooseboardCargoDialog.vue
T
2026-11-02 17:15:37 +08:00

54 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import AppDialog from '@/shared/components/AppDialog.vue'
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import { getDispatch, listLooseboardCargo, addLooseboardCargo, expandSelectionGroups, type Candidate, type DispatchDetail } from '@/modules/overseas-warehouse'
const open=defineModel<boolean>({default:false})
const props=defineProps<{dispatchNo:string}>()
const emit=defineEmits<{saved:[]}>()
const rows=ref<Candidate[]>([]), selected=ref<Candidate[]>([]), detail=ref<DispatchDetail|null>(null)
const page=ref(1), size=ref(20), total=ref(0), loading=ref(false), saving=ref(false), error=ref<ApiErrorDetails|null>(null)
const columns:DataTableColumn[]=[
{key:'selection',type:'selection',width:45}, {key:'orderNo',label:'订单号',minWidth:180},
{key:'customerName',label:'客户',minWidth:140}, {key:'inboundCode',label:'入仓号',minWidth:150},
{key:'sourceStage',label:'货物阶段',width:110,formatter:(row:Candidate)=>!row.selection.warehousePalletId ? '申报待到仓' : '已实收'}, {key:'palletNo',label:'计划 / 实物托盘',minWidth:150}, {key:'destination',label:'目的地',minWidth:180,formatter:(row:Candidate)=>row.destination.warehouseCode || row.destination.address || '—'},
{key:'availablePackages',label:'计划 / 可用箱数',width:100},
{key:'blockReasons',label:'资格',minWidth:200,formatter:(row:Candidate)=>row.blockReasons.length?row.blockReasons.join(';'):'可添加'},
]
let generation=0
async function load() {
const current=++generation;loading.value=true;error.value=null;selected.value=[];rows.value=[];detail.value=null
try {
const [dispatch,value]=await Promise.all([getDispatch(props.dispatchNo),listLooseboardCargo(props.dispatchNo,page.value,size.value)])
if(current!==generation)return
if(dispatch.dispatchNo!==props.dispatchNo)throw new Error('排车身份不一致,请重新打开')
detail.value=dispatch;rows.value=value.candidates;total.value=value.total
}catch(cause){if(current===generation)error.value=getApiErrorDetails(cause,'散板货物读取失败')}
finally{if(current===generation)loading.value=false}
}
async function submit(){
if(!detail.value || saving.value || !selected.value.length)return
saving.value=true;error.value=null
try{
if(selected.value.some(row=>row.blockReasons.length))throw new Error('所选货物存在阻断,请重新选择')
const cargo=expandSelectionGroups(selected.value)
// 完整组来源版本由后端复核;预约批次继续通过原排车预约工作台绑定。
await addLooseboardCargo(props.dispatchNo,{recordVersion:detail.value.recordVersion,idempotencyKey:crypto.randomUUID(),cargo,batchAllocations:[]})
ElMessage.success('散板货物已加入排车,请按当前货物重新审核');open.value=false;emit('saved')
}catch(cause){await load();error.value=getApiErrorDetails(cause,'添加货物失败')}
finally{saving.value=false}
}
watch(open,value=>{if(value){page.value=1;void load()}else generation++})
watch([page,size],()=>{if(open.value)void load()})
</script>
<template><AppDialog v-model="open" title="添加散板货物" width="1180px" class="admin-density-dialog admin-workbench" :confirm-loading="saving" :confirm-disabled="loading || !selected.length || !detail?.actions.ADD_CARGO?.allowed" lock-while-submitting @confirm="submit">
<LoadErrorState v-if="error" title="添加货物暂未完成" :message="error.message" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
<el-alert v-if="detail && !detail.actions.ADD_CARGO?.allowed" :title="detail.actions.ADD_CARGO?.blockReason || '当前排车不可加货,请先退回审核或重新排车'" type="warning" :closable="false" />
<el-alert title="申报货物可先加入排车;实际到仓后核对货量,完成实收后才能出库拣货。上门取货的凭证在对应取货排车节点上传。" type="info" :closable="false" />
<DataTable v-model:page="page" v-model:page-size="size" :data="rows" :columns="columns" :total="total" :loading="loading" row-key="sourceKey" :page-sizes="[10,20,50]" empty-text="暂无可添加的已审核散板货物" @selection-change="selected=$event" />
</AppDialog></template>