Files
tms-erp-web/src/option/business/waybill-manage.js
T

1153 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', 'confirmReturn'],
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);
// 待回单确认由末位打卡产生,司机必然已接单,先于下面的接单校正返回
if (status === 'pending_return_confirm') return '待回单确认';
// 需司机接单且尚未接单 → 待执行(含库中仍为 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,
};