✨ 业务数量单位改走计量单位,并放开运输计划日期必填

发货模板、运输计划、运单与总单调度从计量单位取 unitName;修复调度提交顶层单位为空,并取消计划开始/结束日期必填。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-04 20:26:35 +08:00
co-authored by Cursor
parent 0b81001ce7
commit 7751a735c5
13 changed files with 323 additions and 139 deletions
@@ -2742,6 +2742,7 @@ import { packageOptions } from '@/option/business/common';
import { formatUpdateUserName } from '@/utils/audit';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeMapSearchResults, searchAmapPlaceText } from '@/utils/map-search';
import { loadMeasurementUnitOptions } from '@/utils/measurement-unit';
import { applyTableMenuWidth } from '@/utils/table-menu';
import { downloadFileByUrl, downloadXls } from '@/utils/util';
import { isMobile } from '@/utils/validate';
@@ -3206,7 +3207,7 @@ export default {
billingCargoTypeLoading: false,
billingCargoTypeRequest: null,
packageOptions,
quantityUnitOptions: ['吨', '千克', '立方米', '件', '车', '箱', '托盘'],
quantityUnitOptions: [],
attachmentFileTypes: [
'pdf',
'bmp',
@@ -3245,6 +3246,7 @@ export default {
} else {
this.consumeTemplateCreatePayload();
}
this.loadTaskQuantityUnitOptions();
},
computed: {
...mapGetters(['permission', 'userInfo']),
@@ -4307,8 +4309,6 @@ export default {
['contractName', '客户合同'],
['planName', '计划名称'],
['transportType', '运输方式'],
['planStartDate', '计划开始日期'],
['planEndDate', '计划结束日期'],
['departureAddress', '发货地址'],
['arrivalAddress', '收货地址'],
];
@@ -5076,15 +5076,40 @@ export default {
return Promise.resolve(this.taskQuantityUnitOptions);
}
this.taskQuantityUnitLoading = true;
return getDictionary({ code: 'quantity_unit' })
.then(res => {
this.taskQuantityUnitOptions = this.normalizeDictOptions(res.data.data || []);
return loadMeasurementUnitOptions()
.then(options => {
this.taskQuantityUnitOptions = options;
this.quantityUnitOptions = options.map(item => item.value);
this.ensureQuantityUnitOptions([
this.dispatchItemForm?.quantityUnit,
...(this.dispatchItemCargoRows || []).map(row => row.quantityUnit),
...(this.transportCargoRows || []).map(row => row.quantityUnit),
]);
return this.taskQuantityUnitOptions;
})
.finally(() => {
this.taskQuantityUnitLoading = false;
});
},
ensureQuantityUnitOptions(units = []) {
const pending = [...new Set(
(Array.isArray(units) ? units : [units])
.map(item => String(item || '').trim())
.filter(Boolean)
)];
if (!pending.length) return;
pending.forEach(unit => {
if (!this.quantityUnitOptions.includes(unit)) {
this.quantityUnitOptions = [...this.quantityUnitOptions, unit];
}
if (!this.taskQuantityUnitOptions.some(item => item.value === unit)) {
this.taskQuantityUnitOptions = [
...this.taskQuantityUnitOptions,
{ label: unit, value: unit },
];
}
});
},
loadTaskFeeUnitOptions() {
if (this.taskFeeUnitOptions.length || this.taskFeeUnitLoading) {
return Promise.resolve(this.taskFeeUnitOptions);
@@ -5146,6 +5171,9 @@ export default {
});
},
normalizeTransportCargoRow(row = {}) {
const quantityUnit = String(
row.quantityUnit || row.goodsQuantityUnit || row.unit || ''
).trim();
const cargo = {
...defaultTransportCargo(),
...row,
@@ -5162,10 +5190,14 @@ export default {
packageType: row.packageType || row.package || '',
specification: row.specification || row.spec || '',
freightAmount: row.freightAmount ?? row.amount ?? row.totalAmount ?? '',
quantityUnit,
};
['quantity', 'mileage', 'unitPrice', 'freightAmount'].forEach(prop => {
if (Number(cargo[prop]) === -1) cargo[prop] = '';
});
if (quantityUnit) {
this.ensureQuantityUnitOptions(quantityUnit);
}
return cargo;
},
hasMultipleConfiguredGoods(source = {}, rows = []) {
@@ -7594,6 +7626,9 @@ export default {
...baseRow,
...(index >= 0 ? row : {}),
};
this.dispatchItemForm.quantityUnit =
this.dispatchItemForm.quantityUnit || defaultUnit || TRANSPORT_PLAN_QUANTITY_UNIT;
this.ensureQuantityUnitOptions(this.dispatchItemForm.quantityUnit);
this.dispatchItemForm.otherFeeTotal = this.normalizeDispatchFeeValue(
this.dispatchItemForm.otherFeeTotal
);
@@ -7603,7 +7638,11 @@ export default {
});
const goodsRows = this.parseJsonArray(this.dispatchItemForm.goodsJson);
this.dispatchItemCargoRows = (goodsRows.length ? goodsRows : [this.dispatchItemForm]).map(
item => this.normalizeTransportCargoRow(item)
item =>
this.normalizeTransportCargoRow({
...item,
quantityUnit: item.quantityUnit || this.dispatchItemForm.quantityUnit || defaultUnit,
})
);
const hasMultiplePlanGoods = this.dispatchPlanGoodsRows.length > 1;
const shouldAutoFillFullGoods =
@@ -7613,11 +7652,18 @@ export default {
const unscheduledGoodsRows = this.getDispatchUnscheduledGoodsRows();
this.dispatchItemForm.taskEntryMode = 'full';
this.dispatchItemForm.quantity = '';
this.dispatchItemCargoRows = unscheduledGoodsRows.length
? unscheduledGoodsRows
: this.dispatchPlanGoodsRows.map(goods =>
this.normalizeTransportCargoRow({ ...goods, quantity: '' })
);
this.dispatchItemCargoRows = (
unscheduledGoodsRows.length
? unscheduledGoodsRows
: this.dispatchPlanGoodsRows.map(goods =>
this.normalizeTransportCargoRow({ ...goods, quantity: '' })
)
).map(goods =>
this.normalizeTransportCargoRow({
...goods,
quantityUnit: goods.quantityUnit || defaultUnit || TRANSPORT_PLAN_QUANTITY_UNIT,
})
);
}
if (!this.dispatchItemCargoRows.length) {
this.dispatchItemCargoRows = [this.normalizeTransportCargoRow()];
@@ -8309,7 +8355,10 @@ export default {
this.dispatchItemForm.cargoName ||
'',
quantity: quantityText,
quantityUnit: firstGoods.quantityUnit || this.dispatchItemForm.quantityUnit || '',
quantityUnit:
firstGoods.quantityUnit ||
this.dispatchItemForm.quantityUnit ||
TRANSPORT_PLAN_QUANTITY_UNIT,
unitPrice: firstGoods.unitPrice || '',
priceUnit: firstGoods.priceUnit || '',
freightTotal: this.dispatchItemFreightTotal,
@@ -8324,7 +8373,7 @@ export default {
unitPrice: cargo.unitPrice || '',
priceUnit: cargo.priceUnit || '',
quantity: cargo.quantity || '',
quantityUnit: cargo.quantityUnit || '',
quantityUnit: cargo.quantityUnit || firstGoods.quantityUnit || TRANSPORT_PLAN_QUANTITY_UNIT,
freightAmount: this.dispatchCargoFreightAmount(cargo),
})),
}),
@@ -8413,26 +8462,40 @@ export default {
return {
id: this.dispatchRow.id,
mode,
waybills: rows.map(row => ({
...row,
taskEntryMode: row.taskEntryMode || 'simple',
taskRemark: row.remark || '',
estimatedStartTime: this.formatDispatchDate(row.estimatedStartTime),
estimatedEndTime: this.formatDispatchDate(row.estimatedEndTime),
goodsJson:
row.goodsJson ||
JSON.stringify([
waybills: rows.map(row => {
const quantityUnit = this.getDispatchQuantityUnit(row);
let goodsJson = row.goodsJson;
const goodsRows = this.parseJsonArray(goodsJson);
if (goodsRows.length) {
goodsJson = JSON.stringify(
goodsRows.map(goods => ({
...goods,
quantityUnit: goods.quantityUnit || quantityUnit,
}))
);
} else {
goodsJson = JSON.stringify([
{
cargoName: row.cargoName,
cargoType: row.cargoType,
quantity: row.quantity,
quantityUnit: row.quantityUnit,
quantityUnit,
specification: row.specification,
model: row.model,
packageType: row.packageType,
},
]),
})),
]);
}
return {
...row,
quantityUnit,
taskEntryMode: row.taskEntryMode || 'simple',
taskRemark: row.remark || '',
estimatedStartTime: this.formatDispatchDate(row.estimatedStartTime),
estimatedEndTime: this.formatDispatchDate(row.estimatedEndTime),
goodsJson,
};
}),
};
},
formatDispatchDate(value) {