Files
tms-erp-web/src/option/business/waybill-manage.js
T
weicw-dshsa 509f5e163c ✨ 打卡详情展示异常状态并新增异常节点展示
运单详情「打卡详情」时间轴按节点关联异常处置:存在未了结异常时显示「异常」标签
与「跟进」链接,全部处理完成时显示「已处理异常」与「详情」链接。异常跟节点走,
节点未打卡也可能有异常。

异常来源改用异常处置表而非打卡行的 exception_flag —— 后者由打卡接口写入且未随
异常上报维护,实测有异常的节点该值仍为 0,原「异常」标签从未显示过。

「已处理」的口径与后端打卡门禁一致(已完成、已撤销都放行),故「处理中」仍算
未处理。

异常节点字段补入各处异常信息:运单详情「异常上报」表格、编辑弹窗、跟进/详情
弹窗,统一放在异常类型之前;表格内空节点显示「-」而不是留白(存量异常无节点)。

过程节点列显示配置中的中文名而非原始 key(库里混存 key 与中文名两种格式)。

删除打卡详情中在途节点的「在途」标签 —— 节点名已表明是在途。
2026-10-05 15:13:34 +08:00

1151 lines
32 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
auditColumns,
createCrudOption,
dataSourceOptions,
phoneRule,
selectRule,
textRule,
waybillStatusOptions,
withSearchPlaceholders,
} from './common';
const transportTypeDict = {
dicUrl: '/blade-system/dict-biz/dictionary?code=transport_type',
props: {
label: 'dictValue',
value: 'dictKey',
},
};
const isEmpty = value => value === undefined || value === null || value === '';
const normalizeNumericDisplayValue = value => (Number(value) === -1 ? '' : value);
const formatMoneyDisplay = value => {
if (isEmpty(value) || Number(value) === -1) return '';
const number = Number(value);
if (!Number.isFinite(number)) return '';
return number.toFixed(2);
};
const parseJsonArray = value => {
if (Array.isArray(value)) return value;
if (typeof value !== 'string' || !value.trim()) return [];
try {
const result = JSON.parse(value);
if (Array.isArray(result)) return result;
if (Array.isArray(result.records)) return result.records;
if (Array.isArray(result.rows)) return result.rows;
return [];
} catch (error) {
return [];
}
};
const parseJsonObject = value => {
if (!value) return {};
if (typeof value === 'object' && !Array.isArray(value)) return value;
if (typeof value !== 'string' || !value.trim()) return {};
try {
const result = JSON.parse(value);
return result && typeof result === 'object' && !Array.isArray(result) ? result : {};
} catch (error) {
return {};
}
};
const parseProcessNodes = value => {
const result = parseJsonArray(value);
if (result.length) return result;
if (typeof value === 'string' && value.trim()) {
try {
const parsed = JSON.parse(value);
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
return Array.isArray(parsed.nodes) ? parsed.nodes : [];
}
} catch (error) {
return [];
}
}
if (!value || typeof value !== 'object' || Array.isArray(value)) return [];
return Array.isArray(value.nodes) ? value.nodes : [];
};
const getProcessConfigNodes = row => {
const sources = [
row.processJson,
row.processConfigJson,
row.projectProcessJson,
row.processConfig,
row.projectProcessConfig,
];
return sources.flatMap(source => {
const nodes = parseProcessNodes(source);
if (nodes.length || !source || typeof source !== 'object' || Array.isArray(source)) {
return nodes;
}
const configuredNodes = parseProcessNodes(source.nodeConfigJson);
const includedNodes = String(source.includedNodes || '')
.split(',')
.map(item => item.trim())
.filter(Boolean);
return configuredNodes.filter(
node =>
!includedNodes.length ||
includedNodes.includes(node.name) ||
includedNodes.includes(node.key)
);
});
};
const isAcceptProcessNode = node => node.key === 'accept' || node.name === '接单';
/**
* 过程节点列显示文案。
*
* 该列在库里存的是「原始值」,且历史上写入了两种格式:司机打卡推进写的是配置的
* key(unload / dispatch / load …),配载单新建默认值写的是中文名(接单)。
* 故这里按两种格式都认一次,认不出就原样显示,不把值吞掉。
*
* 运单创建后、司机首次打卡前该字段为空,属正常——显示「-」,避免留白看不出是没值还是没渲染。
*/
const formatCurrentProcessNode = row => {
const value = String(getFirstValue(row, ['currentProcessNode', 'currentNode']) || '').trim();
if (!value) return '-';
const node = getProcessConfigNodes(row).find(
item => item.key === value || item.name === value
);
return node?.name || node?.key || value;
};
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 => {
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;
return [
'-1',
'2',
'reject',
'rejected',
'refuse',
'refused',
'decline',
'declined',
'deny',
'denied',
'拒绝',
'已拒绝',
'拒绝接单',
'已拒绝接单',
].includes(String(value).trim().toLowerCase());
};
const hasDriverRejectRecord = row => {
if (String(row.driverAcceptStatus || '').toLowerCase() === 'rejected') return true;
const rejectRecordValues = [
row.driverRejectTime,
row.driverRejectedTime,
row.driverRefuseTime,
row.acceptRejectTime,
row.driverRejectReason,
row.driverRefuseReason,
row.acceptRejectReason,
];
if (rejectRecordValues.some(value => !isEmpty(value))) return true;
const driverStatusProps = [
'driverAcceptStatus',
'driverAccepted',
'driverAccept',
'accepted',
'isAccepted',
'acceptStatus',
'driverResponseStatus',
'driverOrderStatus',
'driverAcceptResult',
'acceptResult',
];
if (driverStatusProps.some(prop => isDriverRejectedStatus(row[prop]))) return true;
const nodeStatusProps = [
...driverStatusProps,
'confirmStatus',
'executionStatus',
'nodeStatus',
'status',
'result',
];
return getProcessConfigNodes(row)
.filter(isAcceptProcessNode)
.some(node => nodeStatusProps.some(prop => isDriverRejectedStatus(node[prop])));
};
const isDriverRejectedWaybill = 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,
row.acceptTime,
row.driverAcceptId,
row.driverAcceptedBy,
row.acceptUserId,
row.acceptUserName,
row.driverAcceptDriverId,
];
if (recordValues.some(value => value !== null && value !== undefined && value !== '')) {
return true;
}
const statusValues = [
row.driverAcceptStatus,
row.driverAccepted,
row.driverAccept,
row.accepted,
row.isAccepted,
row.acceptStatus,
];
return statusValues.some(value => {
if (value === true) return true;
if (value === false || value === null || value === undefined || value === '') return false;
return ['1', 'true', 'accepted', 'confirmed', 'success', '已接单', '已确认'].includes(
String(value).toLowerCase()
);
});
};
const isInProgressStatus = (row, defaultText) =>
['processing', 'running', 'in_progress', 'inProgress'].includes(
String(row.businessStatus || row.status || row.waybillStatus || '')
) ||
String(defaultText || '').includes('进行中') ||
String(row.businessStatusName || row.statusName || '').includes('进行中');
const getFirstValue = (row, props) => {
const prop = props.find(item => !isEmpty(row[item]));
return prop ? row[prop] : '';
};
const getGoodsRows = row => parseJsonArray(row.goodsList || row.goodsRows || row.goodsJson);
const getDetailedGoodsRows = row => {
const goodsRows = [
row.goodsJson,
row.goodsList,
row.goodsRows,
row.cargoList,
row.cargoRows,
row.goods,
]
.map(source => {
if (source === undefined || source === null || source === '') return [];
if (Array.isArray(source)) return source;
if (typeof source === 'object') return [source];
return parseJsonArray(source);
})
.filter(source => source.length)
.sort((left, right) => right.length - left.length);
return goodsRows[0] || [];
};
const getBillingRows = row => {
const freightRows = parseJsonArray(row.freightList || row.freightRows || row.freightJson);
if (freightRows.length) return freightRows;
return parseJsonArray(row.billingPlanJson).flatMap(item =>
Array.isArray(item.rules) ? item.rules : []
);
};
const joinText = list => list.filter(item => !isEmpty(item)).join('/');
const formatGoodsInfo = row => {
const goodsRows = [
row.goodsJson,
row.goodsList,
row.goodsRows,
row.cargoList,
row.cargoRows,
row.goods,
]
.map(source => {
if (source === undefined || source === null || source === '') return [];
if (Array.isArray(source)) return source;
if (typeof source === 'object') return [source];
return parseJsonArray(source);
})
.filter(source => source.length)
.sort((left, right) => right.length - left.length)[0] || [];
const text = getFirstValue(row, ['goodsInfo', 'cargoInfo']);
if (!goodsRows.length) return text || '';
return goodsRows
.map(item => {
const name = getFirstValue(item, ['cargoName', 'goodsName', 'name']);
const type = getFirstValue(item, ['cargoType', 'goodsType', 'typeName']);
const quantity = joinText([
normalizeNumericDisplayValue(
getFirstValue(item, ['quantity', 'cargoQuantity', 'goodsQuantity'])
),
getFirstValue(item, ['quantityUnit', 'goodsQuantityUnit', 'cargoUnit', 'unit']) ||
getFirstValue(row, ['quantityUnit', 'goodsQuantityUnit', 'cargoUnit', 'unit']),
]);
return joinText([name, type, quantity]);
})
.filter(Boolean)
.join('; ') || text || '';
};
const formatGoodsField = (row, props) => {
const value = getFirstValue(row, props);
if (value) return value;
const goods = getGoodsRows(row).find(item => getFirstValue(item, props));
return goods ? getFirstValue(goods, props) : '';
};
const formatUnitPrice = row => {
const value = normalizeNumericDisplayValue(getFirstValue(row, ['unitPrice', 'price']));
const unit = getFirstValue(row, ['priceUnit', 'billingUnit', 'unit']);
const goodsRows = getDetailedGoodsRows(row);
if (goodsRows.length > 1) {
const billingRows = getBillingRows(row);
const goodsPrices = goodsRows
.map((item, index) => {
const itemPrice = normalizeNumericDisplayValue(
getFirstValue(item, ['unitPrice', 'price'])
);
if (!isEmpty(itemPrice)) return itemPrice;
return normalizeNumericDisplayValue(
getFirstValue(billingRows[index] || {}, ['unitPrice', 'price'])
);
})
.filter(itemPrice => !isEmpty(itemPrice));
const priceKeys = goodsPrices.map(itemPrice => {
const numericPrice = Number(itemPrice);
return Number.isFinite(numericPrice) ? String(numericPrice) : String(itemPrice).trim();
});
if (new Set(priceKeys).size > 1) return '-';
}
if (!isEmpty(value)) return unit ? `${value}(${unit})` : value;
const billing = getBillingRows(row).find(
item => !isEmpty(normalizeNumericDisplayValue(item.unitPrice))
);
if (!billing) return '';
const billingUnit = getFirstValue(billing, ['priceUnit', 'billingUnit', 'unit']);
const billingPrice = normalizeNumericDisplayValue(billing.unitPrice);
return billingUnit ? `${billingPrice}(${billingUnit})` : billingPrice;
};
const formatAmount = (row, props) => formatMoneyDisplay(getFirstValue(row, props));
const sumAmount = (rows = []) =>
rows.reduce((sum, item) => {
const value = getFirstValue(item, ['freightAmount', 'amount', 'totalAmount']);
return isEmpty(value) ? sum : sum + Number(value || 0);
}, 0);
const calculateFreightTotal = rows => {
if (!rows.length) return '';
let hasAmountField = false;
const total = rows.reduce((sum, item) => {
const amount = getFirstValue(item, ['freightAmount', 'amount']);
if (!isEmpty(amount)) {
hasAmountField = true;
return sum + Number(amount || 0);
}
if (isEmpty(item?.unitPrice) || isEmpty(item?.quantity)) return sum;
hasAmountField = true;
return sum + Number(item.unitPrice || 0) * Number(item.quantity || 0);
}, 0);
if (!hasAmountField) return '';
return Number.isFinite(total) ? total.toFixed(2) : '';
};
const formatFreight = row => {
const value = formatAmount(row, ['freight', 'freightAmount', 'transportFee']);
if (!isEmpty(value)) return value;
const freight = parseJsonObject(row.freightJson);
const freightValue = getFirstValue(freight, ['freightAmount', 'transportFee']);
if (!isEmpty(freightValue)) return formatMoneyDisplay(freightValue);
const total = sumAmount(Array.isArray(freight.freightItems) ? freight.freightItems : []);
return total ? formatMoneyDisplay(total) : '';
};
const formatOtherFeeTotal = row => {
const value = formatAmount(row, ['otherFeeTotal', 'otherAmount', 'otherFeeAmount']);
return Number(value) === -1 ? '' : value;
};
const formatFreightTotal = row => {
const freight = parseJsonObject(row.freightJson);
const freightItems = Array.isArray(freight.freightItems) ? freight.freightItems : [];
const goodsRows = getGoodsRows(row);
const calculated = calculateFreightTotal(freightItems.length ? freightItems : goodsRows);
const otherFee = getFirstValue(freight, ['otherFreightAmount', 'otherFeeTotal']);
const otherFeeTotal = !isEmpty(otherFee) ? otherFee : formatOtherFeeTotal(row);
if (!isEmpty(calculated)) {
const total = Number(calculated || 0) + Number(otherFeeTotal || 0);
return Number.isFinite(total) ? total.toFixed(2) : calculated;
}
const value = getFirstValue(freight, ['totalFreightAmount', 'totalFreight', 'totalAmount']);
if (!isEmpty(value)) return formatMoneyDisplay(value);
return formatAmount(row, ['freightTotal', 'totalFreight', 'totalAmount']);
};
const auditColumn = prop => ({ ...auditColumns.find(item => item.prop === prop) });
export const config = {
title: '运单管理',
permission: 'waybill_manage',
importUrl: '/blade-transport/waybill-manage/import-waybill-manage',
exportUrl: '/blade-transport/waybill-manage/export-waybill-manage',
exportName: '运单管理',
defaultForm: {
carrierType: '承运商',
transportType: 'road',
quantityUnit: '吨',
priceUnit: '元/吨',
},
enableAllDept: false,
enableProjectSelect: true,
projectQueryParams: {
approvalStatuses: 'approved,change_approved',
},
contractQueryParams: {
contractCategory: '客户合同',
},
templateCreateTarget: 'waybill-manage',
enableContractSelect: true,
enableShippingPlanSelect: true,
enableShippingInfoForm: true,
enableAttachmentTable: true,
attachmentTitle: '附件',
fixedTransportAddressType: true,
enableTaskInfoForm: true,
enableWaybillFooterFreightSummary: true,
enableDraftSave: true,
saveAsDraft: true,
skipDraftValidation: true,
draftStatusProp: 'businessStatus',
draftStatus: 'draft',
draftSaveText: '暂存',
batchDelete: false,
actionButtonLikeSearch: true,
createText: '新建运单',
importText: '导入运单',
enableWaybillImport: true,
roadLoading: true,
roadLoadingText: '公路配载',
searchRangeMap: {
startDateRange: ['startDateStart', 'startDateEnd'],
endDateRange: ['endDateStart', 'endDateEnd'],
createTimeRange: ['createTimeStart', 'createTimeEnd'],
},
actions: ['copy', 'cancel', 'reassign', 'complete', 'batchComplete'],
detailButton: true,
statusProp: 'businessStatus',
statusTextProp: 'businessStatusName',
formatStatus(row, prop, defaultText) {
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 (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)) {
return false;
}
return !isDriverRejectedWaybill(row);
},
canCancel(row) {
// 进行中的运单不允许取消
return !isInProgressStatus(row, row.businessStatusName);
},
deleteStatus: ['draft'],
editStatus: ['draft', 'pending'],
};
export const option = {
dialogCustomClass: 'waybill-manage-dialog',
...createCrudOption(
withSearchPlaceholders([
{
label: '',
prop: 'basicInfoTitle',
formslot: true,
span: 24,
order: 900,
hide: true,
labelWidth: 0,
},
{
label: '运单号',
prop: 'waybillNo',
search: true,
searchOrder: 23,
minWidth: 150,
addDisplay: false,
editDisabled: true,
},
{
label: '配载单号',
prop: 'loadingNo',
search: true,
searchOrder: 5,
span: 6,
order: 840,
minWidth: 140,
addDisplay: false,
editDisplay: false,
},
{
label: '总单号',
prop: 'masterNo',
search: true,
searchLabel: '多联总单',
searchOrder: 6,
span: 6,
order: 830,
minWidth: 140,
addDisplay: false,
editDisplay: false,
},
{
label: '项目名称',
prop: 'projectName',
formslot: true,
search: true,
searchLabel: '项目名称',
searchPlaceholder: '请选择或输入',
searchOrder: 22,
span: 6,
order: 890,
minWidth: 150,
rules: textRule('项目', 100, true),
},
{
label: '客户',
prop: 'customerName',
search: true,
searchLabel: '客户名称',
searchPlaceholder: '请选择或输入',
searchOrder: 21,
minWidth: 150,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '车牌号/船班号/船次号/班次号',
prop: 'vehicleNo',
search: true,
searchLabel: '车牌号/船班号/船次号/班次号',
searchOrder: 13,
minWidth: 210,
display: false,
},
{
label: '司机',
prop: 'driverName',
search: true,
searchLabel: '司机名称',
searchPlaceholder: '请选择或输入',
searchOrder: 14,
minWidth: 120,
display: false,
},
{
label: '联系方式',
prop: 'driverPhone',
formatter: row => getFirstValue(row, ['driverPhone', 'driverMobile', 'driverTel']),
minWidth: 140,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '运输方式',
prop: 'transportType',
type: 'select',
search: true,
searchOrder: 20,
span: 6,
order: 850,
...transportTypeDict,
minWidth: 130,
rules: selectRule('运输方式'),
},
{
label: '过程节点',
prop: 'currentProcessNode',
formatter: row => formatCurrentProcessNode(row),
minWidth: 140,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '承运类型',
prop: 'carrierType',
formatter: row => getFirstValue(row, ['carrierTypeName', 'carrierType']),
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '承运商',
prop: 'carrierName',
search: true,
searchLabel: '承运商名称',
searchPlaceholder: '请选择或输入',
searchOrder: 15,
minWidth: 150,
display: false,
},
{
label: '货物信息',
prop: 'goodsInfo',
formatter: row => formatGoodsInfo(row),
minWidth: 260,
overHidden: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '发货地址',
prop: 'departureAddress',
formslot: true,
search: true,
searchOrder: 17,
span: 24,
order: 790,
minWidth: 220,
rules: textRule('发货地址', 255, true),
},
{
label: '到货地址',
prop: 'arrivalAddress',
formslot: true,
search: true,
searchLabel: '收货地址',
searchOrder: 16,
span: 24,
order: 780,
minWidth: 220,
rules: textRule('收货地址', 255, true),
},
{
label: '发货联系人',
prop: 'departureContact',
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '收货联系人',
prop: 'arrivalContact',
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '单价',
prop: 'unitPrice',
formatter: row => formatUnitPrice(row),
minWidth: 140,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '运费',
prop: 'freight',
formatter: row => formatFreight(row),
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '其他费用合计',
prop: 'otherFeeTotal',
formatter: row => formatOtherFeeTotal(row),
minWidth: 140,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '运费合计',
prop: 'freightTotal',
formatter: row => formatFreightTotal(row),
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '客户合同',
prop: 'contractName',
formslot: true,
span: 6,
order: 880,
minWidth: 160,
rules: textRule('客户合同', 100, true),
},
{
label: '计划名称',
prop: 'planName',
formslot: true,
search: true,
searchPlaceholder: '请选择或输入',
searchOrder: 7,
span: 6,
order: 870,
minWidth: 150,
formatter: row => {
const value = row?.planName;
if (
value === undefined ||
value === null ||
value === '' ||
String(value) === '-1' ||
Number(value) === -1
) {
return '';
}
return value;
},
},
{
label: '货物类型',
prop: 'cargoType',
search: true,
searchPlaceholder: '请选择或输入',
searchOrder: 18,
formatter: row => formatGoodsField(row, ['cargoType', 'goodsType', 'typeName']),
minWidth: 130,
display: false,
rules: textRule('货物类型', 100, true),
},
{
label: '货物名称',
prop: 'cargoName',
search: true,
searchOrder: 19,
formatter: row => formatGoodsField(row, ['cargoName', 'goodsName', 'name']),
minWidth: 150,
display: false,
rules: textRule('货物名称', 100, true),
},
{
label: '实际发货时间',
prop: 'startDate',
sortable: true,
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 170,
addDisplay: false,
editDisplay: false,
},
{
label: '实际完成时间',
prop: 'endDate',
sortable: true,
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
minWidth: 170,
addDisplay: false,
editDisplay: false,
},
{
label: '原始单号',
prop: 'originalNo',
search: true,
searchOrder: 12,
span: 6,
order: 860,
minWidth: 140,
},
{
label: '运单批次号',
prop: 'batchNo',
search: true,
searchLabel: '运输批次',
searchOrder: 3,
minWidth: 140,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '关联单号',
prop: 'relationNo',
search: true,
searchOrder: 2,
span: 6,
order: 820,
minWidth: 140,
hide: false,
addDisplay: true,
editDisplay: true,
viewDisplay: true,
},
{
label: '预计发货日期',
prop: 'estimatedStartTime',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
formatter: row => getFirstValue(row, ['estimatedStartTime', 'planStartDate']),
minWidth: 170,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '预计完成日期',
prop: 'estimatedEndTime',
sortable: true,
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
formatter: row => getFirstValue(row, ['estimatedEndTime', 'planEndDate']),
minWidth: 170,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '备注',
prop: 'remark',
type: 'textarea',
minRows: 2,
span: 24,
order: 810,
minWidth: 180,
overHidden: true,
maxlength: 200,
showWordLimit: true,
rules: textRule('备注', 200),
},
{
label: '数据来源',
prop: 'dataSource',
type: 'select',
search: true,
searchOrder: 10,
dicData: dataSourceOptions,
minWidth: 120,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
...auditColumn('createUserName'),
},
{
...auditColumn('createTime'),
},
{
...auditColumn('updateTime'),
},
{
label: '状态',
prop: 'businessStatus',
type: 'select',
slot: true,
search: true,
searchLabel: '状态',
searchOrder: 11,
dicData: waybillStatusOptions,
minWidth: 82,
fixed: 'right',
addDisplay: false,
editDisplay: false,
},
{
label: '',
prop: 'shippingInfoTitle',
formslot: true,
span: 24,
order: 800,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'taskInfoTitle',
formslot: true,
span: 24,
order: 770,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'taskInfoForm',
formslot: true,
span: 24,
order: 760,
hide: true,
labelWidth: '0px',
className: 'waybill-manage-page__full-form-item',
},
{
label: '实际发货时间',
prop: 'startDateRange',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
search: true,
searchRange: true,
searchOrder: 9,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '实际完成时间',
prop: 'endDateRange',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
search: true,
searchRange: true,
searchOrder: 8,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
display: false,
},
{
label: '创建时间',
prop: 'createTimeRange',
type: 'datetime',
format: 'YYYY-MM-DD HH:mm:ss',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
search: true,
searchRange: true,
searchOrder: 4,
hide: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '货物信息',
prop: 'goodsJson',
type: 'textarea',
minRows: 2,
span: 24,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '承运信息',
prop: 'carrierJson',
type: 'textarea',
minRows: 2,
span: 24,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '过程配置',
prop: 'processJson',
type: 'textarea',
minRows: 2,
span: 24,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '运费信息',
prop: 'freightJson',
type: 'textarea',
minRows: 2,
span: 24,
hide: true,
display: false,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
},
{
label: '',
prop: 'attachmentTitle',
formslot: true,
span: 24,
order: 750,
hide: true,
labelWidth: 0,
},
{
label: '',
prop: 'attachmentsJson',
type: 'textarea',
formslot: true,
span: 24,
order: 740,
hide: true,
labelWidth: '0px',
className: 'waybill-manage-page__full-form-item',
},
{
label: '所属组织',
prop: 'deptName',
hide: true,
minWidth: 150,
addDisplay: false,
editDisplay: false,
},
{
label: '发货地',
prop: 'departureName',
hide: true,
display: false,
minWidth: 140,
rules: textRule('发货地', 100, true),
},
{
label: '收货地',
prop: 'arrivalName',
hide: true,
display: false,
minWidth: 140,
rules: textRule('收货地', 100, true),
},
{
label: '发货联系方式',
prop: 'departurePhone',
hide: true,
display: false,
rules: [phoneRule('发货联系方式'), ...textRule('发货联系方式', 50)],
},
{
label: '收货联系方式',
prop: 'arrivalPhone',
hide: true,
display: false,
rules: [phoneRule('收货联系方式'), ...textRule('收货联系方式', 50)],
},
{
label: '项目ID',
prop: 'projectId',
hide: true,
display: false,
},
{
label: '客户合同ID',
prop: 'contractId',
hide: true,
display: false,
},
{
label: '计划名称ID',
prop: 'planId',
hide: true,
display: false,
},
{
label: '任务录入模式',
prop: 'taskEntryMode',
hide: true,
display: false,
value: 'simple',
},
{
label: '任务备注',
prop: 'taskRemark',
hide: true,
display: false,
},
{
label: '任务信息',
prop: 'taskInfoJson',
hide: true,
display: false,
},
])
),
// label 固定宽度(容纳 6 汉字),覆盖 createCrudOption 默认 labelWidth:'auto'
labelWidth: 100,
dialogWidth: '96%',
dialogTop: '4vh',
menuWidth: 280,
};