⚡ 调度剩余数量按本次填写联动,公路运输司机手机号必填
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3774,7 +3774,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="剩余数量" min-width="130" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ formatDispatchQuantity(dispatchItemRemainingQuantity(row)) }}
|
||||
{{ formatDispatchQuantity(dispatchItemDisplayRemainingQuantity(row)) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column min-width="130" align="center">
|
||||
@@ -4031,7 +4031,7 @@
|
||||
</el-input>
|
||||
<div class="business-crud-page__dispatch-quantity-hint">
|
||||
剩余数量:{{
|
||||
formatDispatchQuantity(dispatchItemHintRemainingQuantity(dispatchItemForm))
|
||||
formatDispatchQuantity(dispatchItemDisplayRemainingQuantity(dispatchItemForm))
|
||||
}}
|
||||
{{ dispatchItemForm.quantityUnit || '吨' }}
|
||||
</div>
|
||||
@@ -5740,6 +5740,8 @@ export default {
|
||||
dispatchItemIndex: -1,
|
||||
dispatchItemForm: defaultDispatchRow(),
|
||||
dispatchItemCargoRows: [],
|
||||
// 本次数量变更版本号:驱动同表其他行「剩余数量」同步重算
|
||||
dispatchCargoQuantityVersion: 0,
|
||||
dispatchItemAttachmentRows: [],
|
||||
selectedDispatchItemAttachmentRows: [],
|
||||
attachmentRows: [],
|
||||
@@ -12776,18 +12778,23 @@ export default {
|
||||
row.cargoName = '';
|
||||
row.specification = '';
|
||||
row.model = '';
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
handleDispatchConfiguredCargoNameChange(row, value) {
|
||||
const option = this.getDispatchConfiguredCargoNameOptions(row).find(
|
||||
item => String(item.value) === String(value || '')
|
||||
);
|
||||
row.cargoName = option?.value || '';
|
||||
if (!option) return;
|
||||
if (!option) {
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
return;
|
||||
}
|
||||
row.cargoType = option.cargoTypeLabel || row.cargoType || '';
|
||||
row.cargoTypeCode = option.cargoTypeCode || row.cargoTypeCode || '';
|
||||
row.cargoTypePath = option.cargoTypePath || row.cargoTypePath || [];
|
||||
row.specification = option.specification || row.specification || '';
|
||||
row.model = option.model || row.model || '';
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
openDispatchItemDialog(index = -1, row = defaultDispatchRow()) {
|
||||
const defaultSummaryItem =
|
||||
@@ -13119,6 +13126,7 @@ export default {
|
||||
const parts = text.split('.');
|
||||
row.quantity =
|
||||
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 3)}` : parts[0];
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
handleDispatchCargoNumberInput(row, prop, value) {
|
||||
this.handleTaskFullFreightNumberInput(row, prop, value);
|
||||
@@ -13138,12 +13146,14 @@ export default {
|
||||
const nextRow = this.normalizeTransportCargoRow({ priceUnit: '元/吨' });
|
||||
if (index > -1) this.dispatchItemCargoRows.splice(index + 1, 0, nextRow);
|
||||
else this.dispatchItemCargoRows.push(nextRow);
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
removeDispatchCargoRow(index) {
|
||||
this.dispatchItemCargoRows.splice(index, 1);
|
||||
if (!this.dispatchItemCargoRows.length) {
|
||||
this.dispatchItemCargoRows.push(this.normalizeTransportCargoRow());
|
||||
}
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
dispatchCargoFreightAmount(cargo = {}) {
|
||||
const quantity = Number(cargo.quantity || 0);
|
||||
@@ -13217,11 +13227,52 @@ export default {
|
||||
}, 0)
|
||||
);
|
||||
},
|
||||
/** 精简录入提示:可调度余量扣减当前本次数量后的剩余 */
|
||||
dispatchItemHintRemainingQuantity(row = {}) {
|
||||
/**
|
||||
* 当前编辑表单中,与指定行同货物(有身份)或同单位(无身份)已占用的本次数量合计。
|
||||
* 用于剩余数量展示联动,不参与提交校验(校验仍按整单合计对比计划余量)。
|
||||
*/
|
||||
getDispatchFormOccupiedQuantity(row = {}) {
|
||||
const goodsRows =
|
||||
this.dispatchItemForm?.taskEntryMode === 'full'
|
||||
? this.dispatchItemCargoRows || []
|
||||
: [this.dispatchItemForm || row];
|
||||
const hasCargoIdentity = Boolean(
|
||||
String(row.cargoName || row.goodsName || row.name || '').trim() ||
|
||||
String(
|
||||
row.cargoType || row.secondCargoTypeName || row.goodsType || row.type || ''
|
||||
).trim()
|
||||
);
|
||||
const unit = this.getDispatchQuantityUnit(row);
|
||||
const cargoKey = this.getDispatchCargoIdentity(row);
|
||||
return goodsRows.reduce((sum, goods) => {
|
||||
if (!goods) return sum;
|
||||
if (hasCargoIdentity) {
|
||||
const goodsHasIdentity = Boolean(
|
||||
String(goods.cargoName || goods.goodsName || goods.name || '').trim() ||
|
||||
String(
|
||||
goods.cargoType || goods.secondCargoTypeName || goods.goodsType || goods.type || ''
|
||||
).trim()
|
||||
);
|
||||
if (!goodsHasIdentity || this.getDispatchCargoIdentity(goods) !== cargoKey) {
|
||||
return sum;
|
||||
}
|
||||
} else if (this.getDispatchQuantityUnit(goods) !== unit) {
|
||||
return sum;
|
||||
}
|
||||
return sum + this.parseDispatchQuantity(goods.quantity);
|
||||
}, 0);
|
||||
},
|
||||
/** 展示用剩余数量:计划可调度余量扣减本单已填本次数量(含当前行) */
|
||||
dispatchItemDisplayRemainingQuantity(row = {}) {
|
||||
// 依赖版本号,确保一行本次数量变化后其他行剩余数量一并刷新
|
||||
void this.dispatchCargoQuantityVersion;
|
||||
const available = this.dispatchItemRemainingQuantity(row);
|
||||
const current = this.parseDispatchQuantity(row.quantity);
|
||||
return Math.max(available - current, 0);
|
||||
const occupied = this.getDispatchFormOccupiedQuantity(row);
|
||||
return Math.max(available - occupied, 0);
|
||||
},
|
||||
/** 精简录入提示:与完整录入剩余数量展示规则一致 */
|
||||
dispatchItemHintRemainingQuantity(row = {}) {
|
||||
return this.dispatchItemDisplayRemainingQuantity(row);
|
||||
},
|
||||
pruneDispatchPendingRows(rows = []) {
|
||||
const planQuantities = new Map();
|
||||
|
||||
@@ -1677,7 +1677,7 @@
|
||||
{{
|
||||
isDispatchPlanQuantityUnlimited(row)
|
||||
? '-'
|
||||
: formatDispatchQuantity(dispatchItemRemainingQuantity(row))
|
||||
: formatDispatchQuantity(dispatchItemDisplayRemainingQuantity(row))
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -1861,7 +1861,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="司机" :required="dispatchItemForm.carrierType !== '承运商'">
|
||||
<el-form-item label="司机" required>
|
||||
<el-autocomplete
|
||||
v-model="dispatchItemForm.driverName"
|
||||
placeholder="请输入"
|
||||
@@ -1874,7 +1874,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="dispatchItemForm.carrierType === '承运商' ? '手机号' : '司机手机号'"
|
||||
:required="dispatchItemForm.carrierType !== '承运商'"
|
||||
required
|
||||
>
|
||||
<el-input v-model="dispatchItemForm.driverPhone" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
@@ -1955,7 +1955,7 @@
|
||||
class="transport-plan-page__dispatch-quantity-hint"
|
||||
>
|
||||
剩余数量:{{
|
||||
formatDispatchQuantity(dispatchItemHintRemainingQuantity(dispatchItemForm))
|
||||
formatDispatchQuantity(dispatchItemDisplayRemainingQuantity(dispatchItemForm))
|
||||
}}
|
||||
{{ dispatchItemForm.quantityUnit || '吨' }}
|
||||
</div>
|
||||
@@ -2096,11 +2096,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="dispatchIsRoadTransport"
|
||||
label="司机"
|
||||
:required="dispatchItemForm.carrierType === '自运'"
|
||||
>
|
||||
<el-form-item v-if="dispatchIsRoadTransport" label="司机" required>
|
||||
<el-autocomplete
|
||||
v-model="dispatchItemForm.driverName"
|
||||
placeholder="请输入"
|
||||
@@ -2111,11 +2107,7 @@
|
||||
@select="item => handleTaskDriverSelect('dispatch', item)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="dispatchIsRoadTransport"
|
||||
label="手机号"
|
||||
:required="dispatchItemForm.carrierType === '自运'"
|
||||
>
|
||||
<el-form-item v-if="dispatchIsRoadTransport" label="手机号" required>
|
||||
<el-input v-model="dispatchItemForm.driverPhone" placeholder="请输入" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -3158,6 +3150,8 @@ export default {
|
||||
dispatchItemIndex: -1,
|
||||
dispatchItemForm: defaultDispatchRow(),
|
||||
dispatchItemCargoRows: [],
|
||||
// 本次数量变更版本号:驱动同表其他行「剩余数量」同步重算
|
||||
dispatchCargoQuantityVersion: 0,
|
||||
dispatchItemAttachmentRows: [],
|
||||
selectedDispatchItemAttachmentRows: [],
|
||||
attachmentRows: [],
|
||||
@@ -7708,6 +7702,7 @@ export default {
|
||||
row.cargoName = '';
|
||||
row.specification = '';
|
||||
row.model = '';
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
handleDispatchConfiguredCargoNameChange(row, value) {
|
||||
const nextValue = String(value ?? row.cargoName ?? '').trim();
|
||||
@@ -7716,6 +7711,7 @@ export default {
|
||||
);
|
||||
if (!option) {
|
||||
row.cargoName = nextValue;
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
return;
|
||||
}
|
||||
const previousType = String(row.cargoType || '').trim();
|
||||
@@ -7730,6 +7726,7 @@ export default {
|
||||
}
|
||||
row.specification = option.specification || row.specification || '';
|
||||
row.model = option.model || row.model || '';
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
openDispatchItemDialog(index = -1, row = defaultDispatchRow()) {
|
||||
const defaultSummaryItem =
|
||||
@@ -8058,6 +8055,7 @@ export default {
|
||||
const parts = text.split('.');
|
||||
row.quantity =
|
||||
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 3)}` : parts[0];
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
handleDispatchCargoNumberInput(row, prop, value) {
|
||||
this.handleFreightNumberInput(row, prop, value);
|
||||
@@ -8077,12 +8075,14 @@ export default {
|
||||
const nextRow = this.normalizeTransportCargoRow({ priceUnit: this.defaultPriceUnit });
|
||||
if (index > -1) this.dispatchItemCargoRows.splice(index + 1, 0, nextRow);
|
||||
else this.dispatchItemCargoRows.push(nextRow);
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
removeDispatchCargoRow(index) {
|
||||
this.dispatchItemCargoRows.splice(index, 1);
|
||||
if (!this.dispatchItemCargoRows.length) {
|
||||
this.dispatchItemCargoRows.push(this.normalizeTransportCargoRow());
|
||||
}
|
||||
this.dispatchCargoQuantityVersion += 1;
|
||||
},
|
||||
dispatchCargoFreightAmount(cargo = {}) {
|
||||
if (cargo.freightAmount !== undefined && cargo.freightAmount !== null) {
|
||||
@@ -8232,11 +8232,50 @@ export default {
|
||||
}, 0)
|
||||
);
|
||||
},
|
||||
/** 精简录入提示:可调度余量扣减当前本次数量后的剩余 */
|
||||
dispatchItemHintRemainingQuantity(row = {}) {
|
||||
/**
|
||||
* 当前编辑表单中,与指定行同货物(有身份)或同单位(无身份)已占用的本次数量合计。
|
||||
* 用于剩余数量展示联动,不参与提交校验(校验仍按整单合计对比计划余量)。
|
||||
*/
|
||||
getDispatchFormOccupiedQuantity(row = {}) {
|
||||
const goodsRows =
|
||||
this.dispatchItemForm?.taskEntryMode === 'full'
|
||||
? this.dispatchItemCargoRows || []
|
||||
: [this.dispatchItemForm || row];
|
||||
const hasCargoIdentity = Boolean(
|
||||
String(row.cargoName || row.goodsName || row.name || '').trim() ||
|
||||
String(row.cargoType || row.secondCargoTypeName || row.goodsType || row.type || '').trim()
|
||||
);
|
||||
const unit = this.getDispatchQuantityUnit(row);
|
||||
const cargoKey = this.getDispatchCargoIdentity(row);
|
||||
return goodsRows.reduce((sum, goods) => {
|
||||
if (!goods) return sum;
|
||||
if (hasCargoIdentity) {
|
||||
const goodsHasIdentity = Boolean(
|
||||
String(goods.cargoName || goods.goodsName || goods.name || '').trim() ||
|
||||
String(
|
||||
goods.cargoType || goods.secondCargoTypeName || goods.goodsType || goods.type || ''
|
||||
).trim()
|
||||
);
|
||||
if (!goodsHasIdentity || this.getDispatchCargoIdentity(goods) !== cargoKey) {
|
||||
return sum;
|
||||
}
|
||||
} else if (this.getDispatchQuantityUnit(goods) !== unit) {
|
||||
return sum;
|
||||
}
|
||||
return sum + this.parseDispatchQuantity(goods.quantity);
|
||||
}, 0);
|
||||
},
|
||||
/** 展示用剩余数量:计划可调度余量扣减本单已填本次数量(含当前行) */
|
||||
dispatchItemDisplayRemainingQuantity(row = {}) {
|
||||
// 依赖版本号,确保一行本次数量变化后其他行剩余数量一并刷新
|
||||
void this.dispatchCargoQuantityVersion;
|
||||
const available = this.dispatchItemRemainingQuantity(row);
|
||||
const current = this.parseDispatchQuantity(row.quantity);
|
||||
return Math.max(available - current, 0);
|
||||
const occupied = this.getDispatchFormOccupiedQuantity(row);
|
||||
return Math.max(available - occupied, 0);
|
||||
},
|
||||
/** 精简录入提示:与完整录入剩余数量展示规则一致 */
|
||||
dispatchItemHintRemainingQuantity(row = {}) {
|
||||
return this.dispatchItemDisplayRemainingQuantity(row);
|
||||
},
|
||||
pruneDispatchPendingRows(rows = []) {
|
||||
const planQuantities = new Map();
|
||||
@@ -8334,13 +8373,17 @@ export default {
|
||||
const fullEntry = row.taskEntryMode === 'full';
|
||||
const roadTransport = this.resolveTransportMode(row.transportType) === 'road';
|
||||
if (fullEntry) {
|
||||
if (roadTransport && row.carrierType === '自运') {
|
||||
// 公路运输时司机/手机号一律必填(含承运类型为承运商)
|
||||
if (roadTransport && row.carrierType) {
|
||||
requiredFields.push(['driverName', '司机']);
|
||||
requiredFields.push(['driverPhone', '手机号']);
|
||||
}
|
||||
} else if (row.carrierType && row.carrierType !== '承运商') {
|
||||
} else if (row.carrierType) {
|
||||
requiredFields.push(['driverName', '司机']);
|
||||
requiredFields.push(['driverPhone', '司机手机号']);
|
||||
requiredFields.push([
|
||||
'driverPhone',
|
||||
row.carrierType === '承运商' ? '手机号' : '司机手机号',
|
||||
]);
|
||||
}
|
||||
const emptyField = requiredFields.find(([prop]) => this.isBillingFieldEmpty(row[prop]));
|
||||
if (emptyField) return requiredMessage(emptyField[1]);
|
||||
|
||||
Reference in New Issue
Block a user