1、新增应付明细
2、新增应收明细 3、新增异常处置 4、新增风险处置 5、新增在途追踪 6、修复业务模块bug
This commit is contained in:
@@ -262,22 +262,20 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="配载子单号" prop="loadingSubNos" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<div class="loading-manage-page__multi-line">
|
||||
<el-link
|
||||
v-for="item in splitText(row.loadingSubNos)"
|
||||
:key="item"
|
||||
type="primary"
|
||||
class="loading-manage-page__sub-link"
|
||||
>{{ item }}</el-link>
|
||||
</div>
|
||||
<span class="loading-manage-page__sub-nos">
|
||||
{{ splitText(row.loadingSubNos).join(',') || '-' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="车牌号/航班号/船号/班列号"
|
||||
prop="vehicleNo"
|
||||
min-width="210"
|
||||
min-width="170"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
>
|
||||
<template #header>
|
||||
<span class="loading-manage-page__vehicle-header">车牌号/航班号/船号<br />班列号</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="司机" prop="driverName" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column label="联系电话" prop="driverPhone" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="承运类型" prop="carrierType" min-width="120" show-overflow-tooltip />
|
||||
@@ -285,10 +283,21 @@
|
||||
label="发货地"
|
||||
prop="departureAddress"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="途经地" prop="transitAddress" min-width="190" show-overflow-tooltip />
|
||||
<el-table-column label="到货地" prop="arrivalAddress" min-width="180" show-overflow-tooltip />
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<div class="loading-manage-page__address-cell">{{ formatRouteAddress(row, 'departure') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="途经地" prop="transitAddress" min-width="190">
|
||||
<template #default="{ row }">
|
||||
<div class="loading-manage-page__address-cell">{{ formatRouteAddress(row, 'transit') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="到货地" prop="arrivalAddress" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<div class="loading-manage-page__address-cell">{{ formatRouteAddress(row, 'arrival') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="承运商" prop="carrierName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
label="运输类型"
|
||||
@@ -369,7 +378,7 @@
|
||||
</section-card>
|
||||
<section-card title="货物信息"><el-table :data="cargoRows" border height="220"><el-table-column type="index" label="序号" width="70"/><el-table-column prop="projectName" label="项目名称" min-width="140"/><el-table-column prop="cargoName" label="货物名称" min-width="140"/><el-table-column prop="cargoType" label="货物类型" min-width="120"/><el-table-column prop="packageType" label="包装" min-width="100"/><el-table-column prop="weight" label="重量(吨)" min-width="110"/><el-table-column prop="volume" label="体积(方)" min-width="110"/><el-table-column prop="quantity" label="数量" min-width="90"/><el-table-column prop="materialCode" label="物料编码" min-width="120"/><el-table-column prop="equipmentCode" label="设备编码" min-width="120"/><el-table-column prop="brand" label="品牌" min-width="120"/><el-table-column prop="specificationModel" label="规格型号" min-width="140"/><el-table-column prop="remark" label="备注" min-width="160"/><el-table-column prop="unitPrice" label="货物单价(元)" min-width="140"/><el-table-column prop="planDate" label="计划日期" min-width="130"/></el-table></section-card>
|
||||
<section-card title="关联运单信息"><el-table :data="selectedWaybillRows" border><el-table-column type="index" label="序号" width="70"/><el-table-column prop="waybillNo" label="运单号" min-width="150"><template #default="{ row }"><el-link type="primary">{{ row.waybillNo || '-' }}</el-link></template></el-table-column><el-table-column label="配载单号" min-width="150"><template #default>{{ dialogForm.loadingNo || '-' }}</template></el-table-column><el-table-column prop="projectName" label="项目名称" min-width="150"/><el-table-column prop="customerName" label="客户" min-width="140"/><el-table-column prop="departureAddress" label="发货地址" min-width="220" show-overflow-tooltip/><el-table-column prop="arrivalAddress" label="到货地址" min-width="220" show-overflow-tooltip/></el-table></section-card>
|
||||
<div class="loading-detail__bottom-grid"><section-card title="运输节点"><template #extra><div class="loading-detail__process-actions"><el-select v-model="processProjectId" filterable remote clearable placeholder="切换项目" :remote-method="loadProjectOptions" :loading="projectLoading" @visible-change="visible => visible && loadProjectOptions()" @change="handleProcessProjectChange"><el-option v-for="item in projectOptions" :key="item.id" :label="item.projectName || item.name" :value="item.id" /></el-select><el-button plain @click="handleProcessAction('supplement')">补录执行</el-button><el-button plain @click="handleProcessAction('batch')">批量补录</el-button></div></template><el-timeline v-if="processNodes.length"><el-timeline-item v-for="(item, index) in processNodes" :key="item.id || index" :timestamp="item.time || ''">{{ item.name || item.nodeName || item.label }}</el-timeline-item></el-timeline><el-empty v-else description="暂无运输节点" :image-size="50"/></section-card><section-card title="物流轨迹"><template #extra><div class="loading-detail__track-actions"><el-button plain @click="handleTrackAction('playback')">轨迹回放</el-button><el-button plain @click="handleTrackAction('locate')">实时定位</el-button></div></template><div ref="detailAmap" class="loading-detail__map"></div></section-card></div>
|
||||
<div class="loading-detail__bottom-grid"><section-card title="运输节点"><template #extra><div class="loading-detail__process-actions"><el-select v-model="processProjectId" filterable placeholder="切换项目" @change="handleProcessProjectChange"><el-option v-for="item in processProjectOptions" :key="item.id" :label="item.projectName" :value="item.id" /></el-select><el-button plain @click="handleProcessAction('supplement')">补录执行</el-button><el-button plain @click="handleProcessAction('batch')">批量补录</el-button></div></template><el-timeline v-if="processNodes.length"><el-timeline-item v-for="(item, index) in processNodes" :key="item.id || index" :timestamp="item.time || ''">{{ item.name || item.nodeName || item.label }}</el-timeline-item></el-timeline><el-empty v-else description="暂无运输节点" :image-size="50"/></section-card><section-card title="物流轨迹"><template #extra><div class="loading-detail__track-actions"><el-button plain @click="handleTrackAction('playback')">轨迹回放</el-button><el-button plain @click="handleTrackAction('locate')">实时定位</el-button></div></template><div ref="detailAmap" class="loading-detail__map"></div></section-card></div>
|
||||
</div>
|
||||
<el-form
|
||||
v-else
|
||||
@@ -384,7 +393,7 @@
|
||||
<template #extra>
|
||||
<el-link v-if="!dialogReadonly" type="primary" @click="openCandidateSearch">筛选</el-link>
|
||||
</template>
|
||||
<div class="loading-manage-dialog__candidate-search" v-if="candidateSearchVisible">
|
||||
<div class="loading-manage-dialog__candidate-search">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="运单号">
|
||||
@@ -424,6 +433,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<template v-if="candidateSearchVisible">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="货物名称">
|
||||
<el-input v-model="candidateQuery.cargoName" clearable placeholder="请输入" />
|
||||
@@ -562,14 +572,24 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="loading-manage-dialog__candidate-actions">
|
||||
</template>
|
||||
<el-col
|
||||
:span="candidateSearchVisible ? 24 : 6"
|
||||
class="loading-manage-dialog__candidate-actions"
|
||||
>
|
||||
<el-button type="primary" @click="handleCandidateSearch">查询</el-button>
|
||||
<el-button @click="handleCandidateReset">重置</el-button>
|
||||
<el-link type="primary" @click="candidateSearchVisible = false"
|
||||
>收起</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
@click="candidateSearchVisible = !candidateSearchVisible"
|
||||
>{{ candidateSearchVisible ? '收起' : '展开' }}</el-link>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</section-card>
|
||||
|
||||
<section-card title="配载信息" class="loading-manage-dialog__load-info-card">
|
||||
<section-card title="待配载运单">
|
||||
<el-table
|
||||
ref="candidateTableRef"
|
||||
v-loading="candidateLoading"
|
||||
@@ -736,9 +756,8 @@
|
||||
<el-table-column prop="cargoName" label="货物名称" min-width="140" />
|
||||
<el-table-column prop="cargoType" label="货物类型" min-width="140" />
|
||||
<el-table-column prop="packageType" label="包装" min-width="100" />
|
||||
<el-table-column prop="weight" label="重量(吨)" min-width="120" />
|
||||
<el-table-column prop="volume" label="体积(方)" min-width="120" />
|
||||
<el-table-column prop="quantity" label="数量" min-width="100" />
|
||||
<el-table-column prop="quantityUnit" label="单位" min-width="100" />
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="130" />
|
||||
<el-table-column prop="equipmentCode" label="设备编码" min-width="130" />
|
||||
<el-table-column prop="brand" label="品牌" min-width="120" />
|
||||
@@ -759,7 +778,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="loading-manage-dialog__grid">
|
||||
<el-form-item v-if="dialogForm.carrierType !== '自运'" label="承运商" required>
|
||||
<el-form-item v-if="!['自运', '网货平台'].includes(dialogForm.carrierType)" label="承运商" required>
|
||||
<el-select
|
||||
v-model="dialogForm.carrierName"
|
||||
clearable
|
||||
@@ -779,7 +798,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="司机" :required="dialogForm.carrierType === '自运'">
|
||||
<el-form-item label="司机" :required="['自运', '网货平台'].includes(dialogForm.carrierType)">
|
||||
<el-select
|
||||
v-model="dialogForm.driverName"
|
||||
clearable
|
||||
@@ -802,7 +821,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" :required="dialogForm.carrierType === '自运'">
|
||||
<el-form-item label="手机号" :required="['自运', '网货平台'].includes(dialogForm.carrierType)">
|
||||
<el-input v-model="dialogForm.driverPhone" clearable placeholder="请输入" />
|
||||
</el-form-item>
|
||||
<el-form-item label="车牌号" required>
|
||||
@@ -855,6 +874,7 @@
|
||||
</el-form-item>
|
||||
</div>
|
||||
</section-card>
|
||||
</section-card>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
@@ -1111,6 +1131,7 @@ export default {
|
||||
config: loadingManageConfig,
|
||||
processNodes: [],
|
||||
processProjectId: '',
|
||||
processProjectOptions: [],
|
||||
routeChangeVisible: false,
|
||||
routeChangeTab: 'change',
|
||||
routeChangeRows: [],
|
||||
@@ -1229,6 +1250,30 @@ export default {
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean);
|
||||
},
|
||||
formatRouteAddress(row, type) {
|
||||
const prefix = type === 'departure' ? 'departure' : type === 'arrival' ? 'arrival' : 'transit';
|
||||
const values = [
|
||||
row[`${prefix}Name`],
|
||||
row[`${prefix}RegionName`],
|
||||
row[`${prefix}DistrictName`],
|
||||
row[`${prefix}Address`],
|
||||
]
|
||||
.filter(Boolean)
|
||||
.flatMap(value => this.splitText(value));
|
||||
const addressType = [
|
||||
row[`${prefix}AddressType`],
|
||||
row[`${prefix}Type`],
|
||||
row.addressType,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('');
|
||||
const isStation = /港口|码头|机场|铁路|车站|空港/.test(`${addressType}${values[0] || ''}`);
|
||||
const displayValues = values.filter(
|
||||
(value, index) => index === 0 || isStation || !row[`${prefix}Name`] || value !== row[`${prefix}Address`]
|
||||
);
|
||||
if (type === 'transit') return displayValues.join(',') || '-';
|
||||
return (isStation ? displayValues[0] : row[`${prefix}Name`] || displayValues[0]) || '-';
|
||||
},
|
||||
rowActions(row) {
|
||||
const status = row.businessStatus;
|
||||
if (status === 'draft') {
|
||||
@@ -1286,12 +1331,11 @@ export default {
|
||||
...createDialogForm(),
|
||||
...(res.data?.data || res.data || {}),
|
||||
};
|
||||
this.processProjectId = this.dialogForm.projectId || '';
|
||||
await this.loadProjectOptions(this.dialogForm.projectName || '');
|
||||
await this.restoreWaybillRows(
|
||||
this.dialogForm.waybillIdsJson,
|
||||
this.dialogForm.loadingSubNos
|
||||
);
|
||||
this.syncProcessProjectOptions();
|
||||
this.restoreRouteAndCargo();
|
||||
this.restoreRouteChangeRecords();
|
||||
await this.loadProcessNodes();
|
||||
@@ -1326,6 +1370,7 @@ export default {
|
||||
this.candidateSearchVisible = false;
|
||||
this.processNodes = [];
|
||||
this.processProjectId = '';
|
||||
this.processProjectOptions = [];
|
||||
},
|
||||
clearLoadingDialog() {
|
||||
this.resetDialogData();
|
||||
@@ -1355,13 +1400,62 @@ export default {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const rows = unwrapRecords(await getProcessConfigList(1, 20, { projectId: this.processProjectId, status: 1 }));
|
||||
const config = rows.find(item => item.nodeConfigJson) || {};
|
||||
this.processNodes = parseJsonArray(config.nodeConfigJson);
|
||||
const projectId = String(this.processProjectId);
|
||||
const rows = unwrapRecords(
|
||||
await getProcessConfigList(1, 100, { projectIds: projectId, status: 1 })
|
||||
);
|
||||
const config =
|
||||
rows.find(item => {
|
||||
const projectIds = String(item.projectIds || '')
|
||||
.split(',')
|
||||
.map(value => value.trim())
|
||||
.filter(Boolean);
|
||||
return projectIds.includes(projectId) && item.nodeConfigJson;
|
||||
}) || {};
|
||||
this.processNodes = this.parseProcessConfigNodes(config);
|
||||
} catch (error) {
|
||||
this.processNodes = [];
|
||||
}
|
||||
},
|
||||
syncProcessProjectOptions() {
|
||||
const projectMap = new Map();
|
||||
this.selectedWaybillRows.forEach(row => {
|
||||
const id = row.projectId;
|
||||
if (!id || projectMap.has(String(id))) return;
|
||||
projectMap.set(String(id), {
|
||||
id,
|
||||
projectName: row.projectName || row.projectNames || String(id),
|
||||
});
|
||||
});
|
||||
if (!projectMap.size && this.dialogForm.projectId) {
|
||||
projectMap.set(String(this.dialogForm.projectId), {
|
||||
id: this.dialogForm.projectId,
|
||||
projectName: this.dialogForm.projectName || String(this.dialogForm.projectId),
|
||||
});
|
||||
}
|
||||
this.processProjectOptions = [...projectMap.values()];
|
||||
this.processProjectId = this.processProjectOptions[0]?.id || '';
|
||||
},
|
||||
parseProcessConfigNodes(config = {}) {
|
||||
let nodes = [];
|
||||
try {
|
||||
const parsed =
|
||||
typeof config.nodeConfigJson === 'string'
|
||||
? JSON.parse(config.nodeConfigJson)
|
||||
: config.nodeConfigJson;
|
||||
nodes = Array.isArray(parsed) ? parsed : parsed?.nodes || [];
|
||||
} catch (error) {
|
||||
nodes = [];
|
||||
}
|
||||
const includedNodes = String(config.includedNodes || '')
|
||||
.split(',')
|
||||
.map(value => value.trim())
|
||||
.filter(Boolean);
|
||||
return nodes.filter(
|
||||
node =>
|
||||
node.enabled !== false && (!includedNodes.length || includedNodes.includes(node.name))
|
||||
);
|
||||
},
|
||||
async handleProcessProjectChange() {
|
||||
await this.loadProcessNodes();
|
||||
},
|
||||
@@ -1605,7 +1699,7 @@ export default {
|
||||
this.dialogForm.loadingSubNos = rows
|
||||
.map(row => row.waybillNo)
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
.join(',');
|
||||
this.dialogForm.waybillIdsJson = JSON.stringify(rows.map(row => row.id).filter(Boolean));
|
||||
this.dialogForm.projectName = uniqueText(rows, 'projectName');
|
||||
this.dialogForm.customerName = uniqueText(rows, 'customerName');
|
||||
@@ -1697,6 +1791,16 @@ export default {
|
||||
weight: item.weight || item.cargoWeight || '',
|
||||
volume: item.volume || item.cargoVolume || '',
|
||||
quantity: item.quantity || item.cargoQuantity || waybill.quantity || '',
|
||||
quantityUnit:
|
||||
item.quantityUnit ||
|
||||
item.goodsQuantityUnit ||
|
||||
item.cargoUnit ||
|
||||
item.unit ||
|
||||
waybill.quantityUnit ||
|
||||
waybill.goodsQuantityUnit ||
|
||||
waybill.cargoUnit ||
|
||||
waybill.unit ||
|
||||
'',
|
||||
planDate: item.planDate || waybill.startDate || '',
|
||||
unitPrice: item.unitPrice || waybill.unitPrice || '',
|
||||
materialCode: item.materialCode || '',
|
||||
@@ -1754,7 +1858,7 @@ export default {
|
||||
ElMessage.warning('请输入车牌号');
|
||||
return false;
|
||||
}
|
||||
if (this.dialogForm.carrierType === '自运') {
|
||||
if (['自运', '网货平台'].includes(this.dialogForm.carrierType)) {
|
||||
if (!this.dialogForm.driverName || !this.dialogForm.driverPhone) {
|
||||
ElMessage.warning('请输入司机和司机手机号');
|
||||
return false;
|
||||
@@ -1855,6 +1959,7 @@ export default {
|
||||
{
|
||||
...this.buildQueryParams(this.searchForm),
|
||||
ids,
|
||||
exportColumns: JSON.stringify(loadingManageConfig.exportColumns),
|
||||
},
|
||||
{
|
||||
feedback: true,
|
||||
@@ -1864,7 +1969,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleCarrierTypeChange() {
|
||||
if (this.dialogForm.carrierType === '自运') {
|
||||
if (['自运', '网货平台'].includes(this.dialogForm.carrierType)) {
|
||||
this.dialogForm.carrierName = '';
|
||||
}
|
||||
},
|
||||
@@ -1991,17 +2096,27 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loading-manage-page__link,
|
||||
.loading-manage-page__sub-link {
|
||||
.loading-manage-page__link {
|
||||
padding: 0;
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
.loading-manage-page__multi-line {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
line-height: 1.6;
|
||||
.loading-manage-page__sub-nos {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.loading-manage-page__address-cell {
|
||||
line-height: 20px;
|
||||
white-space: pre-line;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.loading-manage-page__vehicle-header {
|
||||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.loading-manage-page__status {
|
||||
@@ -2069,12 +2184,12 @@ export default {
|
||||
|
||||
.loading-manage-dialog__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0 24px;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__span-2 {
|
||||
grid-column: span 2;
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.loading-manage-dialog__title-action {
|
||||
@@ -2118,6 +2233,10 @@ export default {
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.loading-manage-dialog__grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.loading-manage-dialog__waybill-route-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@@ -2233,5 +2352,14 @@ export default {
|
||||
}
|
||||
.loading-route-change-dialog { .loading-route-change-dialog__original { color: #a8abb2; line-height: 20px; margin-bottom: 4px; }.loading-route-change-dialog__location { cursor: pointer; color: #909399; }.loading-route-change-dialog__hint { color: #909399; }.loading-route-change-dialog__route-list { display: flex; flex-direction: column; gap: 8px; }.loading-route-change-dialog__route-item { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto 24px; align-items: center; gap: 12px; padding: 10px 12px; background: #f5f6f7; cursor: move; }.loading-route-change-dialog__route-type { width: 30px; height: 30px; border-radius: 50%; background: #dcdfe6; text-align: center; line-height: 30px; }.loading-route-change-dialog__tags { display: flex; gap: 4px; }.loading-route-change-dialog__record-content { white-space: normal; overflow-wrap: anywhere; line-height: 22px; } }
|
||||
.loading-common-address-dialog__toolbar { display: flex; gap: 8px; margin-bottom: 12px; }.loading-common-address-dialog__toolbar .el-input { flex: 1; }
|
||||
@media (max-width: 900px) { .loading-detail__task-row, .loading-detail__bottom-grid { grid-template-columns: 1fr; } }
|
||||
@media (max-width: 900px) {
|
||||
.loading-manage-dialog__grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.loading-detail__task-row,
|
||||
.loading-detail__bottom-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user