🔀 合并 websoft/dev,统一待回单确认与公路配载校验
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -294,8 +294,8 @@ export default {
|
||||
query: { id: String(customerId), name: '查看客商档案', view: '1' },
|
||||
});
|
||||
},
|
||||
waybillStatusName(value) { return ({ pending: '待执行', waiting: '待执行', running: '进行中', processing: '进行中', completed: '已完成', cancelled: '已取消' })[value] || value || '-'; },
|
||||
waybillStatusType(value) { return ({ pending: 'info', waiting: 'info', running: 'warning', processing: 'warning', completed: 'success', cancelled: 'danger' })[value] || 'info'; },
|
||||
waybillStatusName(value) { return ({ pending: '待执行', waiting: '待执行', running: '进行中', processing: '进行中', pending_return_confirm: '待回单确认', completed: '已完成', cancelled: '已取消' })[value] || value || '-'; },
|
||||
waybillStatusType(value) { return ({ pending: 'info', waiting: 'info', running: 'warning', processing: 'warning', pending_return_confirm: 'warning', completed: 'success', cancelled: 'danger' })[value] || 'info'; },
|
||||
statusName(value) { return ({ waiting_dispatch: '待调度', dispatching: '调度中', completed: '调度完成', closed: '调度关闭' })[value] || value || '-'; },
|
||||
statusType(value) { return ({ waiting_dispatch: 'warning', dispatching: 'success', completed: 'primary', closed: 'danger' })[value] || 'info'; },
|
||||
},
|
||||
|
||||
@@ -210,7 +210,11 @@
|
||||
@mousedown="() => handleDriverFocus(route)"
|
||||
@focus="() => handleDriverFocus(route)"
|
||||
@select="handleDriverSuggestionSelect"
|
||||
/></el-form-item
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete></el-form-item
|
||||
></el-col>
|
||||
<el-col :span="6"
|
||||
><el-form-item
|
||||
@@ -239,7 +243,11 @@
|
||||
@mousedown="() => handleDriverFocus(route)"
|
||||
@focus="() => handleDriverFocus(route)"
|
||||
@select="handleEscortSuggestionSelect"
|
||||
/></el-form-item
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete></el-form-item
|
||||
></el-col>
|
||||
<el-col v-if="route.carrierType !== '承运商'" :span="6"
|
||||
><el-form-item label="押运人手机号"
|
||||
@@ -316,7 +324,7 @@
|
||||
|
||||
<script>
|
||||
import * as api from '@/api/business/master-order';
|
||||
import { fetchDriversByCarrierOrganizations } from '@/utils/carrier-org-resource';
|
||||
import { fetchDriverCandidates, driverOptionText } from '@/utils/carrier-org-resource';
|
||||
import { formatContractOptionLabel } from '@/utils/contract';
|
||||
import {
|
||||
currencyUnit,
|
||||
@@ -403,6 +411,7 @@ export default {
|
||||
this.applySelfOperatedCarrierDefaults();
|
||||
},
|
||||
methods: {
|
||||
driverOptionText,
|
||||
loadQuantityUnitOptions() {
|
||||
if (this.quantityUnitLoading) return this.quantityUnitLoadPromise;
|
||||
this.quantityUnitLoading = true;
|
||||
@@ -944,12 +953,6 @@ export default {
|
||||
route.escortPhone = '';
|
||||
this.driverOptions = [];
|
||||
},
|
||||
getRouteCarrierFilter(route = {}) {
|
||||
return {
|
||||
carrierId: route.carrierId || '',
|
||||
carrierName: route.carrierName || '',
|
||||
};
|
||||
},
|
||||
carrierOptionValue(item = {}) {
|
||||
return item.contractId || item.id || item.value || item.carrierName || '';
|
||||
},
|
||||
@@ -1026,36 +1029,22 @@ export default {
|
||||
this.activeSuggestRoute = route;
|
||||
},
|
||||
async loadDriverOptions(route = {}, keyword = '') {
|
||||
const carrier = this.getRouteCarrierFilter(route);
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
this.driverOptions = [];
|
||||
return [];
|
||||
}
|
||||
this.driverLoading = true;
|
||||
try {
|
||||
this.driverOptions = await fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' },
|
||||
carrier
|
||||
);
|
||||
this.driverOptions = await fetchDriverCandidates({
|
||||
size: 20,
|
||||
...(keyword ? { driverName: keyword } : {}),
|
||||
posts: '司机',
|
||||
});
|
||||
return this.driverOptions;
|
||||
} finally {
|
||||
this.driverLoading = false;
|
||||
}
|
||||
},
|
||||
fetchDriverSuggestions(queryString, callback) {
|
||||
const route = this.activeSuggestRoute || {};
|
||||
const carrier = this.getRouteCarrierFilter(route);
|
||||
const keyword = String(queryString || '').trim();
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
if (!keyword) this.$message.warning('请先选择承运商');
|
||||
return;
|
||||
}
|
||||
this.driverLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' })
|
||||
.then(records => {
|
||||
this.driverOptions = records;
|
||||
callback(
|
||||
@@ -1080,19 +1069,13 @@ export default {
|
||||
if (drivingVehicle) route.vehicleNo = drivingVehicle;
|
||||
},
|
||||
fetchEscortSuggestions(queryString, callback) {
|
||||
const route = this.activeSuggestRoute || {};
|
||||
const keyword = String(queryString || '').trim();
|
||||
const carrier = this.getRouteCarrierFilter(route);
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
if (!keyword) this.$message.warning('请先选择承运商');
|
||||
return;
|
||||
}
|
||||
this.escortLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '押运员' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({
|
||||
size: 20,
|
||||
...(keyword ? { driverName: keyword } : {}),
|
||||
posts: '押运员',
|
||||
})
|
||||
.then(records => {
|
||||
callback(
|
||||
records.map(item => ({
|
||||
|
||||
@@ -1870,7 +1870,11 @@
|
||||
:fetch-suggestions="fetchTaskDriverSuggestions"
|
||||
:loading="taskDriverLoading"
|
||||
@select="item => handleTaskDriverSelect('dispatch', item)"
|
||||
/>
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="dispatchItemForm.carrierType === '承运商' ? '手机号' : '司机手机号'"
|
||||
@@ -1893,7 +1897,11 @@
|
||||
:fetch-suggestions="fetchTaskEscortSuggestions"
|
||||
:loading="taskEscortLoading"
|
||||
@select="handleTaskEscortSelect"
|
||||
/>
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dispatchItemForm.carrierType !== '承运商'" label="押运人手机号">
|
||||
<el-input v-model="dispatchItemForm.escortPhone" placeholder="请输入" />
|
||||
@@ -2760,7 +2768,7 @@ import {
|
||||
getList as getProjectList,
|
||||
} from '@/api/business/project-apply';
|
||||
import { getList as getCommonRouteList } from '@/api/business/common-route';
|
||||
import { fetchDriversByCarrierOrganizations } from '@/utils/carrier-org-resource';
|
||||
import { fetchDriverCandidates, driverOptionText } from '@/utils/carrier-org-resource';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||
import { addressTypeOptions } from '@/option/base/common-address';
|
||||
@@ -3809,6 +3817,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formatContractOptionLabel,
|
||||
driverOptionText,
|
||||
initStandaloneFormPage() {
|
||||
if (!this.isStandaloneFormPage) return;
|
||||
const mode = this.$route.query.mode === 'edit' ? 'edit' : 'add';
|
||||
@@ -4178,6 +4187,7 @@ export default {
|
||||
waiting: ['待执行', 'is-pending'],
|
||||
processing: ['进行中', 'is-processing'],
|
||||
running: ['进行中', 'is-processing'],
|
||||
pending_return_confirm: ['待回单确认', 'is-pending'],
|
||||
completed: ['已完成', 'is-completed'],
|
||||
cancelled: ['已取消', 'is-cancelled'],
|
||||
};
|
||||
@@ -4988,16 +4998,8 @@ export default {
|
||||
},
|
||||
fetchTaskDriverSuggestions(queryString, callback) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const carrier = this.getDispatchCarrierFilter();
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
this.taskDriverLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' })
|
||||
.then(records => {
|
||||
this.taskDriverOptions = records;
|
||||
callback(
|
||||
@@ -5017,16 +5019,12 @@ export default {
|
||||
},
|
||||
fetchTaskEscortSuggestions(queryString, callback) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const carrier = this.getDispatchCarrierFilter();
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
this.taskEscortLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '押运员' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({
|
||||
size: 20,
|
||||
...(keyword ? { driverName: keyword } : {}),
|
||||
posts: '押运员',
|
||||
})
|
||||
.then(records => {
|
||||
this.taskEscortOptions = records;
|
||||
callback(records.map(item => ({ ...item, value: item.driverName || item.name || '' })));
|
||||
@@ -8044,12 +8042,6 @@ export default {
|
||||
this.taskDriverOptions = [];
|
||||
this.taskEscortOptions = [];
|
||||
},
|
||||
getDispatchCarrierFilter() {
|
||||
return {
|
||||
carrierId: this.dispatchItemForm.carrierId || '',
|
||||
carrierName: this.dispatchItemForm.carrierName || '',
|
||||
};
|
||||
},
|
||||
handleDispatchCargoQuantityInput(row, value) {
|
||||
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||
const parts = text.split('.');
|
||||
|
||||
@@ -1381,11 +1381,23 @@ const formatOptionalNumber = value => {
|
||||
const normalized = normalizeOptionalImportNumber(value);
|
||||
return normalized === null || normalized === undefined ? '' : normalized;
|
||||
};
|
||||
// 明细接口返回运单实体字段 startDate/endDate/estimatedStartTime/estimatedEndTime,
|
||||
// 而明细表与编辑回填按导入列字段名 actualStartDate 等读取,重载后在此对齐,否则实际/预计时间列为空。
|
||||
const detailDateAliases = {
|
||||
actualStartDate: 'startDate',
|
||||
actualEndDate: 'endDate',
|
||||
planStartDate: 'estimatedStartTime',
|
||||
planEndDate: 'estimatedEndTime',
|
||||
};
|
||||
const normalizeDetailRow = row => {
|
||||
const next = { ...(row || {}) };
|
||||
OPTIONAL_NUMBER_PROPS.forEach(prop => {
|
||||
next[prop] = formatOptionalNumber(next[prop]);
|
||||
});
|
||||
Object.entries(detailDateAliases).forEach(([prop, source]) => {
|
||||
if (String(next[prop] ?? '').trim()) return;
|
||||
if (String(next[source] ?? '').trim()) next[prop] = next[source];
|
||||
});
|
||||
return next;
|
||||
};
|
||||
const normalizeImportRow = row => ({
|
||||
|
||||
@@ -1200,7 +1200,11 @@
|
||||
:loading="taskDriverLoading"
|
||||
:disabled="dialogReadonly"
|
||||
@select="handleTaskDriverSelect"
|
||||
/>
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="isRoadTransport"
|
||||
@@ -1279,7 +1283,11 @@
|
||||
:loading="taskEscortLoading"
|
||||
:disabled="dialogReadonly"
|
||||
@select="handleTaskEscortSelect"
|
||||
/>
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showRoadEscortFields" label="押运人手机号">
|
||||
<el-input
|
||||
@@ -1591,8 +1599,15 @@
|
||||
<el-link type="primary" v-if="canCancel(row)" @click="handleAction('cancel', row)">
|
||||
取消
|
||||
</el-link>
|
||||
<el-link type="primary" v-if="canComplete(row)" @click="handleCompleteAction(row)">
|
||||
{{ completeActionLabelFor(row) }}
|
||||
<el-link type="primary" v-if="canComplete(row)" @click="handleAction('complete', row)">
|
||||
{{ completeActionLabel }}
|
||||
</el-link>
|
||||
<el-link
|
||||
type="primary"
|
||||
v-if="canConfirmReturn(row)"
|
||||
@click="handleAction('confirmReturn', row)"
|
||||
>
|
||||
确认回单
|
||||
</el-link>
|
||||
<el-link type="primary" v-if="canMaintainMileage(row)" @click="openMileageDialog(row)">
|
||||
维护里程
|
||||
@@ -1653,7 +1668,11 @@
|
||||
style="width: 100%"
|
||||
@select="handleReassignDriverSelect"
|
||||
@change="handleReassignDriverChange"
|
||||
/>
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<span>{{ driverOptionText(item) }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="手机号"
|
||||
@@ -3683,6 +3702,7 @@ import {
|
||||
getVoucherImages as getProcessConfigVoucherImages,
|
||||
} from '@/api/business/process-config';
|
||||
import {
|
||||
getList as getWaybillList,
|
||||
getPunchRecords as getWaybillPunchRecords,
|
||||
locateVehicle,
|
||||
savePunchRecord,
|
||||
@@ -3692,9 +3712,7 @@ import VoucherExecutionDetail from './voucher-execution-detail.vue';
|
||||
import PunchRecordPhotos from './punch-record-photos.vue';
|
||||
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||
import {
|
||||
fetchDriversByCarrierOrganizations,
|
||||
} from '@/utils/carrier-org-resource';
|
||||
import { fetchDriverCandidates, driverOptionText } from '@/utils/carrier-org-resource';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||
import { addressTypeOptions } from '@/option/base/common-address';
|
||||
@@ -4370,9 +4388,15 @@ export default {
|
||||
addBtn: this.canCreate,
|
||||
};
|
||||
},
|
||||
// 打卡记录编辑入口与运单编辑同权限:能改运单的人才能订正它的打卡流水
|
||||
// 打卡记录编辑入口与运单编辑同权限:能改运单的人才能订正它的打卡流水。
|
||||
// 时间轴的「编辑打卡 / 补卡」链接是本页唯一写入入口,提交固定 punched=true。
|
||||
// 取消打卡不在本页;待回单确认的运单不显示该链接。
|
||||
canEditWaybillPunchRecord() {
|
||||
return this.hasPermission(`${this.config.permission}_edit`) && !this.readonlyScope;
|
||||
return (
|
||||
this.hasPermission(`${this.config.permission}_edit`) &&
|
||||
!this.readonlyScope &&
|
||||
this.statusValue(this.detailRow) !== 'pending_return_confirm'
|
||||
);
|
||||
},
|
||||
waybillPunchEditNode() {
|
||||
return this.findWaybillPunchEditNodeConfig(this.waybillPunchEditRecord);
|
||||
@@ -4800,6 +4824,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formatContractOptionLabel,
|
||||
driverOptionText,
|
||||
parseRouteChangeContent,
|
||||
// 页面被 keep-alive 缓存/卸载时调用,关闭本页所有 append-to-body 的弹窗,
|
||||
// 避免 Teleport 出去的 DOM 残留在 body 上盖住后续页面(详见 data 里的说明)。
|
||||
@@ -5099,7 +5124,8 @@ export default {
|
||||
return false;
|
||||
}
|
||||
const status = this.statusValue(row);
|
||||
return status === 'pending';
|
||||
// 待回单确认可取消,取消不生成应收应付
|
||||
return status === 'pending' || status === 'pending_return_confirm';
|
||||
},
|
||||
canComplete(row) {
|
||||
if (
|
||||
@@ -5111,29 +5137,17 @@ export default {
|
||||
return false;
|
||||
}
|
||||
const status = this.statusValue(row);
|
||||
return status === 'processing' || status === 'running' || status === 'pending_return';
|
||||
// 待回单确认也可直接完成,不经确认回单
|
||||
return status === 'processing' || status === 'running' || status === 'pending_return_confirm';
|
||||
},
|
||||
completeActionLabelFor(row) {
|
||||
return this.statusValue(row) === 'pending_return' ? '确认回单' : this.completeActionLabel;
|
||||
},
|
||||
handleCompleteAction(row) {
|
||||
const isPendingReturn = this.statusValue(row) === 'pending_return';
|
||||
const actionName = this.completeActionLabelFor(row);
|
||||
this.$confirm(`确定${actionName}该${this.config.title}?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
if (isPendingReturn && typeof this.api.confirmReturn === 'function') {
|
||||
return this.api.confirmReturn(row.id);
|
||||
}
|
||||
return this.api.complete(row.id);
|
||||
})
|
||||
.then(() => {
|
||||
this.$message.success(`${actionName}成功`);
|
||||
this.onLoad(this.page, this.query);
|
||||
});
|
||||
canConfirmReturn(row) {
|
||||
return (
|
||||
this.hasAction('confirmReturn') &&
|
||||
this.hasPermission(`${this.config.permission}_complete`) &&
|
||||
!this.readonlyScope &&
|
||||
!row.readonly &&
|
||||
this.statusValue(row) === 'pending_return_confirm'
|
||||
);
|
||||
},
|
||||
canMaintainMileage(row) {
|
||||
return (
|
||||
@@ -6565,7 +6579,7 @@ export default {
|
||||
if (status === 'completed') {
|
||||
return 'primary';
|
||||
}
|
||||
if (status === 'pending_return') {
|
||||
if (status === 'pending_return_confirm') {
|
||||
return 'warning';
|
||||
}
|
||||
return 'warning';
|
||||
@@ -7967,19 +7981,10 @@ export default {
|
||||
this.taskDriverOptions = [];
|
||||
this.taskEscortOptions = [];
|
||||
},
|
||||
getTaskCarrierFilter() {
|
||||
return {
|
||||
carrierId: this.form.carrierId || '',
|
||||
carrierName: this.form.carrierName || '',
|
||||
};
|
||||
},
|
||||
loadTaskDriverOptions() {
|
||||
if (!this.taskInfoFormEnabled || this.taskDriverLoading) return Promise.resolve([]);
|
||||
this.taskDriverLoading = true;
|
||||
return fetchDriversByCarrierOrganizations(
|
||||
{ size: 9999, posts: '司机' },
|
||||
this.getTaskCarrierFilter()
|
||||
)
|
||||
return fetchDriverCandidates({ size: 9999, posts: '司机' })
|
||||
.then(records => {
|
||||
this.taskDriverOptions = records;
|
||||
return this.taskDriverOptions;
|
||||
@@ -7990,16 +7995,8 @@ export default {
|
||||
},
|
||||
fetchTaskDriverSuggestions(queryString, callback) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const carrier = this.getTaskCarrierFilter();
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
this.taskDriverLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' })
|
||||
.then(records => {
|
||||
this.taskDriverOptions = records;
|
||||
callback(
|
||||
@@ -8019,16 +8016,12 @@ export default {
|
||||
},
|
||||
fetchTaskEscortSuggestions(queryString, callback) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const carrier = this.getTaskCarrierFilter();
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
this.taskEscortLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '押运员' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({
|
||||
size: 20,
|
||||
...(keyword ? { driverName: keyword } : {}),
|
||||
posts: '押运员',
|
||||
})
|
||||
.then(records => {
|
||||
this.taskEscortOptions = records;
|
||||
callback(records.map(item => ({ ...item, value: item.driverName || item.name || '' })));
|
||||
@@ -10175,8 +10168,14 @@ export default {
|
||||
cancel: '取消',
|
||||
complete: this.completeActionLabel,
|
||||
reassign: '重新派单',
|
||||
confirmReturn: '确认回单',
|
||||
}[action];
|
||||
this.$confirm(`确定${actionName}该${this.config.title}?`, '提示', {
|
||||
// 确认回单是终态动作(本轮不做撤销),把后果写在提示里,别让人以为还能退回
|
||||
const confirmText =
|
||||
action === 'confirmReturn'
|
||||
? '确认回单后该运单将置为已完成,且不可撤销。是否继续?'
|
||||
: `确定${actionName}该${this.config.title}?`;
|
||||
this.$confirm(confirmText, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
@@ -10229,20 +10228,8 @@ export default {
|
||||
},
|
||||
fetchReassignDriverSuggestions(queryString, callback) {
|
||||
const keyword = String(queryString || '').trim();
|
||||
const row = this.reassignDrawer.row || {};
|
||||
const carrier = {
|
||||
carrierId: row.carrierId || '',
|
||||
carrierName: row.carrierName || '',
|
||||
};
|
||||
if (!carrier.carrierId && !carrier.carrierName) {
|
||||
callback([]);
|
||||
return;
|
||||
}
|
||||
this.reassignDrawer.driverLoading = true;
|
||||
fetchDriversByCarrierOrganizations(
|
||||
{ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' },
|
||||
carrier
|
||||
)
|
||||
fetchDriverCandidates({ size: 20, ...(keyword ? { driverName: keyword } : {}), posts: '司机' })
|
||||
.then(records => {
|
||||
this.reassignDriverOptions = records;
|
||||
callback(
|
||||
@@ -10382,11 +10369,11 @@ export default {
|
||||
return;
|
||||
}
|
||||
const pendingReturnCount = this.selectionList.filter(
|
||||
row => this.statusValue(row) === 'pending_return'
|
||||
row => this.statusValue(row) === 'pending_return_confirm'
|
||||
).length;
|
||||
const tip =
|
||||
pendingReturnCount > 0
|
||||
? `确定完成选中的运单?其中 ${pendingReturnCount} 条为待确认回单,确认后将转为已完成。`
|
||||
? `确定完成选中的运单?其中 ${pendingReturnCount} 条为待回单确认,确认后将转为已完成。`
|
||||
: '确定完成选中的运单?';
|
||||
this.$confirm(tip, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -10402,25 +10389,38 @@ export default {
|
||||
this.onLoad(this.page, this.query);
|
||||
});
|
||||
},
|
||||
handleRoadLoading() {
|
||||
async handleRoadLoading() {
|
||||
if (!this.selectionList.length) {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
const nonRoadWaybills = this.selectionList.filter(row => !this.waybillIsRoadTransport(row));
|
||||
if (nonRoadWaybills.length) {
|
||||
this.$message.warning('公路配载仅支持运输方式为“公路运输”的运单');
|
||||
const selectedIds = this.selectionList.map(row => row.id).filter(Boolean);
|
||||
if (!selectedIds.length) {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
const unavailableWaybills = this.selectionList.filter(
|
||||
row =>
|
||||
!['pending', 'processing', 'running'].includes(this.statusValue(row)) ||
|
||||
row.loadingId ||
|
||||
row.loadingManageId ||
|
||||
row.loadingNo
|
||||
);
|
||||
if (unavailableWaybills.length) {
|
||||
this.$message.warning('公路配载仅支持待执行/进行中且未关联有效配载单的运单');
|
||||
// 可配载与否只看后端查询结果
|
||||
let loadableIds;
|
||||
try {
|
||||
const res = await getWaybillList(1, selectedIds.length, {
|
||||
loadableOnly: 1,
|
||||
ids: selectedIds.join(','),
|
||||
});
|
||||
loadableIds = new Set(extractRecords(res).map(row => String(row.id)));
|
||||
} catch (error) {
|
||||
this.$message.error('校验运单可配载状态失败,请重试');
|
||||
return;
|
||||
}
|
||||
const rejectedRows = this.selectionList.filter(row => !loadableIds.has(String(row.id)));
|
||||
if (rejectedRows.length) {
|
||||
const rejectedText = rejectedRows
|
||||
.map(row => {
|
||||
const reason = this.roadLoadingRejectReasonText(row);
|
||||
const no = row.waybillNo || row.id || '';
|
||||
return `${no}(${reason})`;
|
||||
})
|
||||
.join('、');
|
||||
this.$message.warning(`${rejectedText};公路配载仅支持公路、待执行且未配载的运单`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -10443,6 +10443,13 @@ export default {
|
||||
},
|
||||
});
|
||||
},
|
||||
// 只给后端判定为不可配载的运单生成可读原因,本身不参与准入判定
|
||||
roadLoadingRejectReasonText(row = {}) {
|
||||
if (!this.waybillIsRoadTransport(row)) return '非公路运输';
|
||||
if (String(row.businessStatus || '') !== 'pending') return '状态不是待执行';
|
||||
if (row.loadingNo) return '已关联配载单';
|
||||
return '运单数据可能已变化,请刷新后重试';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user