调整结算
This commit is contained in:
@@ -691,7 +691,7 @@ export default {
|
||||
return value !== undefined && value !== null && String(value).trim() !== '';
|
||||
},
|
||||
taxRateInput(row, value) {
|
||||
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||
const text = String(value ?? '').replace(/[^\d.]/g, '');
|
||||
const parts = text.split('.');
|
||||
row.taxRate =
|
||||
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0];
|
||||
|
||||
@@ -71,12 +71,12 @@
|
||||
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="运输方式" required class="transport-type-field"><el-input :model-value="route.transportType" readonly /></el-form-item>
|
||||
<el-form-item label="运输方式" required class="transport-type-field"><el-input :model-value="route.transportType" disabled /></el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发货地址" required><el-input :model-value="addressText(route.departureName, route.departureAddress)" readonly /></el-form-item>
|
||||
<el-form-item label="发货地址" required><el-input :model-value="addressText(route.departureName, route.departureAddress)" disabled /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4"><el-form-item label="联系人"><el-input v-model="route.departureContact" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="4"><el-form-item label="联系方式"><el-input v-model="route.departurePhone" placeholder="请输入" /></el-form-item></el-col>
|
||||
@@ -84,7 +84,7 @@
|
||||
</el-row>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="收货地址" required><el-input :model-value="addressText(route.arrivalName, route.arrivalAddress)" readonly /></el-form-item>
|
||||
<el-form-item label="收货地址" required><el-input :model-value="addressText(route.arrivalName, route.arrivalAddress)" disabled /></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4"><el-form-item label="联系人"><el-input v-model="route.arrivalContact" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="4"><el-form-item label="联系方式"><el-input v-model="route.arrivalPhone" placeholder="请输入" /></el-form-item></el-col>
|
||||
@@ -109,6 +109,7 @@
|
||||
</el-table>
|
||||
|
||||
<template v-if="route.documentType === '运单'">
|
||||
<div class="goods-heading"><h3>任务信息</h3></div>
|
||||
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form carrier-type-form"><el-form-item label="承运类型" required><el-radio-group v-model="route.carrierType" @change="value => handleCarrierTypeChange(route, value)"><el-radio-button label="承运商" /><el-radio-button label="自运" /><el-radio-button label="网货平台" /></el-radio-group></el-form-item></el-form>
|
||||
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form carrier-form">
|
||||
<el-row :gutter="16">
|
||||
@@ -125,7 +126,7 @@
|
||||
<el-col :span="6"><el-form-item label="承运商" :required="route.carrierType === '承运商'"><el-select :model-value="route.carrierType === '承运商' ? route.carrierContractId : route.carrierName" filterable clearable placeholder="请选择" :loading="carrierLoading" @change="value => handleCarrierContractChange(route, value)"><el-option v-for="item in carrierOptions" :key="carrierOptionValue(item)" :label="carrierOptionLabel(item)" :value="route.carrierType === '承运商' ? carrierOptionValue(item) : item.carrierName" /></el-select></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="船/航/班列号" required><el-input v-model="route.vehicleNo" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="船长"><el-input v-model="route.captainName" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="联系电话" required><el-input v-model="route.driverPhone" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="联系电话"><el-input v-model="route.driverPhone" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="箱号"><el-input v-model="route.containerNo" placeholder="请输入" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="舱位"><el-input v-model="route.cabinNo" placeholder="请输入" /></el-form-item></el-col>
|
||||
</template>
|
||||
@@ -171,7 +172,7 @@
|
||||
<section class="pending-panel">
|
||||
<div class="pending-bar">
|
||||
<div class="pending-summary">
|
||||
<strong>待提交 <em>{{ pending.length }}</em> 条 <span class="pending-summary-text">({{ pendingSegmentSummary }})</span></strong>
|
||||
<strong>待提交 <em>{{ pendingBatchCount }}</em> 条 <span class="pending-summary-text">({{ pendingSegmentSummary }})</span></strong>
|
||||
<el-link type="primary" @click="pendingExpanded = !pendingExpanded">{{ pendingExpanded ? '收起待调度列表' : '展开待调度列表' }}</el-link>
|
||||
</div>
|
||||
<div class="pending-actions"><el-button @click="$emit('back')">取消</el-button><el-button type="primary" :loading="submitting" @click="submit">确认调度</el-button></div>
|
||||
@@ -179,7 +180,7 @@
|
||||
<div v-show="pendingExpanded" class="pending-list">
|
||||
<template v-for="(items, segmentNo) in pendingGroups" :key="segmentNo">
|
||||
<h3>{{ segmentNo }}:{{ dispatchLocationName(items[0], 'departure') }} → {{ dispatchLocationName(items[0], 'arrival') }}</h3>
|
||||
<el-table :data="items" border><el-table-column type="index" label="序号" width="70" /><el-table-column label="单据类型" prop="documentType" width="100" /><el-table-column label="货物" min-width="220"><template #default="{ row }">{{ row.cargoName }}{{ row.cargoType ? `,${row.cargoType}` : '' }}</template></el-table-column><el-table-column label="本次数量" width="150"><template #default="{ row }">{{ formatQuantity(row.quantity) }} {{ row.quantityUnit }}</template></el-table-column><el-table-column prop="carrierName" label="承运商" min-width="180" /><el-table-column prop="driverName" label="司机" width="130" /><el-table-column prop="vehicleNo" label="车牌" width="130" /><el-table-column label="操作" width="120" fixed="right"><template #default="{ row }"><div class="table-actions"><el-link type="primary" @click="editPending(row)">编辑</el-link><el-link type="danger" @click="removePending(row.id)">删除</el-link></div></template></el-table-column></el-table>
|
||||
<el-table :data="items" border><el-table-column type="index" label="序号" width="70" /><el-table-column label="货物" min-width="220"><template #default="{ row }">{{ pendingGoodsText(row) }}</template></el-table-column><el-table-column label="本次数量" min-width="150"><template #default="{ row }">{{ pendingQuantityText(row) }}</template></el-table-column><el-table-column prop="carrierName" label="承运商" min-width="180" /><el-table-column prop="driverName" label="司机" width="130" /><el-table-column prop="vehicleNo" label="车牌" width="130" /><el-table-column label="操作" width="120" fixed="right"><template #default="{ row }"><div class="table-actions"><el-link type="primary" @click="editPending(row)">编辑</el-link><el-link type="danger" @click="removePendingBatch(row)">删除</el-link></div></template></el-table-column></el-table>
|
||||
</template>
|
||||
<el-empty v-if="!pending.length" description="暂无待提交调度条目" :image-size="60" />
|
||||
</div>
|
||||
@@ -216,13 +217,28 @@ export default {
|
||||
goodsTypes() { return [...new Set((this.master?.goods || []).map(item => item.cargoType).filter(Boolean))].join('、') || '-'; },
|
||||
masterGoods() { return (this.master?.goods || []).map((item, sourceIndex) => ({ ...item, sourceIndex, label: [item.cargoName, item.cargoType].filter(Boolean).join(' / ') })); },
|
||||
dateRange() { return this.master?.planStartTime && this.master?.planEndTime ? `${String(this.master.planStartTime).slice(0, 10)} ~ ${String(this.master.planEndTime).slice(0, 10)}` : '-'; },
|
||||
pendingGroups() { return this.pending.reduce((groups, item) => { (groups[item.segmentNo] ||= []).push(item); return groups; }, {}); },
|
||||
pendingGroups() {
|
||||
return this.pending.reduce((groups, item, index) => {
|
||||
const segmentRows = (groups[item.segmentNo] ||= []);
|
||||
const batchKey = item.batchNo || item.id || `${item.segmentNo}-${index}`;
|
||||
let batch = segmentRows.find(row => row.batchKey === batchKey);
|
||||
if (!batch) {
|
||||
batch = { ...item, batchKey, items: [] };
|
||||
segmentRows.push(batch);
|
||||
}
|
||||
batch.items.push(item);
|
||||
return groups;
|
||||
}, {});
|
||||
},
|
||||
pendingBatchCount() {
|
||||
return Object.values(this.pendingGroups).reduce((count, rows) => count + rows.length, 0);
|
||||
},
|
||||
pendingSegmentSummary() {
|
||||
return this.routes.map(route => {
|
||||
const items = this.pending.filter(item => item.segmentNo === route.segmentNo);
|
||||
if (!items.length) return `${route.segmentNo}:无`;
|
||||
const documentSummary = items.reduce((result, item) => {
|
||||
result[item.documentType] = (result[item.documentType] || 0) + 1;
|
||||
const batches = this.pendingGroups[route.segmentNo] || [];
|
||||
if (!batches.length) return `${route.segmentNo}:无`;
|
||||
const documentSummary = batches.reduce((result, batch) => {
|
||||
result[batch.documentType] = (result[batch.documentType] || 0) + 1;
|
||||
return result;
|
||||
}, {});
|
||||
return `${route.segmentNo}:${Object.entries(documentSummary).map(([type, count]) => `${type} x ${count}`).join('、')}`;
|
||||
@@ -506,6 +522,26 @@ export default {
|
||||
return sum + this.quantityNumber(item.quantity);
|
||||
}, 0);
|
||||
},
|
||||
validatePreviousSegmentCompletedQuantity(route, goods) {
|
||||
const routeIndex = this.routes.indexOf(route);
|
||||
if (routeIndex <= 0) return true;
|
||||
const previousCompletedQuantity = this.quantityNumber(
|
||||
this.routes[routeIndex - 1]?.arrivedQuantity
|
||||
);
|
||||
const currentDispatchQuantity = (goods || []).reduce(
|
||||
(sum, item) => sum + this.quantityNumber(item.dispatchQuantity),
|
||||
0
|
||||
);
|
||||
const dispatchTotal =
|
||||
this.quantityNumber(route.dispatchedQuantity) +
|
||||
this.pendingSegmentQuantity(route) +
|
||||
currentDispatchQuantity;
|
||||
if (dispatchTotal <= previousCompletedQuantity) return true;
|
||||
this.$message.warning(
|
||||
`${route.segmentNo}调度总量不能大于上一段已完成数量(${this.formatQuantity(previousCompletedQuantity)} ${this.quantityUnitLabel})`
|
||||
);
|
||||
return false;
|
||||
},
|
||||
pendingGoodsQuantity(route, row) {
|
||||
const goodsIndex = this.masterGoodsIndex(row);
|
||||
return this.pending.reduce((sum, item) => {
|
||||
@@ -798,6 +834,7 @@ export default {
|
||||
if (!goods.length) return this.$message.warning('请填写本次数量');
|
||||
if (!this.validateDispatchGoods(route, goods)) return;
|
||||
if (goods.some(item => Number(item.dispatchQuantity) > this.availableDispatchQuantity(route, item))) return this.$message.warning('本次数量不能超过剩余数量');
|
||||
if (!this.validatePreviousSegmentCompletedQuantity(route, goods)) return;
|
||||
this.syncFreightItems(route);
|
||||
if (!this.validateFreightItems(route)) return;
|
||||
if (!this.validateRoutePhones(route)) return;
|
||||
@@ -805,7 +842,7 @@ export default {
|
||||
if (this.isRoad(route)) {
|
||||
if (route.carrierType === '承运商' && (!route.carrierContractId || !route.carrierName || !route.vehicleNo)) return this.$message.warning('请选择承运商并填写车牌号');
|
||||
if (route.carrierType !== '承运商' && (!route.driverName || !route.driverPhone || !route.vehicleNo)) return this.$message.warning('请补全自运或网货平台的车辆与人员信息');
|
||||
} else if (!route.vehicleNo || !route.driverPhone || (route.carrierType === '承运商' && (!route.carrierContractId || !route.carrierName))) {
|
||||
} else if (!route.vehicleNo || (route.carrierType === '承运商' && (!route.carrierContractId || !route.carrierName))) {
|
||||
return this.$message.warning('请补全非公路运输的承运信息');
|
||||
}
|
||||
}
|
||||
@@ -829,35 +866,59 @@ export default {
|
||||
}
|
||||
this.$message.success('已加入调度清单');
|
||||
},
|
||||
editPending(item) {
|
||||
const route = this.routes.find(routeItem => routeItem.segmentNo === item.segmentNo);
|
||||
pendingGoodsText(batch = {}) {
|
||||
return (batch.items || [batch])
|
||||
.map(item => [item.cargoName, item.cargoType].filter(Boolean).join(','))
|
||||
.join(' | ');
|
||||
},
|
||||
pendingQuantityText(batch = {}) {
|
||||
return (batch.items || [batch])
|
||||
.map(item => `${this.formatQuantity(item.quantity)} ${item.quantityUnit || ''}`.trim())
|
||||
.join(' | ');
|
||||
},
|
||||
editPending(batch) {
|
||||
const items = batch.items || [batch];
|
||||
const first = items[0];
|
||||
const route = this.routes.find(routeItem => routeItem.segmentNo === first.segmentNo);
|
||||
if (!route) return;
|
||||
const itemSourceIndex = Number(item.sourceIndex);
|
||||
const sourceIndex = Number.isInteger(itemSourceIndex) && itemSourceIndex >= 0
|
||||
? itemSourceIndex
|
||||
: (this.master.goods || []).findIndex(goods => goods.cargoName === item.cargoName && goods.cargoType === item.cargoType);
|
||||
let goods = route.goods.find(goodsItem => String(goodsItem.sourceIndex) === String(sourceIndex));
|
||||
if (!goods && sourceIndex >= 0) {
|
||||
goods = this.createGoodsRow(this.master.goods[sourceIndex], sourceIndex);
|
||||
route.goods.push(goods);
|
||||
}
|
||||
if (goods) goods.dispatchQuantity = item.quantity;
|
||||
Object.assign(route, item);
|
||||
Object.assign(route, first);
|
||||
const editedGoods = items.map(item => {
|
||||
const itemSourceIndex = Number(item.sourceIndex);
|
||||
const sourceIndex = Number.isInteger(itemSourceIndex) && itemSourceIndex >= 0
|
||||
? itemSourceIndex
|
||||
: (this.master.goods || []).findIndex(goods => goods.cargoName === item.cargoName && goods.cargoType === item.cargoType);
|
||||
let goods = route.goods.find(goodsItem => String(goodsItem.sourceIndex) === String(sourceIndex));
|
||||
if (!goods && sourceIndex >= 0) {
|
||||
goods = this.createGoodsRow(this.master.goods[sourceIndex], sourceIndex);
|
||||
route.goods.push(goods);
|
||||
}
|
||||
if (goods) goods.dispatchQuantity = item.quantity;
|
||||
return { goods, item };
|
||||
});
|
||||
route.currency = this.normalizeCurrencyValue(
|
||||
this.master?.settlementCurrency || route.currency || 'RMB'
|
||||
);
|
||||
this.syncFreightItems(route);
|
||||
const freightItem = this.freightItemsForGoods(route, goods);
|
||||
if (freightItem) { freightItem.unitPrice = item.unitPrice || ''; freightItem.priceUnit = item.priceUnit || freightItem.priceUnit; }
|
||||
this.removePending(item.id);
|
||||
this.editingId = item.id;
|
||||
editedGoods.forEach(({ goods, item }) => {
|
||||
const freightItem = this.freightItemsForGoods(route, goods);
|
||||
if (freightItem) {
|
||||
freightItem.unitPrice = item.unitPrice || '';
|
||||
freightItem.priceUnit = item.priceUnit || freightItem.priceUnit;
|
||||
}
|
||||
});
|
||||
this.removePendingBatch(batch);
|
||||
this.editingId = batch.batchKey;
|
||||
route.selected = true;
|
||||
this.$nextTick(() => document.querySelector(`[data-segment="${item.segmentNo}"]`)?.scrollIntoView({ behavior: 'smooth', block: 'start' }));
|
||||
this.$nextTick(() => document.querySelector(`[data-segment="${first.segmentNo}"]`)?.scrollIntoView({ behavior: 'smooth', block: 'start' }));
|
||||
},
|
||||
freightItemsForGoods(route, goods) {
|
||||
return (route.freightItems || []).find(item => String(item.sourceIndex) === String(goods?.sourceIndex)) || {};
|
||||
},
|
||||
removePending(id) { this.pending = this.pending.filter(item => item.id !== id); if (this.editingId === id) this.editingId = null; },
|
||||
removePendingBatch(batch = {}) {
|
||||
const ids = new Set((batch.items || [batch]).map(item => item.id));
|
||||
this.pending = this.pending.filter(item => !ids.has(item.id));
|
||||
if (this.editingId === batch.batchKey) this.editingId = null;
|
||||
},
|
||||
validateRoutePhones(route = {}) {
|
||||
const invalidPhone = [
|
||||
[route.departurePhone, '发货联系方式'],
|
||||
|
||||
@@ -228,9 +228,9 @@
|
||||
>
|
||||
</section>
|
||||
<section>
|
||||
<h3>附件</h3>
|
||||
<div class="master-editor__attachment">
|
||||
<div class="master-editor__attachment-head">
|
||||
<div class="section-head">
|
||||
<h3>附件</h3>
|
||||
<div class="section-head__actions">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!attachmentRows.length"
|
||||
@@ -239,6 +239,8 @@
|
||||
批量下载
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="master-editor__attachment">
|
||||
<el-table
|
||||
:data="attachmentRows"
|
||||
border
|
||||
@@ -254,6 +256,17 @@
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件描述" min-width="220" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
v-model="row.description"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
placeholder="请输入附件描述"
|
||||
@input="syncAttachmentsJson"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文件大小" width="120" align="center">
|
||||
<template #default="{ row }">{{ formatFileSize(row.size) }}</template>
|
||||
</el-table-column>
|
||||
@@ -1006,6 +1019,7 @@ export default {
|
||||
const first = this.contracts[0];
|
||||
this.form.contractId = first?.id;
|
||||
this.form.contractName = first?.contractName || '';
|
||||
this.form.customerName = first?.partyA || '';
|
||||
}
|
||||
},
|
||||
async projectChange(projectId) {
|
||||
@@ -1019,6 +1033,7 @@ export default {
|
||||
contractChange(contractId) {
|
||||
const contract = this.contracts.find(item => String(item.id) === String(contractId));
|
||||
this.form.contractName = contract?.contractName || '';
|
||||
this.form.customerName = contract?.partyA || '';
|
||||
},
|
||||
addressModel(target) {
|
||||
if (target.startsWith('route-')) {
|
||||
@@ -1939,12 +1954,6 @@ export default {
|
||||
.master-editor__attachment {
|
||||
width: 100%;
|
||||
}
|
||||
.master-editor__attachment-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.master-editor__attachment-upload {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
|
||||
@@ -161,7 +161,7 @@ export default {
|
||||
handleContractFileBatchDownload() { (this.selectedContractFiles.length ? this.selectedContractFiles : this.contractFileRows).forEach(row => { if (row.url) window.open(row.url, '_blank'); }); },
|
||||
formatFileSize(value) { const size = Number(value || 0); return size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(2)}MB` : `${Math.max(1, Math.ceil(size / 1024))}KB`; },
|
||||
addPaymentRatioRow() { this.paymentRatioRows.push({ paymentTerm: `第${this.paymentRatioRows.length + 1}笔`, ratioLimit: '', remark: '' }); },
|
||||
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeContent, changeReason: this.form.changeReason, changeAttachmentsJson: JSON.stringify(this.changeMaterials) }); this.$message.success('变更已提交'); this.$router.back(); },
|
||||
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, settlementCurrency: String(this.form.settlementCurrency || '').trim() || 'RMB', copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeContent, changeReason: this.form.changeReason, changeAttachmentsJson: JSON.stringify(this.changeMaterials) }); this.$message.success('变更已提交'); this.$router.back(); },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
>
|
||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||
<el-table-column type="index" label="序号" width="58" fixed="left" align="center" />
|
||||
<el-table-column label="配载单号" prop="loadingNo" min-width="170" fixed="left">
|
||||
<el-table-column label="配载单号" prop="loadingNo" min-width="170">
|
||||
<template #default="{ row }">
|
||||
<el-link
|
||||
type="primary"
|
||||
@@ -1172,6 +1172,31 @@ const createDialogForm = () => ({
|
||||
businessStatus: 'draft',
|
||||
});
|
||||
|
||||
// 后端以 -1 表示未填写里程,表单中应保持为空,避免给用户造成已填写的错觉。
|
||||
const normalizeLoadingMileage = value => {
|
||||
if (value === undefined || value === null || value === '' || Number(value) === -1) return '';
|
||||
return value;
|
||||
};
|
||||
|
||||
const createCopiedDialogForm = (detail = {}) => {
|
||||
const form = createDialogForm();
|
||||
Object.keys(form).forEach(prop => {
|
||||
if (Object.prototype.hasOwnProperty.call(detail, prop)) form[prop] = detail[prop];
|
||||
});
|
||||
return {
|
||||
...form,
|
||||
id: '',
|
||||
loadingNo: '',
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
dataSource: '手工创建',
|
||||
currentProcessNode: '接单',
|
||||
mileage: normalizeLoadingMileage(form.mileage),
|
||||
taskInfoJson: '',
|
||||
businessStatus: 'draft',
|
||||
};
|
||||
};
|
||||
|
||||
const unwrapRecords = res => {
|
||||
const data = res?.data || res;
|
||||
if (Array.isArray(data)) return data;
|
||||
@@ -1369,7 +1394,8 @@ export default {
|
||||
this.syncStandaloneTagTitle();
|
||||
if (
|
||||
to.query.mode !== from?.query?.mode ||
|
||||
String(to.query.id || '') !== String(from?.query.id || '')
|
||||
String(to.query.id || '') !== String(from?.query.id || '') ||
|
||||
String(to.query.copyId || '') !== String(from?.query.copyId || '')
|
||||
) {
|
||||
this.initStandaloneFormPage();
|
||||
}
|
||||
@@ -1674,10 +1700,12 @@ export default {
|
||||
async initStandaloneFormPage() {
|
||||
if (!this.isStandaloneFormPage) return;
|
||||
const mode = this.$route.query.mode === 'edit' ? 'edit' : 'add';
|
||||
const copyId = mode === 'add' ? this.$route.query.copyId : '';
|
||||
await this.openLoadingDialog(mode, {
|
||||
id: this.$route.query.id,
|
||||
id: copyId || this.$route.query.id,
|
||||
copy: Boolean(copyId),
|
||||
});
|
||||
if (mode === 'add') await this.consumeLoadingCreateWaybills();
|
||||
if (mode === 'add' && !copyId) await this.consumeLoadingCreateWaybills();
|
||||
},
|
||||
async consumeLoadingCreateWaybills() {
|
||||
const raw = sessionStorage.getItem(loadingCreateWaybillsStorageKey);
|
||||
@@ -1711,10 +1739,11 @@ export default {
|
||||
try {
|
||||
if (row?.id) {
|
||||
const res = await loadingApi.getDetail(row.id);
|
||||
this.dialogForm = {
|
||||
...createDialogForm(),
|
||||
...(res.data?.data || res.data || {}),
|
||||
};
|
||||
const detail = res.data?.data || res.data || {};
|
||||
this.dialogForm = row.copy
|
||||
? createCopiedDialogForm(detail)
|
||||
: { ...createDialogForm(), ...detail };
|
||||
this.dialogForm.mileage = normalizeLoadingMileage(this.dialogForm.mileage);
|
||||
await this.restoreWaybillRows(
|
||||
this.dialogForm.waybillIdsJson,
|
||||
this.dialogForm.loadingSubNos
|
||||
@@ -2247,6 +2276,7 @@ export default {
|
||||
normalizePayload() {
|
||||
this.syncRouteAddressFields();
|
||||
this.rebuildSummaryFromWaybills(false);
|
||||
this.dialogForm.mileage = normalizeLoadingMileage(this.dialogForm.mileage);
|
||||
if (this.dialogForm.carrierType === '网货平台') {
|
||||
this.dialogForm.carrierContractId = '';
|
||||
this.dialogForm.carrierName = '';
|
||||
@@ -2332,6 +2362,7 @@ export default {
|
||||
...this.dialogForm,
|
||||
...(res.data?.data || res.data || {}),
|
||||
};
|
||||
this.dialogForm.mileage = normalizeLoadingMileage(this.dialogForm.mileage);
|
||||
ElMessage.success('暂存成功');
|
||||
this.loadTable();
|
||||
} finally {
|
||||
@@ -2356,10 +2387,15 @@ export default {
|
||||
this.dialogSaving = '';
|
||||
}
|
||||
},
|
||||
async copyLoading(row) {
|
||||
await loadingApi.copy(row.id);
|
||||
ElMessage.success('复制成功');
|
||||
this.loadTable();
|
||||
copyLoading(row) {
|
||||
this.$router.push({
|
||||
path: '/business/loading-manage/form',
|
||||
query: {
|
||||
mode: 'add',
|
||||
copyId: row.id,
|
||||
name: '新增配载管理',
|
||||
},
|
||||
});
|
||||
},
|
||||
deleteLoading(row) {
|
||||
ElMessageBox.confirm(`确定删除配载单 ${row.loadingNo}?`, '提示', { type: 'warning' })
|
||||
|
||||
@@ -262,7 +262,7 @@ export default {
|
||||
result.unshift({ text: '调度', run: () => this.goDispatch(row.id) });
|
||||
if (row.businessStatus !== 'draft')
|
||||
result.unshift({ text: '详情', run: () => this.goDetail(row.id) });
|
||||
if (['dispatching', 'completed'].includes(row.businessStatus))
|
||||
if (row.businessStatus === 'dispatching')
|
||||
result.push({
|
||||
text: '关闭调度',
|
||||
run: () =>
|
||||
|
||||
Reference in New Issue
Block a user