运单调整

This commit is contained in:
2026-09-11 14:39:30 +08:00
parent 1a9cd55d66
commit 764c0f4581
7 changed files with 610 additions and 59 deletions
+3 -4
View File
@@ -92,13 +92,12 @@ export const createCrudApi = baseUrl => ({
data,
});
},
reassign(id) {
reassign(data) {
const payload = data && typeof data === 'object' ? data : { id: data };
return request({
url: `${baseUrl}/reassign`,
method: 'post',
params: {
id,
},
data: payload,
});
},
batchComplete(ids) {
+7
View File
@@ -26,6 +26,13 @@ export const maintainMileage = data =>
method: 'post',
data,
});
/** 运单打卡记录 + 司机上传凭证图 */
export const getPunchRecords = waybillId =>
request({
url: `${baseUrl}/punch-records`,
method: 'get',
params: { waybillId },
});
export const roadLoading = ids =>
request({
url: `${baseUrl}/road-loading`,
+1 -1
View File
@@ -41,7 +41,7 @@ export const planStatusOptions = [
export const waybillStatusOptions = [
{ label: '草稿', value: 'draft' },
{ label: '待执行', value: 'pending' },
{ label: '进行中', value: 'processing' },
{ label: '进行中', value: 'running' },
{ label: '已完成', value: 'completed' },
{ label: '已取消', value: 'cancelled' },
];
+48 -21
View File
@@ -92,14 +92,32 @@ const getProcessConfigNodes = row => {
const isAcceptProcessNode = node => node.key === 'accept' || node.name === '接单';
const isTruthyFlag = value => {
if (value === true || value === 1) return true;
if (value === false || value === 0 || value === null || value === undefined || value === '') {
return false;
}
return ['true', '1', 'yes'].includes(String(value).trim().toLowerCase());
};
const requiresDriverAcceptConfirmation = row =>
getProcessConfigNodes(row).some(
node =>
isAcceptProcessNode(node) &&
node.enabled !== false &&
node.confirmMode === 'yes' &&
node.confirmDriver === true
);
getProcessConfigNodes(row).some(node => {
if (!isAcceptProcessNode(node) || node.enabled === false) return false;
if (node.confirmMode === 'no_confirm_accept') return false;
// 与后端一致:是否确认=是 即需接单(不强制依赖 confirmDriver
return node.confirmMode === 'yes' || !node.confirmMode;
});
const getDriverRejectReason = row => {
if (!row) return '';
const reason =
row.driverRejectReason ||
row.driverRefuseReason ||
row.acceptRejectReason ||
row.rejectReason ||
'';
return String(reason || '').trim();
};
const isDriverRejectedStatus = value => {
if (value === null || value === undefined || typeof value === 'boolean') return false;
@@ -122,6 +140,7 @@ const isDriverRejectedStatus = value => {
};
const hasDriverRejectRecord = row => {
if (String(row.driverAcceptStatus || '').toLowerCase() === 'rejected') return true;
const rejectRecordValues = [
row.driverRejectTime,
row.driverRejectedTime,
@@ -161,9 +180,16 @@ const hasDriverRejectRecord = row => {
};
const isDriverRejectedWaybill = row =>
requiresDriverAcceptConfirmation(row) && hasDriverRejectRecord(row);
(row.requireAccept === true ||
row.requireAccept === 1 ||
requiresDriverAcceptConfirmation(row)) &&
hasDriverRejectRecord(row);
const hasDriverAcceptRecord = row => {
if (String(row.driverAcceptStatus || '').toLowerCase() === 'accepted') return true;
if (['rejected', 'pending'].includes(String(row.driverAcceptStatus || '').toLowerCase())) {
return false;
}
const recordValues = [
row.driverAcceptTime,
row.driverAcceptedTime,
@@ -172,6 +198,7 @@ const hasDriverAcceptRecord = row => {
row.driverAcceptedBy,
row.acceptUserId,
row.acceptUserName,
row.driverAcceptDriverId,
];
if (recordValues.some(value => value !== null && value !== undefined && value !== '')) {
return true;
@@ -425,26 +452,26 @@ export const config = {
statusProp: 'businessStatus',
statusTextProp: 'businessStatusName',
formatStatus(row, prop, defaultText) {
if (
prop === 'businessStatus' &&
requiresDriverAcceptConfirmation(row) &&
isInProgressStatus(row, defaultText) &&
!hasDriverAcceptRecord(row)
) {
if (prop !== 'businessStatus') return defaultText;
const status = String(row.businessStatus || '');
const terminalStatuses = ['draft', 'completed', 'cancelled', 'waiting_dispatch', 'dispatching'];
const needAccept =
row.requireAccept === true ||
row.requireAccept === 1 ||
requiresDriverAcceptConfirmation(row);
// 需司机接单且尚未接单 → 待执行(含库中仍为 running 的历史数据展示校正)
if (needAccept && !hasDriverAcceptRecord(row) && !terminalStatuses.includes(status)) {
return '待执行';
}
if (
prop === 'businessStatus' &&
row.businessStatus === 'pending' &&
!requiresDriverAcceptConfirmation(row)
) {
return '进行中';
}
if (status === 'pending') return '待执行';
if (status === 'running' || status === 'processing') return '进行中';
return defaultText;
},
canReassign(row) {
return isDriverRejectedWaybill(row);
},
getDriverRejectReason,
isDriverRejectedWaybill,
canEdit(row) {
// 进行中的运单不允许编辑
if (isInProgressStatus(row, row.businessStatusName)) {
@@ -6874,7 +6874,7 @@ export default {
const status = this.statusValue(row);
return this.config.permission === 'transport_plan'
? ['waiting_dispatch', 'dispatching'].includes(status)
: ['pending', 'processing'].includes(status);
: ['pending', 'processing', 'running'].includes(status);
},
canComplete(row) {
if (
@@ -6888,7 +6888,7 @@ export default {
const status = this.statusValue(row);
return this.config.permission === 'transport_plan'
? status === 'dispatching'
: status === 'processing';
: status === 'processing' || status === 'running';
},
canMaintainMileage(row) {
return (
@@ -100,9 +100,20 @@
</template>
<template #businessStatus="{ row }">
<el-tag :type="statusTagType(row.businessStatus)" class="status-text">
{{ displayStatus(row, 'businessStatus') }}
</el-tag>
<span class="waybill-manage-page__status-cell">
<el-tag :type="statusTagType(row.businessStatus)" class="status-text">
{{ displayStatus(row, 'businessStatus') }}
</el-tag>
<el-tooltip
v-if="driverRejectReasonText(row)"
:content="driverRejectReasonText(row)"
placement="top"
>
<el-icon class="waybill-manage-page__reject-tip-icon">
<WarnTriangleFilled />
</el-icon>
</el-tooltip>
</span>
</template>
<template #approvalStatus="{ row }">
@@ -1569,7 +1580,7 @@
<el-link type="primary" v-if="canEdit(row)" @click="openBusinessForm('edit', row)">
编辑
</el-link>
<el-link type="primary" v-if="canReassign(row)" @click="handleAction('reassign', row)">
<el-link type="primary" v-if="canReassign(row)" @click="openReassignDrawer(row)">
重新派单
</el-link>
<el-link type="primary" v-if="canCopy(row)" @click="handleCopy(row)"> 复制 </el-link>
@@ -1601,6 +1612,87 @@
</template>
</component>
<el-drawer
v-model="reassignDrawer.visible"
title="重新派单"
direction="btt"
size="280px"
append-to-body
destroy-on-close
class="waybill-manage-page__reassign-drawer"
@closed="resetReassignDrawer"
>
<el-form
ref="reassignFormRef"
:model="reassignForm"
:rules="reassignRules"
label-width="72px"
class="waybill-manage-page__reassign-form"
>
<div class="waybill-manage-page__reassign-row">
<div class="waybill-manage-page__reassign-meta">
<span class="waybill-manage-page__reassign-meta-label">运单号</span>
<span class="waybill-manage-page__reassign-meta-value">{{
reassignDrawer.row?.waybillNo || '-'
}}</span>
</div>
<div class="waybill-manage-page__reassign-meta waybill-manage-page__reassign-meta--wide">
<span class="waybill-manage-page__reassign-meta-label">拒绝原因</span>
<span class="waybill-manage-page__reassign-meta-value">{{
driverRejectReasonText(reassignDrawer.row) || '-'
}}</span>
</div>
</div>
<div class="waybill-manage-page__reassign-row">
<el-form-item label="司机" prop="driverName" class="waybill-manage-page__reassign-span-1">
<el-autocomplete
v-model="reassignForm.driverName"
placeholder="请输入"
clearable
:debounce="300"
:fetch-suggestions="fetchReassignDriverSuggestions"
:loading="reassignDrawer.driverLoading"
style="width: 100%"
@select="handleReassignDriverSelect"
@change="handleReassignDriverChange"
/>
</el-form-item>
<el-form-item
label="手机号"
prop="driverPhone"
class="waybill-manage-page__reassign-span-1"
>
<el-input
v-model="reassignForm.driverPhone"
placeholder="请输入"
clearable
maxlength="20"
/>
</el-form-item>
<el-form-item label="车牌号" prop="vehicleNo" class="waybill-manage-page__reassign-span-1">
<el-input
v-model="reassignForm.vehicleNo"
placeholder="请输入车牌号"
clearable
maxlength="30"
/>
</el-form-item>
</div>
</el-form>
<template #footer>
<div class="waybill-manage-page__reassign-footer">
<el-button @click="reassignDrawer.visible = false">取消</el-button>
<el-button
type="primary"
:loading="reassignDrawer.submitting"
@click="submitReassign"
>
确认派单
</el-button>
</div>
</template>
</el-drawer>
<el-dialog
v-model="mileageDialog.visible"
width="520px"
@@ -1934,15 +2026,88 @@
<section-card title="执行详情">
<el-tabs v-model="waybillProcessDetailTab" type="border-card">
<el-tab-pane label="打卡详情" name="punch">
<el-timeline v-if="waybillDetailProcessNodes.length">
<el-timeline-item
v-for="(node, index) in waybillDetailProcessNodes"
:key="node.key || index"
:timestamp="node.time || ''"
>{{ node.name || node.nodeName || node.label }}</el-timeline-item
>
</el-timeline>
<el-empty v-else description="暂无打卡详情" :image-size="50" />
<div v-loading="waybillPunchRecordsLoading">
<el-timeline v-if="waybillPunchRecords.length">
<el-timeline-item
v-for="(record, index) in waybillPunchRecords"
:key="record.nodeCode || record.id || index"
:timestamp="record.punchTime || record.statusName || '未打卡'"
:type="record.punched ? 'primary' : 'info'"
:color="record.punched ? '#2b6ce8' : '#c0c4cc'"
placement="top"
>
<div class="waybill-manage-page__punch-record">
<div class="waybill-manage-page__punch-record-title">
{{ record.nodeName || record.nodeCode || '打卡' }}
<el-tag
:type="record.punched ? 'success' : 'info'"
size="small"
effect="plain"
>{{ record.statusName || (record.punched ? '已打卡' : '未打卡') }}</el-tag
>
<el-tag
v-if="record.type === 'enroute'"
size="small"
type="info"
effect="plain"
>在途</el-tag
>
<el-tag
v-if="record.exceptionFlag"
size="small"
type="danger"
effect="plain"
>异常</el-tag
>
</div>
<template v-if="record.punched">
<div
v-if="record.address"
class="waybill-manage-page__punch-record-line"
>
地点{{ record.address }}
</div>
<div
v-if="record.weight || record.volume || record.quantity"
class="waybill-manage-page__punch-record-line"
>
<span v-if="record.weight">重量 {{ record.weight }}</span>
<span v-if="record.volume">体积 {{ record.volume }}</span>
<span v-if="record.quantity">数量 {{ record.quantity }}</span>
</div>
<div
v-if="record.remark"
class="waybill-manage-page__punch-record-line"
>
备注{{ record.remark }}
</div>
<div
v-if="record.photos && record.photos.length"
class="waybill-manage-page__punch-record-photos"
>
<div
v-for="(photo, pi) in record.photos"
:key="`${record.nodeCode || index}-${pi}`"
class="waybill-manage-page__driver-upload-item"
@click="previewDriverUploadPhoto(record.photos, pi)"
>
<el-image :src="photo.url" fit="cover" lazy />
<div class="waybill-manage-page__driver-upload-label">
{{ photo.label || `${record.nodeName}-凭证` }}
</div>
</div>
</div>
</template>
<div v-else class="waybill-manage-page__punch-record-line">暂未打卡</div>
</div>
</el-timeline-item>
</el-timeline>
<el-empty
v-else-if="!waybillPunchRecordsLoading"
description="暂无打卡记录"
:image-size="50"
/>
</div>
</el-tab-pane>
<el-tab-pane
v-if="waybillHasRelatedVoucher"
@@ -2012,9 +2177,30 @@
/>
</div>
</el-tab-pane>
<!-- <el-tab-pane label="司机上传" name="driverUpload">
<el-empty description="暂无司机上传数据" :image-size="50" />
</el-tab-pane> -->
<el-tab-pane label="司机上传" name="driverUpload">
<div
v-loading="waybillPunchRecordsLoading"
class="waybill-manage-page__driver-upload-grid"
>
<div
v-for="(photo, index) in waybillDriverUploads"
:key="`${photo.url}-${index}`"
class="waybill-manage-page__driver-upload-item"
:title="photo.label"
@click="previewDriverUploadPhoto(waybillDriverUploads, index)"
>
<el-image :src="photo.url" fit="cover" lazy />
<div class="waybill-manage-page__driver-upload-label">
{{ photo.label || '凭证' }}
</div>
</div>
<el-empty
v-if="!waybillPunchRecordsLoading && !waybillDriverUploads.length"
description="暂无司机上传数据"
:image-size="50"
/>
</div>
</el-tab-pane>
</el-tabs>
</section-card>
<section-card title="物流轨迹">
@@ -2837,6 +3023,7 @@ import {
getList as getProcessConfigList,
getVoucherImages as getProcessConfigVoucherImages,
} from '@/api/business/process-config';
import { getPunchRecords as getWaybillPunchRecords } from '@/api/business/waybill-manage';
import { getList as getDriverList } from '@/api/transportCapacity/driver';
import { getDictionary } from '@/api/system/dictbiz';
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
@@ -2848,7 +3035,7 @@ import { openImportDialog } from '@/utils/import-excel';
import { applyTableMenuWidth } from '@/utils/table-menu';
import { downloadFileByUrl, downloadXls } from '@/utils/util';
import { isMobile } from '@/utils/validate';
import { InfoFilled, Location, OfficeBuilding, Rank, Search } from '@element-plus/icons-vue';
import { InfoFilled, Location, OfficeBuilding, Rank, Search, WarnTriangleFilled } from '@element-plus/icons-vue';
import { ElImageViewer } from 'element-plus';
import { OpenFileViewer } from '@open-file-viewer/vue';
import {
@@ -3023,6 +3210,7 @@ export default {
PageAvueForm,
PageDetail,
InfoFilled,
WarnTriangleFilled,
Rank,
ElImageViewer,
OpenFileViewer,
@@ -3079,6 +3267,9 @@ export default {
detailLoading: false,
detailRow: {},
waybillDetailProcessNodes: [],
waybillPunchRecords: [],
waybillDriverUploads: [],
waybillPunchRecordsLoading: false,
waybillProcessDetailTab: 'punch',
waybillHasRelatedVoucher: false,
waybillVoucherImages: [],
@@ -3100,6 +3291,41 @@ export default {
submitting: false,
row: null,
},
reassignDrawer: {
visible: false,
submitting: false,
driverLoading: false,
row: null,
},
reassignForm: {
id: '',
driverId: '',
driverName: '',
driverPhone: '',
vehicleNo: '',
},
reassignDriverOptions: [],
reassignRules: {
driverName: [{ required: true, message: '请选择司机', trigger: 'change' }],
driverPhone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{
validator: (rule, value, callback) => {
if (!value) {
callback();
return;
}
if (!isMobile(value)) {
callback(new Error('请输入正确的手机号'));
return;
}
callback();
},
trigger: 'blur',
},
],
vehicleNo: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
},
mileageForm: {
id: '',
mileage: '',
@@ -3602,6 +3828,7 @@ export default {
},
waybillProcessDetailTab(tab) {
if (tab === 'batchSupplement') this.loadWaybillVoucherImages();
if (tab === 'punch' || tab === 'driverUpload') this.loadWaybillPunchRecords();
},
'form.transportType'(value, oldValue) {
if (!this.shippingInfoFormEnabled || this.suppressTransportTypeClear) return;
@@ -3884,7 +4111,7 @@ export default {
return false;
}
const status = this.statusValue(row);
return ['pending', 'processing'].includes(status);
return ['pending', 'processing', 'running'].includes(status);
},
canComplete(row) {
if (
@@ -3896,7 +4123,7 @@ export default {
return false;
}
const status = this.statusValue(row);
return status === 'processing';
return status === 'processing' || status === 'running';
},
canMaintainMileage(row) {
return (
@@ -4163,6 +4390,9 @@ export default {
this.detailRow = { ...row };
this.waybillProcessDetailTab = 'punch';
this.waybillHasRelatedVoucher = false;
this.waybillDetailProcessNodes = [];
this.waybillPunchRecords = [];
this.waybillDriverUploads = [];
this.waybillVoucherImages = [];
this.waybillVoucherFolders = [];
this.waybillVoucherFolder = null;
@@ -4176,6 +4406,7 @@ export default {
.then(res => {
const detail = res?.data?.data || res?.data || row;
this.detailRow = detail;
this.loadWaybillPunchRecords();
this.loadWaybillVoucherImages();
if (detail.contractId) {
return getContractDetail(detail.contractId)
@@ -4259,6 +4490,37 @@ export default {
})
.catch(() => []);
},
loadWaybillPunchRecords() {
const waybillId = this.detailRow?.id;
if (!waybillId || this.waybillPunchRecordsLoading) return;
this.waybillPunchRecordsLoading = true;
const request =
typeof this.api.getPunchRecords === 'function'
? this.api.getPunchRecords(waybillId)
: getWaybillPunchRecords(waybillId);
request
.then(res => {
const data = res?.data?.data || res?.data || {};
this.waybillPunchRecords = Array.isArray(data.records) ? data.records : [];
this.waybillDriverUploads = Array.isArray(data.driverUploads)
? data.driverUploads
: [];
})
.catch(() => {
this.waybillPunchRecords = [];
this.waybillDriverUploads = [];
})
.finally(() => {
this.waybillPunchRecordsLoading = false;
});
},
previewDriverUploadPhoto(photos, index) {
const list = (photos || []).map(item => item?.url).filter(Boolean);
if (!list.length) return;
this.attachmentImagePreviewUrls = list;
this.attachmentImagePreviewIndex = Math.min(Math.max(Number(index) || 0, 0), list.length - 1);
this.attachmentImagePreviewVisible = true;
},
loadWaybillVoucherImages() {
if (
!this.detailRow.id ||
@@ -7813,6 +8075,10 @@ export default {
this.$refs.mileageFormRef?.clearValidate();
},
handleAction(action, row) {
if (action === 'reassign') {
this.openReassignDrawer(row);
return;
}
const actionName = {
enable: '启用',
disable: '停用',
@@ -7831,6 +8097,113 @@ export default {
this.onLoad(this.page, this.query);
});
},
driverRejectReasonText(row) {
if (!row) return '';
if (typeof this.config.getDriverRejectReason === 'function') {
return this.config.getDriverRejectReason(row) || '';
}
return String(
row.driverRejectReason ||
row.driverRefuseReason ||
row.acceptRejectReason ||
row.rejectReason ||
''
).trim();
},
openReassignDrawer(row) {
if (!row?.id) return;
this.reassignDrawer.row = row;
this.reassignForm = {
id: row.id,
driverId: '',
driverName: '',
driverPhone: '',
vehicleNo: '',
};
this.reassignDrawer.visible = true;
this.$nextTick(() => this.$refs.reassignFormRef?.clearValidate());
},
resetReassignDrawer() {
this.reassignDrawer.row = null;
this.reassignDrawer.submitting = false;
this.reassignDrawer.driverLoading = false;
this.reassignForm = {
id: '',
driverId: '',
driverName: '',
driverPhone: '',
vehicleNo: '',
};
this.reassignDriverOptions = [];
this.$refs.reassignFormRef?.clearValidate();
},
fetchReassignDriverSuggestions(queryString, callback) {
const keyword = String(queryString || '').trim();
this.reassignDrawer.driverLoading = true;
getDriverList(1, 20, { ...(keyword ? { driverName: keyword } : {}), posts: '司机' })
.then(res => {
const records = extractRecords(res);
this.reassignDriverOptions = records;
callback(
records.map(item => ({
...item,
value: item.driverName || item.name || '',
}))
);
})
.catch(error => {
window.console.log(error);
callback([]);
})
.finally(() => {
this.reassignDrawer.driverLoading = false;
});
},
handleReassignDriverSelect(item = {}) {
const value = item.driverName || item.name || '';
const driverPhone = item.mobile || item.phone || item.driverPhone || '';
const drivingVehicle = String(item.drivingVehicle || '').trim();
this.reassignForm.driverId = item.id || '';
this.reassignForm.driverName = value;
if (driverPhone) this.reassignForm.driverPhone = driverPhone;
if (drivingVehicle) this.reassignForm.vehicleNo = drivingVehicle;
},
handleReassignDriverChange(value) {
const driver = this.reassignDriverOptions.find(item =>
[item.driverName, item.name].some(name => String(name || '') === String(value || ''))
);
this.reassignForm.driverId = driver?.id || '';
this.reassignForm.driverName = value || '';
if (driver) {
this.reassignForm.driverPhone =
driver.mobile || driver.phone || driver.driverPhone || this.reassignForm.driverPhone || '';
if (String(driver.drivingVehicle || '').trim()) {
this.reassignForm.vehicleNo = String(driver.drivingVehicle).trim();
}
}
},
submitReassign() {
this.$refs.reassignFormRef?.validate(valid => {
if (!valid) return;
this.reassignDrawer.submitting = true;
this.api
.reassign({
id: this.reassignForm.id,
driverId: this.reassignForm.driverId || null,
driverName: String(this.reassignForm.driverName || '').trim(),
driverPhone: String(this.reassignForm.driverPhone || '').trim(),
vehicleNo: String(this.reassignForm.vehicleNo || '').trim(),
})
.then(() => {
this.$message.success('重新派单成功');
this.reassignDrawer.visible = false;
this.onLoad(this.page, this.query);
})
.finally(() => {
this.reassignDrawer.submitting = false;
});
});
},
handleCustomOperation(operation, row) {
if (operation.action === 'createFromTemplate') {
this.api.getDetail(row.id).then(res => {
@@ -7933,7 +8306,7 @@ export default {
}
const unavailableWaybills = this.selectionList.filter(
row =>
this.statusValue(row) !== 'pending' ||
!['processing', 'running'].includes(this.statusValue(row)) ||
row.loadingId ||
row.loadingManageId ||
row.loadingNo
@@ -9075,6 +9448,63 @@ export default {
min-height: 120px;
}
&__punch-record {
display: flex;
flex-direction: column;
gap: 6px;
}
&__punch-record-title {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 600;
color: #303133;
}
&__punch-record-line {
font-size: 13px;
color: #606266;
span + span {
margin-left: 12px;
}
}
&__punch-record-photos,
&__driver-upload-grid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 10px;
margin-top: 4px;
min-height: 80px;
}
&__driver-upload-item {
display: flex;
flex-direction: column;
gap: 6px;
cursor: pointer;
.el-image {
display: block;
width: 100%;
aspect-ratio: 1;
border: 1px solid #eff1f7;
border-radius: 4px;
overflow: hidden;
}
}
&__driver-upload-label {
font-size: 12px;
line-height: 1.4;
color: #606266;
text-align: center;
word-break: break-all;
}
&__voucher-image-item {
position: relative;
aspect-ratio: 1;
@@ -9456,6 +9886,78 @@ export default {
:global(.waybill-manage-page__mileage-dialog .waybill-manage-page__mileage-form .el-textarea) {
width: 100%;
}
.waybill-manage-page__status-cell {
display: inline-flex;
align-items: center;
gap: 6px;
}
.waybill-manage-page__reject-tip-icon {
color: #e6a23c;
cursor: pointer;
font-size: 16px;
vertical-align: middle;
}
:global(.waybill-manage-page__reassign-drawer .el-drawer__body) {
padding: 12px 20px 0;
}
:global(.waybill-manage-page__reassign-drawer .waybill-manage-page__reassign-form) {
width: 100%;
}
.waybill-manage-page__reassign-row {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 16px;
row-gap: 8px;
margin-bottom: 12px;
align-items: start;
}
.waybill-manage-page__reassign-span-1 {
grid-column: span 1;
margin-bottom: 0;
width: 100%;
}
.waybill-manage-page__reassign-meta {
grid-column: span 1;
display: flex;
align-items: flex-start;
min-width: 0;
line-height: 32px;
font-size: 14px;
}
.waybill-manage-page__reassign-meta--wide {
grid-column: span 3;
}
.waybill-manage-page__reassign-meta-label {
flex: none;
width: 72px;
color: #606266;
text-align: right;
padding-right: 12px;
box-sizing: border-box;
}
.waybill-manage-page__reassign-meta-value {
flex: 1;
min-width: 0;
color: #303133;
word-break: break-all;
}
.waybill-manage-page__reassign-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
.el-input__icon {
color: #1e90ff !important;
}
+27 -11
View File
@@ -227,7 +227,7 @@
<el-radio-group
v-model="row.confirmMode"
:disabled="dialogReadonly || !row.enabled"
@change="syncNodeFields"
@change="handleAcceptConfirmChange(row)"
>
<el-radio label="yes"></el-radio>
<el-radio label="no_confirm_accept">无需确认接单</el-radio>
@@ -235,12 +235,7 @@
</div>
<div class="process-config-form__require-line">
<span class="process-config-form__require-label">确认接单人</span>
<el-checkbox
v-model="row.confirmDriver"
:disabled="dialogReadonly || !row.enabled || row.confirmMode !== 'yes'"
@change="syncNodeFields"
>司机</el-checkbox
>
<el-checkbox v-model="row.confirmDriver" :disabled="true">司机</el-checkbox>
</div>
</template>
@@ -551,10 +546,19 @@ export default {
hasPermission(code) {
return this.isAdmin || this.validData(this.permission && this.permission[code], false);
},
handleAcceptConfirmChange(row) {
row.confirmDriver = row.confirmMode === 'yes';
this.syncNodeFields();
},
handleReturnConfirmChange(row) {
row.confirmInternal = row.confirmMode === 'yes';
this.syncNodeFields();
},
enforceAcceptDriver(node) {
if (!node || (node.key !== 'accept' && node.name !== '接单')) return node;
node.confirmDriver = node.confirmMode === 'yes';
return node;
},
initDeptOptions() {
getDeptTree(this.userInfo.tenantId).then(res => {
const deptColumn = this.findColumn(this.option.column, 'searchDeptId');
@@ -610,7 +614,7 @@ export default {
return 'warning';
},
canEdit(row) {
return this.hasPermission('process_config_edit') && !row.readonly;
return this.hasPermission('process_config_edit') && !row.readonly && !row.hasRelatedWaybill;
},
canDelete(row) {
return (
@@ -626,7 +630,7 @@ export default {
return this.hasPermission('process_config_disable') && !row.readonly && row.status === 1;
},
cloneNode(template) {
return {
const node = {
enabled: false,
punch: true,
location: true,
@@ -641,10 +645,16 @@ export default {
supportVoucher: false,
voucherOptions: [],
confirmMode: 'yes',
confirmDriver: false,
confirmDriver: true,
confirmInternal: false,
...template,
};
if ((node.key === 'accept' || node.name === '接单') && node.confirmMode === 'yes') {
node.confirmDriver = true;
} else if ((node.key === 'accept' || node.name === '接单') && node.confirmMode !== 'yes') {
node.confirmDriver = false;
}
return node;
},
resetNodeRows() {
this.nodeRows = NODE_TEMPLATES.map(item => this.cloneNode(item));
@@ -769,6 +779,7 @@ export default {
this.syncNodeFields();
},
syncNodeFields() {
this.nodeRows.forEach(item => this.enforceAcceptDriver(item));
const enabledNodes = this.nodeRows.filter(item => item.enabled);
this.form.includedNodes = enabledNodes.map(item => item.name).join(',');
this.form.nodeConfigJson = JSON.stringify(
@@ -935,7 +946,7 @@ export default {
);
},
openConfig(row, readonly = false) {
this.dialogReadonly = readonly;
this.dialogReadonly = readonly || !!(row && row.hasRelatedWaybill);
if (!row || !row.id) {
this.form = {
configName: '',
@@ -952,6 +963,7 @@ export default {
}
api.getDetail(row.id).then(res => {
const detail = res.data.data || {};
this.dialogReadonly = readonly || !!detail.hasRelatedWaybill;
this.form = {
...detail,
defaultFinishDays:
@@ -969,6 +981,10 @@ export default {
},
submitConfig(mode) {
if (this.submitting) return;
if (this.form.id && this.form.hasRelatedWaybill) {
this.$message.warning('该项目已有运单,过程配置不可修改');
return;
}
this.syncNodeFields();
const submitRow = this.normalizeRow({
...this.form,