✨ 优化港口地图回填、合同展示与运单导入空值

地图选点回填国家省市区;合同选择显示编号/名称;常用数据组织筛选修正;运单详情将-1费用字段显示为空。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-09 17:07:56 +08:00
parent 570fbeb537
commit a1da644c49
25 changed files with 568 additions and 217 deletions
@@ -374,7 +374,7 @@
<el-option
v-for="item in contracts"
:key="item.id"
:label="item.contractName"
:label="formatContractOptionLabel(item)"
:value="item.id"
/>
</el-select>
@@ -610,6 +610,7 @@ import { getList as getProjectList } from '@/api/business/project-apply';
import { getList as getDriverList } from '@/api/transportCapacity/driver';
import { getDictionary } from '@/api/system/dictbiz';
import * as api from '@/api/business/waybill-manage';
import { formatContractOptionLabel } from '@/utils/contract';
import { downloadXls } from '@/utils/util';
import SectionCard from '@/components/section-card/main.vue';
@@ -1297,6 +1298,31 @@ const carrierChange = value => {
form.carrierName = item.carrierName || '';
if (!isSelfOperated.value) form.carrierContractId = item.carrierContractId || '';
};
const firstNotEmpty = (...values) => values.find(value => String(value ?? '').trim()) ?? '';
const OPTIONAL_NUMBER_EMPTY_SENTINELS = [-1];
const normalizeOptionalImportNumber = (value, emptySentinels = OPTIONAL_NUMBER_EMPTY_SENTINELS) => {
if (!String(value ?? '').trim()) return null;
return emptySentinels.some(sentinel => Number(value) === sentinel) ? null : value;
};
const normalizeImportRow = row => ({
...row,
mileage: normalizeOptionalImportNumber(
firstNotEmpty(row.mileage, row['里程'], row['里程(km)'], row['里程(公里)'])
),
otherFeeTotal: normalizeOptionalImportNumber(
firstNotEmpty(row.otherFeeTotal, row['其他费用合计'])
),
unitPrice: normalizeOptionalImportNumber(firstNotEmpty(row.unitPrice, row['单价'])),
freight: normalizeOptionalImportNumber(firstNotEmpty(row.freight, row['运费'])),
freightTotal: normalizeOptionalImportNumber(firstNotEmpty(row.freightTotal, row['运费合计'])),
transportType: firstNotEmpty(
row.transportType,
row['运输类型'],
row['*运输类型'],
row['运输方式'],
row['*运输方式']
),
});
const fileChange = async (file, list) => {
if (!projectInfoReady.value) {
ElMessage.warning('请先选择项目、客户合同和承运信息,再导入运单明细');
@@ -1370,6 +1396,9 @@ const fileChange = async (file, list) => {
item[key] ??
'';
});
['mileage', 'unitPrice', 'freight', 'otherFeeTotal', 'freightTotal'].forEach(prop => {
row[prop] = normalizeOptionalImportNumber(row[prop]);
});
row.actualStartDate = normalizeImportDate(row.actualStartDate);
row.actualEndDate = normalizeImportDate(row.actualEndDate);
row.planStartDate = normalizeImportDate(row.planStartDate);
@@ -1656,31 +1685,6 @@ const removeSelectedRows = () => {
rowSelection.value = [];
refreshDuplicateFlags();
};
const firstNotEmpty = (...values) => values.find(value => String(value ?? '').trim()) ?? '';
const normalizeOptionalImportNumber = (value, emptySentinels = []) => {
if (!String(value ?? '').trim()) return null;
return emptySentinels.some(sentinel => Number(value) === sentinel) ? null : value;
};
const normalizeImportRow = row => ({
...row,
mileage: normalizeOptionalImportNumber(
firstNotEmpty(row.mileage, row['里程'], row['里程(km)'], row['里程(公里)']),
[-1]
),
otherFeeTotal: normalizeOptionalImportNumber(
firstNotEmpty(row.otherFeeTotal, row['其他费用合计'])
),
unitPrice: normalizeOptionalImportNumber(firstNotEmpty(row.unitPrice, row['单价'])),
freight: normalizeOptionalImportNumber(firstNotEmpty(row.freight, row['运费'])),
freightTotal: normalizeOptionalImportNumber(firstNotEmpty(row.freightTotal, row['运费合计'])),
transportType: firstNotEmpty(
row.transportType,
row['运输类型'],
row['*运输类型'],
row['运输方式'],
row['*运输方式']
),
});
const normalizeOptionalPlanId = value => {
if (value === undefined || value === null || value === '') return null;
return Number(value) === -1 || Number(value) <= 0 ? null : value;