+
货物信息
导入货物
@@ -3712,7 +3974,9 @@
>
- 货物类型
+ 货物类型
- 货物名称
+ 货物名称
-
+
@@ -3762,29 +4033,69 @@
- 本次数量
+ 本次数量
- handleDispatchCargoQuantityInput(row, value)" />
+ handleDispatchCargoQuantityInput(row, value)"
+ />
- 数量单位
+ 数量单位
- visible && loadTaskQuantityUnitOptions()">
-
+ visible && loadTaskQuantityUnitOptions()"
+ >
+
-
-
-
-
-
-
+
+
+
+
+
+
- 新增
+ 新增
删除
@@ -3792,19 +4103,66 @@
费用信息
-
+
- handleDispatchCargoNumberInput(cargo, 'unitPrice', value)">
- visible && loadTaskFeeUnitOptions()">
+ handleDispatchCargoNumberInput(cargo, 'unitPrice', value)"
+ >
+ visible && loadTaskFeeUnitOptions()"
+ >
- {{ cargo.quantityUnit || '吨' }}
- {{ dispatchItemFreightCurrencyLabel }}
+ {{ cargo.quantityUnit || '吨' }}
+ {{ dispatchItemFreightCurrencyLabel }}
- handleDispatchNumberInput('otherFeeTotal', value)">{{ dispatchItemFreightCurrencyLabel }}
- {{ dispatchItemFreightCurrencyLabel }}
- visible && loadShippingTemplateCurrencyOptions()">
+ handleDispatchNumberInput('otherFeeTotal', value)"
+ >{{ dispatchItemFreightCurrencyLabel }}
+ {{ dispatchItemFreightCurrencyLabel }}
+ visible && loadShippingTemplateCurrencyOptions()"
+ >
@@ -3864,19 +4222,13 @@
-
+
-
+
@@ -4170,63 +4522,61 @@
附件
-
-
-
- 批量下载
-
-
-
+
+
-
-
-
-
-
- {{ attachmentName(row) }}
-
-
-
-
-
-
-
-
-
- {{ formatFileSize(row.size) }}
-
-
-
-
-
- 删除
-
-
-
+ 批量下载
+
+
+
+
+
+
+
+
+ {{ attachmentName(row) }}
+
+
+
+
+
+
+
+
+
+ {{ formatFileSize(row.size) }}
+
+
+
+
+
+ 删除
+
+
+
@@ -4235,7 +4585,15 @@
+
@@ -4891,7 +5249,7 @@
{{ transportMapStatus }}
行政区划:{{ transportMapSelected.regionName }}行政区划:{{ transportMapSelected.regionName }}
@@ -4952,7 +5310,20 @@
-
+
+
@@ -5006,6 +5377,14 @@
关闭
+
+ 确定
+
@@ -5149,17 +5528,34 @@ import { isMobile } from '@/utils/validate';
import { List, Location, Rank, Search } from '@element-plus/icons-vue';
import { ElImageViewer } from 'element-plus';
import { OpenFileViewer } from '@open-file-viewer/vue';
-import { fallbackPlugin, imagePlugin, officePlugin, pdfPlugin, textPlugin } from '@open-file-viewer/core';
+import {
+ fallbackPlugin,
+ imagePlugin,
+ officePlugin,
+ pdfPlugin,
+ textPlugin,
+} from '@open-file-viewer/core';
import '@open-file-viewer/core/style.css';
import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
+import { h, resolveComponent } from 'vue';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import WaybillImportDialog from './waybill-import-dialog.vue';
+import BillingPlanEditor from './billing-plan-editor.vue';
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
let amapLoader;
+const standaloneBusinessFormRoutes = {
+ '/business/waybill-manage': '/business/waybill-manage/form',
+ '/business/transport-plan': '/business/transport-plan/form',
+ '/business/shipping-template': '/business/shipping-template/form',
+};
+const standaloneBusinessFormPaths = [
+ ...Object.keys(standaloneBusinessFormRoutes),
+ ...Object.values(standaloneBusinessFormRoutes),
+];
const attachmentViewerPlugins = [
imagePlugin(),
@@ -5169,6 +5565,34 @@ const attachmentViewerPlugins = [
fallbackPlugin(),
];
+const PageAvueForm = {
+ inheritAttrs: false,
+ render() {
+ const attrs = { ...this.$attrs };
+ const rowSave = attrs.onRowSave;
+ const rowUpdate = attrs.onRowUpdate;
+ const boxType = attrs.option?.boxType;
+ delete attrs.onRowSave;
+ delete attrs.onRowUpdate;
+ attrs.onSubmit = (row, hide) => {
+ if (boxType === 'edit') {
+ rowUpdate?.(row, undefined, hide, undefined);
+ } else {
+ rowSave?.(row, hide, undefined);
+ }
+ };
+ const slots = Object.fromEntries(
+ Object.entries(this.$slots).map(([name, slot]) => [
+ name === 'menu-form' || name === 'menu-form-before' ? name : name.replace(/-form$/, ''),
+ slot,
+ ])
+ );
+ return h('div', { class: attrs.option?.dialogCustomClass || 'business-crud-form-page-dialog' }, [
+ h(resolveComponent('avue-form'), attrs, slots),
+ ]);
+ },
+};
+
const estimateMenuButtonCount = config => {
const rowActions = (config.actions || []).filter(action => action !== 'batchComplete');
return 3 + rowActions.length + (config.operations || []).length;
@@ -5249,6 +5673,12 @@ const defaultSettlementRule = () => ({
cycleDays: '',
});
+const defaultPaymentRatio = () => ({
+ paymentTerm: '',
+ ratioLimit: '',
+ remark: '',
+});
+
const defaultReconciliation = () => ({
skipReconciliation: 1,
reconciliationMode: '明细逐行核对',
@@ -5339,7 +5769,14 @@ const defaultDispatchRow = () => ({
const taskCarrierTypes = ['承运商', '自运', '网货平台'];
export default {
- components: { WaybillImportDialog, Rank, ElImageViewer, OpenFileViewer },
+ components: {
+ WaybillImportDialog,
+ BillingPlanEditor,
+ PageAvueForm,
+ Rank,
+ ElImageViewer,
+ OpenFileViewer,
+ },
name: 'BusinessCrudPage',
props: {
api: {
@@ -5367,6 +5804,14 @@ export default {
type: [String, Number],
default: null,
},
+ contractFormPage: {
+ type: Boolean,
+ default: false,
+ },
+ standaloneFormPage: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
@@ -5443,6 +5888,19 @@ export default {
option: (() => {
const opt = this.cloneOption(this.crudOption, estimateMenuButtonCount(this.config));
if (this.menuWidth != null) opt.menuWidth = this.menuWidth;
+ if (
+ (this.contractFormPage && this.$route.path === '/business/contract-manage/form') ||
+ (this.standaloneFormPage && standaloneBusinessFormPaths.includes(this.$route.path))
+ ) {
+ opt.dialogAppendToBody = false;
+ opt.dialogModal = false;
+ opt.dialogCustomClass =
+ this.contractFormPage && this.$route.path === '/business/contract-manage/form'
+ ? 'contract-manage-form-dialog'
+ : 'business-crud-form-page-dialog';
+ opt.dialogTop = '0';
+ opt.dialogWidth = '100%';
+ }
return opt;
})(),
selectedProjectId: '',
@@ -5572,10 +6030,14 @@ export default {
cargoImportRows: [],
billingPlanRows: [],
settlementRuleForm: defaultSettlementRule(),
+ preSettlementRuleForm: defaultSettlementRule(),
+ formalSettlementRuleForm: defaultSettlementRule(),
+ settlementConfigTab: 'pre',
settlementRuleErrors: {},
- reconciliationForm: defaultReconciliation(),
+ paymentRatioRows: [],
changeRecordRows: [],
billingPlanBox: false,
+ billingPlanViewOnly: false,
billingPlanMode: 'add',
billingPlanIndex: -1,
billingPlanForm: defaultBillingPlan(),
@@ -5661,6 +6123,7 @@ export default {
over90: 0,
expired: 0,
},
+ standaloneFormKey: '',
};
},
created() {
@@ -5690,6 +6153,7 @@ export default {
this.loadShippingTemplateCurrencyOptions();
}
this.consumeTemplateCreatePayload();
+ if (this.isStandaloneFormPage) this.$nextTick(() => this.initStandaloneFormPage());
},
computed: {
...mapGetters(['permission', 'userInfo']),
@@ -5701,6 +6165,47 @@ export default {
detailSections() {
return this.config.detailSections || [];
},
+ contractDetailSettlementRows() {
+ if (!this.isContractConfig) return [];
+ return [
+ { configName: '预结算配置', ...this.preSettlementRuleForm },
+ { configName: '正式结算配置', ...this.formalSettlementRuleForm },
+ ];
+ },
+ isContractConfig() {
+ return this.config.permission === 'contract_manage';
+ },
+ isShippingTemplatePage() {
+ return this.config.permission === 'shipping_template';
+ },
+ isContractFormPage() {
+ return this.contractFormPage && this.$route.path === '/business/contract-manage/form';
+ },
+ isStandaloneBusinessPage() {
+ return this.standaloneFormPage && standaloneBusinessFormPaths.includes(this.$route.path);
+ },
+ isStandaloneFormPage() {
+ return (
+ this.isContractFormPage ||
+ (this.isStandaloneBusinessPage && ['add', 'edit'].includes(this.$route.query.mode))
+ );
+ },
+ crudContainer() {
+ return this.isStandaloneFormPage ? 'PageAvueForm' : 'avue-crud';
+ },
+ pageFormOption() {
+ if (!this.isStandaloneFormPage) return this.option;
+ const isTransportPlanCreate =
+ this.config.enableTransportPlanCreateActions === true &&
+ this.$route.query.mode === 'add';
+ return {
+ ...this.option,
+ boxType: this.$route.query.mode === 'edit' ? 'edit' : 'add',
+ menuBtn: true,
+ submitBtn: !isTransportPlanCreate,
+ emptyBtn: false,
+ };
+ },
isWaybillDetailLayout() {
return this.config.permission === 'waybill_manage';
},
@@ -5763,14 +6268,16 @@ export default {
},
transportPlanDispatchSummary() {
const goodsRows = this.parseJsonArray(this.detailRow.goodsJson);
- const total = goodsRows.reduce(
- (sum, row) => sum + Number(row.quantity || row.cargoQuantity || row.goodsQuantity || 0),
- 0
- ) || Number(this.detailRow.totalQuantity || this.detailRow.quantity || 0);
- const assigned = this.transportPlanWaybillRows.reduce(
- (sum, row) => sum + Number(row.quantity || row.cargoQuantity || row.goodsQuantity || 0),
- 0
- ) || Number(this.detailRow.dispatchedQuantity || this.detailRow.dispatchQuantity || 0);
+ const total =
+ goodsRows.reduce(
+ (sum, row) => sum + Number(row.quantity || row.cargoQuantity || row.goodsQuantity || 0),
+ 0
+ ) || Number(this.detailRow.totalQuantity || this.detailRow.quantity || 0);
+ const assigned =
+ this.transportPlanWaybillRows.reduce(
+ (sum, row) => sum + Number(row.quantity || row.cargoQuantity || row.goodsQuantity || 0),
+ 0
+ ) || Number(this.detailRow.dispatchedQuantity || this.detailRow.dispatchQuantity || 0);
return { total, assigned, remaining: Math.max(total - assigned, 0) };
},
isTemplateCreate() {
@@ -5894,10 +6401,10 @@ export default {
this.getDispatchQuantityUnit(row),
'total',
row.quantity ||
- row.cargoQuantity ||
- row.goodsQuantity ||
- row.totalQuantity ||
- row.totalCargoQuantity
+ row.cargoQuantity ||
+ row.goodsQuantity ||
+ row.totalQuantity ||
+ row.totalCargoQuantity
);
});
if (!this.dispatchRows.length) {
@@ -6057,7 +6564,11 @@ export default {
(sum, cargo) => sum + Number(this.dispatchCargoFreightAmount(cargo) || 0),
0
);
- return total ? (Number.isInteger(total) ? String(total) : String(Number(total.toFixed(2)))) : '';
+ return total
+ ? Number.isInteger(total)
+ ? String(total)
+ : String(Number(total.toFixed(2)))
+ : '';
},
dispatchItemFreightCurrencyLabel() {
const value = this.dispatchItemForm.freightCurrency || 'CNY';
@@ -6284,6 +6795,27 @@ export default {
},
},
watch: {
+ $route(to, from) {
+ if (!this.isStandaloneFormPage) return;
+ if (
+ to.query.mode !== from?.query?.mode ||
+ String(to.query.id || '') !== String(from?.query?.id || '')
+ ) {
+ this.$nextTick(() => this.initStandaloneFormPage());
+ }
+ },
+ settlementConfigTab(tab, oldTab) {
+ if (!this.isContractConfig || tab === oldTab) return;
+ if (oldTab === 'formal') {
+ this.formalSettlementRuleForm = { ...this.settlementRuleForm };
+ } else {
+ this.preSettlementRuleForm = { ...this.settlementRuleForm };
+ }
+ this.settlementRuleForm = {
+ ...(tab === 'formal' ? this.formalSettlementRuleForm : this.preSettlementRuleForm),
+ };
+ this.settlementRuleErrors = {};
+ },
detailId: {
immediate: true,
handler(id) {
@@ -6303,6 +6835,40 @@ export default {
},
},
methods: {
+ initStandaloneFormPage() {
+ if (!this.isStandaloneFormPage) return;
+ const mode = this.$route.query.mode === 'edit' ? 'edit' : 'add';
+ const id = this.$route.query.id || '';
+ const key = `${mode}:${id}`;
+ if (this.standaloneFormKey === key) return;
+ this.standaloneFormKey = key;
+ if (mode === 'edit') this.form = { id };
+ this.beforeOpen(() => {}, mode);
+ },
+ openContractFormPage(mode, row = {}) {
+ if (this.isStandaloneBusinessPage) {
+ this.$router.push({
+ path: standaloneBusinessFormRoutes[this.$route.path] || this.$route.path,
+ query: {
+ mode,
+ ...(mode === 'edit' && row.id ? { id: row.id } : {}),
+ name: `${mode === 'edit' ? '编辑' : '新增'}${this.config.title || ''}`,
+ },
+ });
+ return;
+ }
+ if (!this.contractFormPage) {
+ this.$refs.crud?.[mode === 'edit' ? 'rowEdit' : 'rowAdd'](row);
+ return;
+ }
+ this.$router.push({
+ path: '/business/contract-manage/form',
+ query:
+ mode === 'edit'
+ ? { mode, id: row.id, name: '编辑合同管理' }
+ : { mode, name: '新增合同管理' },
+ });
+ },
cloneOption(option, menuButtonCount) {
const nextOption = {
...option,
@@ -6313,7 +6879,9 @@ export default {
const orderMap = new Map(tableOrder.map((prop, index) => [prop, index]));
nextOption.column.sort((left, right) => {
const leftOrder = orderMap.has(left.prop) ? orderMap.get(left.prop) : tableOrder.length;
- const rightOrder = orderMap.has(right.prop) ? orderMap.get(right.prop) : tableOrder.length;
+ const rightOrder = orderMap.has(right.prop)
+ ? orderMap.get(right.prop)
+ : tableOrder.length;
return leftOrder - rightOrder;
});
nextOption.column.forEach(column => {
@@ -6326,7 +6894,8 @@ export default {
const goodsRows = this.parseJsonArray(row.goodsJson);
if (!goodsRows.length) return String(row.goodsInfo || row.cargoInfo || '');
const groups = goodsRows.reduce((result, item = {}) => {
- const unit = item.quantityUnit || item.goodsQuantityUnit || item.cargoUnit || item.unit || '';
+ const unit =
+ item.quantityUnit || item.goodsQuantityUnit || item.cargoUnit || item.unit || '';
const key = unit || '__empty__';
if (!result[key]) {
result[key] = {
@@ -6361,7 +6930,10 @@ export default {
const text = String(value || '').trim();
if (!text) return '-';
const cityIndex = text.indexOf('市');
- const provinceIndex = Math.max(text.lastIndexOf('省', cityIndex), text.lastIndexOf('自治区', cityIndex));
+ const provinceIndex = Math.max(
+ text.lastIndexOf('省', cityIndex),
+ text.lastIndexOf('自治区', cityIndex)
+ );
const cityStart = provinceIndex > -1 ? provinceIndex + 1 : 0;
const districtStart = cityIndex > -1 ? cityIndex + 1 : cityStart;
const districtMatch = text
@@ -6410,7 +6982,8 @@ export default {
this.hasPermission(`${this.config.permission}_edit`) &&
!this.readonlyScope &&
(!row.readonly || this.isReadonlyEditAllowed(row)) &&
- this.inStatus(row, this.config.editStatus)
+ this.inStatus(row, this.config.editStatus) &&
+ (typeof this.config.canEdit !== 'function' || this.config.canEdit(row))
);
},
canDelete(row) {
@@ -6482,7 +7055,8 @@ export default {
this.hasPermission(`${this.config.permission}_reassign`) &&
!this.readonlyScope &&
!row.readonly &&
- this.statusValue(row) === 'pending'
+ this.statusValue(row) === 'pending' &&
+ (typeof this.config.canReassign !== 'function' || this.config.canReassign(row))
);
},
customOperations(row) {
@@ -6522,7 +7096,7 @@ export default {
}
if (action.action === 'edit' || action.action === 'attachmentUpload') {
this.attachmentUploadMode = action.action === 'attachmentUpload';
- this.$refs.crud.rowEdit(row, index);
+ this.openContractFormPage('edit', row);
return;
}
if (action.action === 'delete') {
@@ -6641,9 +7215,15 @@ export default {
const status = this.statusValue(row);
return status !== 'draft';
},
+ isContractBillingDetailSection(section = {}) {
+ return this.isContractConfig && section.title === '计费与结算';
+ },
formatDetailValue(row, prop) {
if (!row) return '-';
if (prop === 'businessStatus') return this.displayStatus(row, prop);
+ if (prop === 'feeGenerationMode') {
+ return row[prop] === 'manual' ? '手动生成' : '系统生成';
+ }
const column = this.findColumn(this.option.column, prop);
if (column?.formatter) return column.formatter(row, {}, row[prop]);
if (column?.dicData) {
@@ -6651,6 +7231,15 @@ export default {
if (item) return item.label;
}
const value = row[prop];
+ if (value && typeof value === 'object') return JSON.stringify(value);
+ if (typeof value === 'string' && /^[\[{]/.test(value.trim())) {
+ try {
+ const parsed = JSON.parse(value);
+ return typeof parsed === 'object' ? JSON.stringify(parsed) : parsed;
+ } catch (error) {
+ // 非 JSON 文本按原值展示。
+ }
+ }
return value === undefined || value === null || value === '' ? '-' : value;
},
waybillTransportMode(row = {}) {
@@ -6743,7 +7332,8 @@ export default {
return {
...row,
_detailIndex: index,
- vehicleNo: row.vehicleNo || row.vehicleNumber || row.flightNo || row.shipNo || row.trainNo || '',
+ vehicleNo:
+ row.vehicleNo || row.vehicleNumber || row.flightNo || row.shipNo || row.trainNo || '',
driverName: row.driverName || row.driver || '',
carrierName: row.carrierName || row.carrier || '',
transportType: row.transportTypeName || row.transportType || '',
@@ -6776,8 +7366,7 @@ export default {
},
transportPlanWaybillIndex(index) {
return (
- (this.transportPlanWaybillPage.currentPage - 1) *
- this.transportPlanWaybillPage.pageSize +
+ (this.transportPlanWaybillPage.currentPage - 1) * this.transportPlanWaybillPage.pageSize +
index +
1
);
@@ -6809,13 +7398,15 @@ export default {
});
},
ensureTransportPlanDetailTransportTypeName(detail = {}) {
- if (!this.isTransportPlanPage) {
+ if (!this.isTransportPlanPage && !this.isWaybillDetailLayout) {
return;
}
- const transportTypes = [
- detail.transportType,
- ...this.transportPlanWaybillRows.map(row => row.transportType),
- ]
+ const transportTypes = (this.isTransportPlanPage
+ ? [
+ detail.transportType,
+ ...this.transportPlanWaybillRows.map(row => row.transportType),
+ ]
+ : [this.waybillTransportMode(detail)])
.map(value => String(value || '').trim())
.filter(Boolean);
if (transportTypes.some(value => !/[\u4e00-\u9fff]/.test(value))) {
@@ -6826,7 +7417,7 @@ export default {
const transportType = String(value || '').trim();
if (!transportType) return '-';
const item = this.transportPlanDetailTransportTypeOptions.find(
- option => String(option.value) === transportType
+ option => String(option.value || '').toLowerCase() === transportType.toLowerCase()
);
return item?.label || transportType;
},
@@ -6922,7 +7513,11 @@ export default {
.catch(() => []);
},
loadWaybillVoucherImages() {
- if (!this.detailRow.id || this.waybillVoucherImagesLoading || this.waybillVoucherImagesLoaded) {
+ if (
+ !this.detailRow.id ||
+ this.waybillVoucherImagesLoading ||
+ this.waybillVoucherImagesLoaded
+ ) {
return;
}
this.waybillVoucherImagesLoading = true;
@@ -6936,7 +7531,9 @@ export default {
});
},
previewWaybillVoucherImage(index) {
- this.attachmentImagePreviewUrls = this.waybillVoucherImages.map(image => image.url).filter(Boolean);
+ this.attachmentImagePreviewUrls = this.waybillVoucherImages
+ .map(image => image.url)
+ .filter(Boolean);
this.attachmentImagePreviewIndex = index;
this.attachmentImagePreviewVisible = this.attachmentImagePreviewUrls.length > 0;
},
@@ -6965,8 +7562,8 @@ export default {
const taskInfo = this.parseJsonObject(this.detailRow.taskInfoJson);
this.waybillRouteChangeRecords = Array.isArray(taskInfo.routeChangeRecords)
? [...taskInfo.routeChangeRecords].sort((a, b) =>
- String(b.changeTime).localeCompare(String(a.changeTime))
- )
+ String(b.changeTime).localeCompare(String(a.changeTime))
+ )
: [];
},
openWaybillRouteChangeDialog() {
@@ -7037,7 +7634,9 @@ export default {
const target = this.waybillCommonAddressTarget;
if (!target) return;
target.row[`${target.field}Address`] =
- [address.regionName, address.detailAddress || address.addressName].filter(Boolean).join('') ||
+ [address.regionName, address.detailAddress || address.addressName]
+ .filter(Boolean)
+ .join('') ||
address.addressName ||
'';
this.updateWaybillRouteChangeNodes();
@@ -7061,8 +7660,8 @@ export default {
const content = changed
? `${row.waybillNo || '运单'}:发货地 ${row.originalDepartureAddress || '-'} → ${
- row.departureAddress || '-'
- };到货地 ${row.originalArrivalAddress || '-'} → ${row.arrivalAddress || '-'}`
+ row.departureAddress || '-'
+ };到货地 ${row.originalArrivalAddress || '-'} → ${row.arrivalAddress || '-'}`
: '调整运输路线顺序';
const records = [
{
@@ -7236,22 +7835,55 @@ export default {
[field]: '',
};
},
- validateSettlementRule() {
- const rule = this.normalizeSettlementRule(this.settlementRuleForm);
+ syncSettlementConfig() {
+ if (!this.isContractConfig) return;
+ if (this.settlementConfigTab === 'formal') {
+ this.formalSettlementRuleForm = { ...this.settlementRuleForm };
+ } else {
+ this.preSettlementRuleForm = { ...this.settlementRuleForm };
+ }
+ },
+ switchSettlementConfig(tab) {
+ this.syncSettlementConfig();
+ this.settlementConfigTab = tab;
+ this.settlementRuleForm = {
+ ...(tab === 'formal' ? this.formalSettlementRuleForm : this.preSettlementRuleForm),
+ };
+ this.settlementRuleErrors = {};
+ },
+ addPaymentRatioRow() {
+ this.paymentRatioRows.push({
+ ...defaultPaymentRatio(),
+ paymentTerm: `第${this.paymentRatioRows.length + 1}笔`,
+ });
+ },
+ validatePaymentRatios() {
+ const total = this.paymentRatioRows.reduce(
+ (sum, row) => sum + Number(row.ratioLimit || 0),
+ 0
+ );
+ if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) {
+ this.$message.warning('付款比例上限合计必须等于100%');
+ return false;
+ }
+ return true;
+ },
+ validateSettlementRule(source = this.settlementRuleForm, label = '') {
+ const rule = this.normalizeSettlementRule(source);
this.settlementRuleErrors = {};
if (this.isBillingFieldEmpty(rule.billStartDate)) {
this.settlementRuleErrors = { billStartDate: '请选择账单起始日期' };
- this.$message.warning('请选择账单起始日期');
+ this.$message.warning(`${label}${label ? ':' : ''}请选择账单起始日期`);
return false;
}
if (this.isBillingFieldEmpty(rule.settlementType)) {
this.settlementRuleErrors = { settlementType: '请选择结算类型' };
- this.$message.warning('请选择结算类型');
+ this.$message.warning(`${label}${label ? ':' : ''}请选择结算类型`);
return false;
}
if (this.isMonthlySettlement(rule) && this.isBillingFieldEmpty(rule.billCycleType)) {
this.settlementRuleErrors = { billCycleType: '请选择账单周期类型' };
- this.$message.warning('请选择账单周期类型');
+ this.$message.warning(`${label}${label ? ':' : ''}请选择账单周期类型`);
return false;
}
if (this.isFixedBillCutoffSettlement(rule)) {
@@ -7315,13 +7947,40 @@ export default {
submitRow.billingPlanJson = JSON.stringify(this.billingPlanRows);
}
if (this.config.enableSettlementRule) {
- if (!skipValidation && this.settlementRuleEnabled && !this.validateSettlementRule()) {
+ if (this.isContractConfig) {
+ this.syncSettlementConfig();
+ if (
+ !skipValidation &&
+ ((this.preSettlementRuleForm.autoGenerate === 1 &&
+ !this.validateSettlementRule(this.preSettlementRuleForm, '预结算配置')) ||
+ (this.formalSettlementRuleForm.autoGenerate === 1 &&
+ !this.validateSettlementRule(this.formalSettlementRuleForm, '正式结算配置')))
+ ) {
+ return false;
+ }
+ submitRow.settlementRuleJson = JSON.stringify({
+ preSettlementConfig: this.normalizeSettlementRule(this.preSettlementRuleForm),
+ formalSettlementConfig: this.normalizeSettlementRule(this.formalSettlementRuleForm),
+ });
+ submitRow.preSettlementConfigJson = JSON.stringify(
+ this.normalizeSettlementRule(this.preSettlementRuleForm)
+ );
+ submitRow.formalSettlementConfigJson = JSON.stringify(
+ this.normalizeSettlementRule(this.formalSettlementRuleForm)
+ );
+ } else if (
+ !skipValidation &&
+ this.settlementRuleEnabled &&
+ !this.validateSettlementRule()
+ ) {
return false;
+ } else {
+ submitRow.settlementRuleJson = JSON.stringify(this.normalizeSettlementRule());
}
- submitRow.settlementRuleJson = JSON.stringify(this.normalizeSettlementRule());
}
- if (this.config.enableReconciliation) {
- submitRow.reconciliationJson = JSON.stringify(this.reconciliationForm);
+ if (this.isContractConfig) {
+ if (!skipValidation && !this.validatePaymentRatios()) return false;
+ submitRow.paymentRatioJson = JSON.stringify(this.paymentRatioRows);
}
if (this.config.enableChangeRecord) {
submitRow.changeRecordJson = JSON.stringify(this.changeRecordRows);
@@ -7339,7 +7998,7 @@ export default {
delete submitRow.contractFileTitle;
delete submitRow.billingInfoTitle;
delete submitRow.settlementRuleTitle;
- delete submitRow.reconciliationTitle;
+ delete submitRow.paymentRatioTitle;
delete submitRow.attachmentTitle;
delete submitRow.changeRecordTitle;
delete submitRow.contractPeriod;
@@ -7351,9 +8010,7 @@ export default {
return submitRow;
},
validateMobileFields(fields = []) {
- const invalidField = fields.find(
- ([value]) => String(value || '').trim() && !isMobile(value)
- );
+ const invalidField = fields.find(([value]) => String(value || '').trim() && !isMobile(value));
if (!invalidField) return true;
this.$message.warning(`${invalidField[1]}格式不正确`);
return false;
@@ -7397,14 +8054,16 @@ export default {
currencyName(value) {
const text = String(value || '');
if (text.includes(' - ')) return text.slice(text.indexOf(' - ') + 3);
- return {
- CNY: '人民币',
- RMB: '人民币',
- USD: '美元',
- EUR: '欧元',
- JPY: '日元',
- GBP: '英镑',
- }[text.toUpperCase()] || text;
+ return (
+ {
+ CNY: '人民币',
+ RMB: '人民币',
+ USD: '美元',
+ EUR: '欧元',
+ JPY: '日元',
+ GBP: '英镑',
+ }[text.toUpperCase()] || text
+ );
},
currencyRemark(value) {
const option = this.shippingTemplateCurrencyOptions.find(
@@ -7681,6 +8340,7 @@ export default {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
+ if (this.isStandaloneBusinessPage) this.closeCrudDialog();
},
error => {
window.console.log(error);
@@ -7704,6 +8364,7 @@ export default {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
+ if (this.isStandaloneBusinessPage) this.closeCrudDialog();
},
error => {
this.attachmentUploadMode = false;
@@ -7848,6 +8509,19 @@ export default {
});
},
closeCrudDialog() {
+ if (this.isStandaloneBusinessPage) {
+ this.$router.$avueRouter?.closeTag?.();
+ const listPath =
+ Object.entries(standaloneBusinessFormRoutes).find(
+ ([, formPath]) => formPath === this.$route.path
+ )?.[0] || this.$route.path;
+ this.$router.push({ path: listPath, query: {} });
+ return;
+ }
+ if (this.isContractFormPage) {
+ this.$router.push('/business/contract-manage');
+ return;
+ }
const crud = this.$refs.crud;
if (crud && typeof crud.closeDialog === 'function') {
crud.closeDialog();
@@ -7927,7 +8601,11 @@ export default {
this.shippingTemplateFreight = defaultShippingTemplateFreight();
this.billingPlanRows = [];
this.settlementRuleForm = defaultSettlementRule();
- this.reconciliationForm = defaultReconciliation();
+ this.preSettlementRuleForm = defaultSettlementRule();
+ this.formalSettlementRuleForm = defaultSettlementRule();
+ this.settlementConfigTab = 'pre';
+ this.paymentRatioRows = [];
+ this.form.feeGenerationMode = this.form.feeGenerationMode || 'system';
this.changeRecordRows = [];
this.applyCurrentUserHandler();
this.initTaskInfoForm();
@@ -7974,14 +8652,33 @@ export default {
this.selectedContractFileRows = [];
this.initTransportPlanFormRows();
this.billingPlanRows = this.parseJsonArray(this.form.billingPlanJson);
- this.settlementRuleForm = this.normalizeSettlementRule({
- ...defaultSettlementRule(),
- ...this.parseJsonObject(this.form.settlementRuleJson),
- });
- this.reconciliationForm = {
- ...defaultReconciliation(),
- ...this.parseJsonObject(this.form.reconciliationJson),
- };
+ const settlementPayload = this.parseJsonObject(this.form.settlementRuleJson);
+ const legacySettlementRule = Object.keys(settlementPayload).some(
+ key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)
+ )
+ ? settlementPayload
+ : {};
+ this.preSettlementRuleForm = this.normalizeSettlementRule(
+ settlementPayload.preSettlementConfig ||
+ (Object.keys(this.parseJsonObject(this.form.preSettlementConfigJson)).length
+ ? this.parseJsonObject(this.form.preSettlementConfigJson)
+ : legacySettlementRule)
+ );
+ this.formalSettlementRuleForm = this.normalizeSettlementRule(
+ settlementPayload.formalSettlementConfig ||
+ (Object.keys(this.parseJsonObject(this.form.formalSettlementConfigJson)).length
+ ? this.parseJsonObject(this.form.formalSettlementConfigJson)
+ : legacySettlementRule)
+ );
+ this.settlementConfigTab = 'pre';
+ this.settlementRuleForm = this.preSettlementRuleForm;
+ this.paymentRatioRows = this.parseJsonArray(this.form.paymentRatioJson).map(row => ({
+ ...defaultPaymentRatio(),
+ ...row,
+ }));
+ this.form.feeGenerationMode =
+ this.form.feeGenerationMode ||
+ (Number(this.form.billingEnabled) === 0 ? 'manual' : 'system');
this.changeRecordRows = this.parseJsonArray(this.form.changeRecordJson);
this.applyCurrentUserHandler();
this.initTaskInfoForm();
@@ -8033,13 +8730,11 @@ export default {
return row.quantityUnit || row.goodsQuantityUnit || row.unit || '吨';
},
getDispatchVehicleIdentifier(row = {}) {
- return [
- row.vehicleNo,
- row.vehicleNumber,
- row.flightNo,
- row.shipNo,
- row.trainNo,
- ].find(value => String(value ?? '').trim()) || '';
+ return (
+ [row.vehicleNo, row.vehicleNumber, row.flightNo, row.shipNo, row.trainNo].find(value =>
+ String(value ?? '').trim()
+ ) || ''
+ );
},
hasDispatchVehicleIdentifier(row = {}) {
return Boolean(this.getDispatchVehicleIdentifier(row));
@@ -8429,7 +9124,10 @@ export default {
}
},
handleTaskEntryModeChange(value) {
- if (value === 'simple' && this.hasMultipleConfiguredGoods(this.form, this.transportCargoRows)) {
+ if (
+ value === 'simple' &&
+ this.hasMultipleConfiguredGoods(this.form, this.transportCargoRows)
+ ) {
this.form.taskEntryMode = 'full';
this.$message.warning('当前配置了多条货物信息,不能切换为精简录入');
return;
@@ -8965,21 +9663,21 @@ export default {
const goodsRows = this.isTaskFullMode
? this.transportCargoRows.map(item => this.normalizeTransportCargoRow(item))
: [
- {
- cargoType: row.cargoType,
- cargoTypeCode: row.cargoTypeCode,
- cargoTypePath: row.cargoTypePath,
- cargoName: row.cargoName,
- specification: row.specification,
- model: row.model,
- quantity: row.quantity,
- quantityUnit: row.quantityUnit,
- mileage: row.mileage,
- unitPrice: row.unitPrice,
- priceUnit: row.priceUnit,
- remark: row.taskRemark,
- },
- ];
+ {
+ cargoType: row.cargoType,
+ cargoTypeCode: row.cargoTypeCode,
+ cargoTypePath: row.cargoTypePath,
+ cargoName: row.cargoName,
+ specification: row.specification,
+ model: row.model,
+ quantity: row.quantity,
+ quantityUnit: row.quantityUnit,
+ mileage: row.mileage,
+ unitPrice: row.unitPrice,
+ priceUnit: row.priceUnit,
+ remark: row.taskRemark,
+ },
+ ];
if (this.isTaskFullMode) {
const firstCargo = goodsRows[0] || {};
taskInfo.unitPrice = firstCargo.unitPrice || '';
@@ -9028,9 +9726,7 @@ export default {
initTransportPlanFormRows() {
if (!this.config.enableTransportPlanForm) return;
const goodsRows = this.parseJsonArray(this.form.goodsJson);
- this.transportCargoRows = goodsRows.map(row =>
- this.normalizeTransportCargoRow(row)
- );
+ this.transportCargoRows = goodsRows.map(row => this.normalizeTransportCargoRow(row));
if (!this.transportCargoRows.length) {
this.transportCargoRows.push(this.normalizeTransportCargoRow());
}
@@ -9824,6 +10520,7 @@ export default {
this.commonCargoBox = true;
},
loadCommonCargoList() {
+ this.commonCargoSelected = [];
this.commonCargoLoading = true;
getCommonCargoList(this.commonCargoPage.currentPage, this.commonCargoPage.pageSize, {
...this.buildCommonCargoQueryParams(),
@@ -9866,6 +10563,9 @@ export default {
this.commonCargoPage.currentPage = currentPage;
this.loadCommonCargoList();
},
+ handleCommonCargoSelectionChange(rows) {
+ this.commonCargoSelected = rows || [];
+ },
handleCommonCargoTypeChange(value) {
const path = this.normalizeBillingCargoTypePath(value);
const labels = this.getBillingCargoTypePathLabels(path);
@@ -9902,6 +10602,15 @@ export default {
}
this.commonCargoBox = false;
},
+ async confirmCommonCargoSelection() {
+ if (!this.commonCargoSelected.length) return;
+ await this.ensureBillingCargoTypeOptions();
+ this.commonCargoSelected.forEach(row => {
+ this.addTransportCargoRow(-1, this.mapCommonCargoRow(row));
+ });
+ this.$message.success(`成功选择${this.commonCargoSelected.length}条常用货物`);
+ this.commonCargoBox = false;
+ },
mapCommonCargoRow(row = {}) {
const cargoTypePath = this.resolveCommonCargoTypePath(row);
const cargoType = this.findBillingCargoTypeByPath(cargoTypePath);
@@ -10146,7 +10855,10 @@ export default {
this.attachmentImagePreviewUrls = (rows || [])
.filter(item => this.isAttachmentImage(item) && this.attachmentUrl(item))
.map(item => this.attachmentUrl(item));
- this.attachmentImagePreviewIndex = Math.max(this.attachmentImagePreviewUrls.indexOf(url), 0);
+ this.attachmentImagePreviewIndex = Math.max(
+ this.attachmentImagePreviewUrls.indexOf(url),
+ 0
+ );
this.attachmentImagePreviewVisible = true;
return;
}
@@ -10354,8 +11066,8 @@ export default {
const children =
level === 1
? (cargoType.children || [])
- .map(item => this.normalizeBillingCargoTypeNode(item, level + 1, path))
- .filter(Boolean)
+ .map(item => this.normalizeBillingCargoTypeNode(item, level + 1, path))
+ .filter(Boolean)
: [];
return {
...cargoType,
@@ -10422,8 +11134,8 @@ export default {
const children =
level === 1
? (region.children || [])
- .map(item => this.normalizeBillingMatchRegionNode(item, level + 1))
- .filter(Boolean)
+ .map(item => this.normalizeBillingMatchRegionNode(item, level + 1))
+ .filter(Boolean)
: [];
return {
...region,
@@ -10664,6 +11376,7 @@ export default {
this.loadBillingFeeItemOptions(row.feeType);
},
openBillingPlan(row, index = -1) {
+ this.billingPlanViewOnly = false;
this.billingPlanMode = index > -1 ? 'edit' : 'add';
this.billingPlanIndex = index;
const plan = row ? this.cloneData(row) : defaultBillingPlan();
@@ -10682,6 +11395,10 @@ export default {
});
this.$nextTick(() => this.$refs.billingPlanFormRef?.clearValidate?.());
},
+ openBillingPlanDetail(row, index) {
+ this.openBillingPlan(row, index);
+ this.billingPlanViewOnly = true;
+ },
submitBillingPlan() {
this.$refs.billingPlanFormRef?.validate(valid => {
if (!valid) return;
@@ -10716,6 +11433,23 @@ export default {
this.billingPlanBox = false;
});
},
+ handleSharedBillingPlanSave(plan, index) {
+ const nextPlan = this.cloneData(plan);
+ if (!this.billingPlanRows.length && index === -1) {
+ nextPlan.defaultPlan = true;
+ }
+ if (nextPlan.defaultPlan) {
+ this.billingPlanRows.forEach(item => {
+ item.defaultPlan = false;
+ });
+ }
+ if (index > -1) {
+ this.billingPlanRows.splice(index, 1, nextPlan);
+ } else {
+ this.billingPlanRows.push(nextPlan);
+ }
+ this.syncBillingPlanJson();
+ },
validateBillingRules() {
const groups = {};
const requiredFields = [
@@ -11454,6 +12188,10 @@ export default {
});
},
handleCustomOperation(operation, row) {
+ if (operation.action === 'startChange' && this.config.permission === 'contract_manage') {
+ this.$router.push({ path: '/business/contract-manage/change', query: { id: row.id } });
+ return;
+ }
if (operation.action === 'createFromTemplate') {
this.api.getDetail(row.id).then(res => {
const template = res.data?.data || row;
@@ -11567,6 +12305,9 @@ export default {
);
return item?.label || value || '';
},
+ formatDispatchDriver(row = {}) {
+ return [row.driverName, row.driverPhone].filter(Boolean).join(' / ') || '-';
+ },
resetDispatchDialog() {
this.dispatchRow = {};
this.dispatchRows = [];
@@ -11633,8 +12374,7 @@ export default {
);
if (totalQuantity <= 0) return goods;
const remainingQuantity = Math.max(
- totalQuantity -
- (assignedQuantities.get(this.getDispatchCargoIdentity(goods)) || 0),
+ totalQuantity - (assignedQuantities.get(this.getDispatchCargoIdentity(goods)) || 0),
0
);
if (!remainingQuantity) return null;
@@ -11675,9 +12415,7 @@ export default {
);
const key = this.getDispatchCargoIdentity(goods);
const remainingQuantity = Math.max(
- totalQuantity -
- (assignedQuantities.get(key) || 0) -
- (pendingQuantities.get(key) || 0),
+ totalQuantity - (assignedQuantities.get(key) || 0) - (pendingQuantities.get(key) || 0),
0
);
if (!remainingQuantity) return null;
@@ -11806,9 +12544,11 @@ export default {
item.goodsQuantityUnit ||
item.unit ||
'吨',
- specification: item.specification || item.spec || itemGoods.specification || itemGoods.spec || '',
+ specification:
+ item.specification || item.spec || itemGoods.specification || itemGoods.spec || '',
model: item.model || itemGoods.model || '',
- packageType: item.packageType || item.package || itemGoods.packageType || itemGoods.package || '',
+ packageType:
+ item.packageType || item.package || itemGoods.packageType || itemGoods.package || '',
estimatedStartTime: item.estimatedStartTime || plan.planStartDate || '',
estimatedEndTime: item.estimatedEndTime || plan.planEndDate || '',
departureAddress: item.departureAddress || plan.departureAddress || '',
@@ -11827,7 +12567,11 @@ export default {
item.createUserName ||
'',
dispatchTime:
- item.dispatchTime || plan.dispatchTime || waybillFallback.createTime || item.createTime || '',
+ item.dispatchTime ||
+ plan.dispatchTime ||
+ waybillFallback.createTime ||
+ item.createTime ||
+ '',
goodsJson: item.goodsJson || '',
attachmentsJson: item.attachmentsJson || '',
remark: item.remark || item.taskRemark || plan.remark || '',
@@ -11920,7 +12664,11 @@ export default {
formatDispatchCargoInfo(plan = {}, item = {}) {
const goodsRows = this.dispatchGoodsRows(plan.goodsJson);
const itemGoodsRows = this.dispatchGoodsRows(item.goodsJson);
- const sourceRows = goodsRows.length ? goodsRows : itemGoodsRows.length ? itemGoodsRows : [item];
+ const sourceRows = goodsRows.length
+ ? goodsRows
+ : itemGoodsRows.length
+ ? itemGoodsRows
+ : [item];
const groups = sourceRows.reduce((result, goods = {}) => {
const cargoType =
goods.secondCargoTypeName ||
@@ -11966,8 +12714,8 @@ export default {
const sourceRows = this.dispatchPlanGoodsRows.length
? this.dispatchPlanGoodsRows
: this.dispatchRow.cargoName || this.dispatchRow.cargoType
- ? [this.dispatchRow]
- : [];
+ ? [this.dispatchRow]
+ : [];
return sourceRows
.map((item, index) => {
const cargoTypePath = this.normalizeBillingCargoTypePath(item.cargoTypePath);
@@ -12128,13 +12876,11 @@ export default {
const unscheduledGoodsRows = this.getDispatchUnscheduledGoodsRows();
this.dispatchItemForm.taskEntryMode = 'full';
this.dispatchItemForm.quantity = '';
- this.dispatchItemCargoRows = (
- unscheduledGoodsRows.length
- ? unscheduledGoodsRows
- : this.dispatchPlanGoodsRows.map(goods =>
- this.normalizeTransportCargoRow({ ...goods, quantity: '' })
- )
- );
+ this.dispatchItemCargoRows = unscheduledGoodsRows.length
+ ? unscheduledGoodsRows
+ : this.dispatchPlanGoodsRows.map(goods =>
+ this.normalizeTransportCargoRow({ ...goods, quantity: '' })
+ );
}
if (!this.dispatchItemCargoRows.length) {
this.dispatchItemCargoRows = [this.normalizeTransportCargoRow()];
@@ -12296,12 +13042,16 @@ export default {
if (!editingRow || !this.hasDispatchVehicleIdentifier(editingRow)) return remaining;
const editingGoodsRows = this.dispatchGoodsRows(editingRow.goodsJson);
const goodsRows = editingGoodsRows.length ? editingGoodsRows : [editingRow];
- return remaining + goodsRows.reduce((total, goods) => {
- if (this.getDispatchQuantityUnit(goods) !== unit) return total;
- return total + this.parseDispatchQuantity(
- goods.quantity || goods.cargoQuantity || goods.goodsQuantity
- );
- }, 0);
+ return (
+ remaining +
+ goodsRows.reduce((total, goods) => {
+ if (this.getDispatchQuantityUnit(goods) !== unit) return total;
+ return (
+ total +
+ this.parseDispatchQuantity(goods.quantity || goods.cargoQuantity || goods.goodsQuantity)
+ );
+ }, 0)
+ );
},
pruneDispatchPendingRows(rows = []) {
const planQuantities = new Map();
@@ -12344,9 +13094,7 @@ export default {
);
if (quantity <= 0) return goods;
const key = this.getDispatchCargoIdentity(goods);
- const available = pendingRemaining.has(key)
- ? pendingRemaining.get(key)
- : quantity;
+ const available = pendingRemaining.has(key) ? pendingRemaining.get(key) : quantity;
const remainingQuantity = Math.min(quantity, Math.max(available, 0));
if (!remainingQuantity) return null;
if (pendingRemaining.has(key)) {
@@ -12372,7 +13120,169 @@ export default {
return result;
}, []);
},
+ validateDispatchItemData(row = {}, goodsRows = [], rowIndex = -1) {
+ const detailPrefix = rowIndex >= 0 ? `第${rowIndex + 1}条调度明细` : '';
+ const warn = message => {
+ this.$message.warning(detailPrefix ? `${detailPrefix}${message}` : message);
+ return false;
+ };
+ const requiredMessage = label =>
+ warn(detailPrefix ? `的${label}不能为空` : `请选择或输入${label}`);
+ const requiredFields = [
+ ['transportType', '运输方式'],
+ ['departureAddress', '发货地址'],
+ ['arrivalAddress', '收货地址'],
+ ['carrierType', '承运类型'],
+ [
+ 'vehicleNo',
+ ['water', 'rail', 'air'].includes(this.resolveTransportMode(row.transportType))
+ ? '船/航/班列号'
+ : '车牌号',
+ ],
+ ];
+ if (row.carrierType === '承运商') {
+ requiredFields.push(['carrierName', '承运商']);
+ }
+ const fullEntry = row.taskEntryMode === 'full';
+ const roadTransport = this.resolveTransportMode(row.transportType) === 'road';
+ if (fullEntry) {
+ if (roadTransport && row.carrierType === '自运') {
+ requiredFields.push(['driverName', '司机']);
+ requiredFields.push(['driverPhone', '手机号']);
+ }
+ if (roadTransport && row.carrierType !== '承运商') {
+ requiredFields.push(['mileage', '里程']);
+ }
+ } else if (row.carrierType && row.carrierType !== '承运商') {
+ requiredFields.push(['driverName', '司机']);
+ requiredFields.push(['driverPhone', '司机手机号']);
+ requiredFields.push(['mileage', '里程']);
+ }
+ const emptyField = requiredFields.find(([prop]) => this.isBillingFieldEmpty(row[prop]));
+ if (emptyField) return requiredMessage(emptyField[1]);
+
+ if (!goodsRows.length) {
+ return warn(detailPrefix ? '的货物信息不能为空' : '请至少添加一条货物信息');
+ }
+ for (const [goodsIndex, goods] of goodsRows.entries()) {
+ const goodsPrefix = fullEntry ? `第${goodsIndex + 1}行` : '';
+ const emptyGoodsField = [
+ ['cargoType', '货物类型'],
+ ['cargoName', '货物名称'],
+ ['quantity', '本次数量'],
+ ['quantityUnit', '数量单位'],
+ ].find(([prop]) => this.isBillingFieldEmpty(goods[prop]));
+ if (emptyGoodsField) {
+ return warn(
+ detailPrefix
+ ? `的${goodsPrefix}${emptyGoodsField[1]}不能为空`
+ : `请选择或输入${goodsPrefix}${emptyGoodsField[1]}`
+ );
+ }
+ const quantity = Number(String(goods.quantity).replace(/,/g, ''));
+ if (!Number.isFinite(quantity) || quantity <= 0) {
+ return warn(
+ detailPrefix
+ ? `的${goodsPrefix}本次数量必须大于0`
+ : `${goodsPrefix}本次数量必须大于0`
+ );
+ }
+ if (!this.isBillingFieldEmpty(goods.unitPrice) && Number(goods.unitPrice) < 0) {
+ return warn(
+ detailPrefix ? `的${goodsPrefix}单价不能小于0` : `${goodsPrefix}单价不能小于0`
+ );
+ }
+ }
+
+ const invalidPhoneField = [
+ [row.departurePhone, '发货联系方式'],
+ [row.arrivalPhone, '收货联系方式'],
+ [row.driverPhone, roadTransport ? '手机号' : '联系电话'],
+ [row.escortPhone, '押运人手机号'],
+ ].find(([value]) => String(value || '').trim() && !isMobile(value));
+ if (invalidPhoneField) {
+ return warn(
+ detailPrefix
+ ? `的${invalidPhoneField[1]}格式不正确`
+ : `${invalidPhoneField[1]}格式不正确`
+ );
+ }
+ const lengthFields = roadTransport
+ ? [
+ ['driverName', '司机', 20],
+ ['driverPhone', '手机号', 20],
+ ['vehicleNo', '车牌号', 30],
+ ['trailerVehicleNo', '挂车车牌号', 30],
+ ['escortName', '押运人', 20],
+ ['escortPhone', '押运人手机号', 20],
+ ]
+ : [
+ ['vehicleNo', '船/航/班列号', 30],
+ ['captainName', '船长', 20],
+ ['cabinNo', '舱位', 30],
+ ['containerNo', '箱号', 30],
+ ];
+ const invalidLengthField = lengthFields.find(
+ ([prop, , max]) => String(row[prop] || '').length > max
+ );
+ if (invalidLengthField) {
+ return warn(
+ detailPrefix
+ ? `的${invalidLengthField[1]}不能超过${invalidLengthField[2]}个字符`
+ : `${invalidLengthField[1]}不能超过${invalidLengthField[2]}个字符`
+ );
+ }
+ if (row.mileage && (!/^\d{1,10}$/.test(String(row.mileage)) || Number(row.mileage) <= 0)) {
+ return warn(detailPrefix ? '的里程必须为不超过10位的正整数' : '里程必须为不超过10位的正整数');
+ }
+ if (!this.isBillingFieldEmpty(row.otherFeeTotal) && Number(row.otherFeeTotal) < 0) {
+ return warn(detailPrefix ? '的其他费用合计不能小于0' : '其他费用合计不能小于0');
+ }
+ if (
+ row.estimatedStartTime &&
+ row.estimatedEndTime &&
+ row.estimatedEndTime < row.estimatedStartTime
+ ) {
+ return warn(
+ detailPrefix
+ ? '的预计完成日期不能早于预计发货日期'
+ : '预计完成日期不能早于预计发货日期'
+ );
+ }
+ if (String(row.remark || row.taskRemark || '').length > 200) {
+ return warn(detailPrefix ? '的备注不能超过200个字符' : '备注不能超过200个字符');
+ }
+ return true;
+ },
+ validateDispatchItemForm() {
+ const goodsRows =
+ this.dispatchItemForm.taskEntryMode === 'full'
+ ? this.dispatchItemCargoRows
+ : [this.dispatchItemForm];
+ if (!this.validateDispatchItemData(this.dispatchItemForm, goodsRows)) return false;
+ const quantitiesByUnit = new Map();
+ goodsRows.forEach(goods => {
+ const unit = this.getDispatchQuantityUnit(goods);
+ quantitiesByUnit.set(
+ unit,
+ (quantitiesByUnit.get(unit) || 0) + this.parseDispatchQuantity(goods.quantity)
+ );
+ });
+ for (const [unit, quantity] of quantitiesByUnit.entries()) {
+ const remaining = this.dispatchItemRemainingQuantity({ quantityUnit: unit });
+ if (quantity - remaining > 1e-8) {
+ this.$message.warning(
+ `本次调度${unit}合计不能超过剩余数量${this.formatDispatchQuantity(
+ remaining
+ )}${unit}`
+ );
+ return false;
+ }
+ }
+ return true;
+ },
saveDispatchItem() {
+ if (!this.validateDispatchItemForm()) return;
const goodsRows =
this.dispatchItemForm.taskEntryMode === 'full'
? this.dispatchItemCargoRows.map(row => this.normalizeTransportCargoRow(row))
@@ -12441,10 +13351,7 @@ export default {
}, 0);
const dispatchedQuantity =
persistedDispatchedQuantity + otherDispatchedQuantity + currentQuantity;
- if (
- totalQuantity > 0 &&
- dispatchedQuantity - totalQuantity > 1e-8
- ) {
+ if (totalQuantity > 0 && dispatchedQuantity - totalQuantity > 1e-8) {
this.$message.warning(
`已调度${quantityUnit}合计不能超过总数量${this.formatDispatchQuantity(
totalQuantity
@@ -12531,54 +13438,28 @@ export default {
return false;
}
for (const [index, row] of this.dispatchRows.entries()) {
- if (row.taskEntryMode === 'full') {
- const goodsRows = this.parseJsonArray(row.goodsJson);
- if (!goodsRows.length || goodsRows.some(item => !item.cargoName || !item.cargoType || !item.quantity || !item.quantityUnit)) {
- this.$message.warning(`第${index + 1}条调度明细的完整录入货物信息不完整`);
+ const goodsRows =
+ row.taskEntryMode === 'full' ? this.parseJsonArray(row.goodsJson) : [row];
+ if (mode === 'draft') {
+ if (row.taskEntryMode === 'full' && !goodsRows.length) {
+ this.$message.warning(`第${index + 1}条调度明细的货物信息不能为空`);
return false;
}
+ const invalidPhoneField = [
+ [row.departurePhone, '发货联系方式'],
+ [row.arrivalPhone, '收货联系方式'],
+ [row.driverPhone, '手机号'],
+ [row.escortPhone, '押运人手机号'],
+ ].find(([value]) => String(value || '').trim() && !isMobile(value));
+ if (invalidPhoneField) {
+ this.$message.warning(
+ `第${index + 1}条调度明细的${invalidPhoneField[1]}格式不正确`
+ );
+ return false;
+ }
+ continue;
}
- const invalidField = [
- [row.departurePhone, '发货联系方式'],
- [row.arrivalPhone, '收货联系方式'],
- [row.driverPhone, '手机号'],
- [row.escortPhone, '押运人手机号'],
- ].find(([value]) => String(value || '').trim() && !isMobile(value));
- if (invalidField) {
- this.$message.warning(`第${index + 1}条调度明细的${invalidField[1]}格式不正确`);
- return false;
- }
- }
- if (mode === 'draft') return true;
- const invalidRow = this.dispatchRows.find(row => {
- const selfTransport = row.carrierType !== '承运商';
- return (
- !row.transportType ||
- !row.cargoName ||
- !row.cargoType ||
- !row.quantity ||
- !row.quantityUnit ||
- !row.carrierType ||
- !row.vehicleNo ||
- !row.departureAddress ||
- !row.arrivalAddress ||
- (row.carrierType === '承运商' && !row.carrierName) ||
- (selfTransport &&
- (!row.driverName || !row.driverPhone || !row.mileage))
- );
- });
- if (invalidRow) {
- this.$message.warning('请补全调度明细中的必填信息');
- return false;
- }
- const invalidMileageRow = this.dispatchRows.find(
- row =>
- row.mileage &&
- (!/^\d{1,10}$/.test(String(row.mileage)) || Number(row.mileage) <= 0)
- );
- if (invalidMileageRow) {
- this.$message.warning('里程必须为不超过10位的正整数');
- return false;
+ if (!this.validateDispatchItemData(row, goodsRows, index)) return false;
}
return true;
},
@@ -12623,8 +13504,8 @@ export default {
mode === 'draft'
? '生成草稿成功'
: shouldCompletePlan
- ? '确认生成成功,运输计划已完成'
- : '确认生成成功';
+ ? '确认生成成功,运输计划已完成'
+ : '确认生成成功';
this.$message.success(message);
this.dispatchBox = false;
this.onLoad(this.page, this.query);
@@ -12815,10 +13696,15 @@ export default {
}
&__shipping-title,
- &__goods-title {
+ &__goods-title,
+ &__task-title {
min-width: 100%;
}
+ &__shipping-route-action {
+ margin-left: auto;
+ }
+
&__goods-title &__section-actions,
&__shipping-title .el-button {
margin-left: auto;
@@ -12872,6 +13758,7 @@ export default {
&__task-form--full {
display: block;
+ margin-top: 16px;
}
&__task-row {
@@ -12915,6 +13802,18 @@ export default {
flex: 0 1 260px;
max-width: 260px;
}
+
+ :deep(.el-radio-group) {
+ width: auto;
+ }
+
+ :deep(.el-radio-button) {
+ flex: 0 0 auto;
+ }
+
+ :deep(.el-radio-button__inner) {
+ width: auto;
+ }
}
&__task-remark {
@@ -12929,6 +13828,28 @@ export default {
}
}
+ // 运单独立表单的任务信息:标题靠左,短字段保持与里程输入框一致的宽度。
+ :global(.business-crud-page--form-page .business-crud-page__task-title) {
+ justify-content: flex-start !important;
+ text-align: left;
+ }
+
+ :global(.business-crud-page--form-page .business-crud-page__task-title > .el-segmented) {
+ margin-left: auto;
+ }
+
+ :global(
+ .business-crud-page--form-page .business-crud-page__task-form
+ .el-form-item__content > .el-autocomplete
+ ),
+ :global(
+ .business-crud-page--form-page .business-crud-page__task-form
+ .el-form-item__content > .el-date-editor
+ ) {
+ width: 250px !important;
+ max-width: 100%;
+ }
+
&__suffix-select {
width: 72px;
margin-right: -8px;
@@ -13016,6 +13937,17 @@ export default {
min-width: 32px;
padding: 0;
}
+
+ &--shipping-template {
+ grid-template-columns: 220px minmax(220px, 1fr) 58px minmax(220px, 280px) 72px minmax(
+ 220px,
+ 280px
+ ) 40px;
+
+ .business-crud-page__map-suffix {
+ color: #409eff;
+ }
+ }
}
&__dispatch-shipping-form {
@@ -13132,24 +14064,24 @@ export default {
max-width: 100%;
}
- :deep(.business-crud-page__full-form-item .el-form-item) {
+ :deep(.business-crud-page__full-form-item > .el-form-item) {
width: 100%;
}
- :deep(.business-crud-page__full-form-item .el-form-item__label) {
+ :deep(.business-crud-page__full-form-item > .el-form-item > .el-form-item__label) {
display: none;
width: 0 !important;
padding: 0 !important;
}
- :deep(.business-crud-page__full-form-item .el-form-item__content) {
+ :deep(.business-crud-page__full-form-item > .el-form-item > .el-form-item__content) {
flex: 1 1 100%;
width: 100%;
max-width: 100%;
margin-left: 0 !important;
}
- :deep(.business-crud-page__full-form-item .el-form-item__content > div) {
+ :deep(.business-crud-page__full-form-item > .el-form-item > .el-form-item__content > div) {
width: 100%;
min-width: 0;
}
@@ -13233,6 +14165,13 @@ export default {
}
}
+ &__create-actions,
+ &__contract-actions {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ }
+
&__process-config-dialog {
max-height: 70vh;
overflow-y: auto;
@@ -13328,6 +14267,7 @@ export default {
&__dialog-search {
padding: 12px 12px 4px;
margin-bottom: 12px;
+ background: #fff;
border: 1px solid #eff1f7;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
@@ -13785,6 +14725,12 @@ export default {
white-space: normal;
line-height: 1.35;
}
+
+ :deep(.business-crud-page__dispatch-driver) {
+ display: inline-block;
+ max-width: 100%;
+ white-space: nowrap;
+ }
}
&__dispatch-list-card {
@@ -13897,7 +14843,7 @@ export default {
}
&--carrier {
- grid-template-columns: repeat(4, minmax(0, 1fr));
+ grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@@ -13915,7 +14861,7 @@ export default {
&__dispatch-item-carrier-type {
grid-column: 1 / -1;
- width: calc((100% - 72px) / 4);
+ width: calc((100% - 48px) / 3);
}
&__billing-form-row {
@@ -14118,6 +15064,26 @@ export default {
}
}
+ &__contract-billing-detail {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+
+ > .dialog-section-title:not(:first-child) {
+ margin-top: 4px;
+ }
+
+ :deep(.el-table__cell) {
+ border-color: #eff1f7;
+ }
+
+ :deep(.el-table__header th) {
+ background: #f5f7fa;
+ color: #303133;
+ font-weight: 600;
+ }
+ }
+
&__detail-dialog.is-transport-plan-detail {
:deep(.el-dialog) {
max-width: none;
@@ -14804,4 +15770,178 @@ export default {
padding: 0 !important;
}
}
+
+:global(.business-crud-form-page-dialog) {
+ width: 100% !important;
+ min-height: 100%;
+ box-sizing: border-box;
+ padding: 20px 24px 96px;
+ background: #f5f6fa;
+ margin: 0 !important;
+ border-radius: 0;
+ box-shadow: none;
+}
+
+:global(.business-crud-form-page-dialog .el-dialog__body) {
+ max-height: none;
+ padding: 20px 24px 96px;
+ background: #f5f6fa;
+}
+
+:global(.el-overlay:has(.business-crud-form-page-dialog)) {
+ position: fixed !important;
+ inset: 92px 0 0 230px !important;
+ z-index: 100 !important;
+ overflow: auto;
+ background: transparent;
+}
+
+:global(.el-overlay:has(.business-crud-form-page-dialog) .el-overlay-dialog) {
+ min-height: 100%;
+ overflow: visible;
+}
+
+:global(.business-crud-form-page-dialog .el-dialog__header) {
+ padding: 18px 24px;
+ margin-right: 0;
+ background: #fff;
+ border-bottom: 1px solid #eff1f7;
+}
+
+:global(.business-crud-form-page-dialog .avue-form__menu) {
+ position: fixed !important;
+ right: 0;
+ bottom: 0;
+ left: 230px;
+ z-index: 1001;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 8px;
+ min-height: 64px;
+ box-sizing: border-box;
+ padding: 12px 24px;
+ background: #fff;
+ border-top: 1px solid #eff1f7;
+ box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
+}
+
+:global(.business-crud-form-page-dialog .business-crud-page__shipping-template-footer-summary) {
+ position: static;
+ height: auto;
+ margin-right: auto;
+}
+
+:global(.avue--collapse .el-overlay:has(.business-crud-form-page-dialog)) {
+ left: 60px !important;
+}
+
+:global(.avue--collapse .business-crud-form-page-dialog .avue-form__menu) {
+ left: 60px;
+}
+
+:global(.avue-layout--horizontal .el-overlay:has(.business-crud-form-page-dialog)) {
+ top: 92px !important;
+ left: 0 !important;
+}
+
+:global(.avue-layout--horizontal .business-crud-form-page-dialog .avue-form__menu) {
+ left: 0;
+}
+
+:global(.contract-manage-form-dialog) {
+ width: 100% !important;
+ margin: 0 !important;
+ box-shadow: none;
+}
+
+:global(.contract-manage-form-dialog .el-dialog__body) {
+ max-height: none;
+ padding: 20px 24px 96px;
+ background: #f5f6fa;
+}
+
+:global(.el-overlay:has(.contract-manage-form-dialog)) {
+ position: fixed !important;
+ inset: 92px 0 0 230px !important;
+ z-index: 100 !important;
+ overflow: auto;
+ background: transparent;
+}
+
+:global(.el-overlay:has(.contract-manage-form-dialog) .el-overlay-dialog) {
+ min-height: 100%;
+ overflow: visible;
+}
+
+:global(.contract-manage-form-dialog .el-dialog__header) {
+ display: none;
+}
+
+:global(.contract-manage-form-dialog) {
+ min-height: 100%;
+ border-radius: 0;
+ box-shadow: none;
+}
+
+:global(.business-crud-page--contract-form .avue-form .el-form-item__label) {
+ flex: 0 0 calc(6em + 24px) !important;
+ width: calc(6em + 24px) !important;
+ height: auto;
+ white-space: normal !important;
+ word-break: break-all;
+ overflow-wrap: anywhere;
+ line-height: 18px;
+}
+
+:global(.business-crud-page--contract-form .avue-form .el-form-item) {
+ align-items: center;
+}
+
+:global(.business-crud-page--contract-form .avue-form .el-form-item__content .el-input),
+:global(.business-crud-page--contract-form .avue-form .el-form-item__content .el-select),
+:global(.business-crud-page--contract-form .avue-form .el-form-item__content .el-cascader),
+:global(.business-crud-page--contract-form .avue-form .el-form-item__content .el-input-number),
+:global(.business-crud-page--contract-form .avue-form .el-form-item__content .el-date-editor) {
+ width: 360px;
+ max-width: 100%;
+}
+
+:global(.business-crud-page--contract-form .contract-file-form-item .el-form-item) {
+ display: block;
+}
+
+:global(.business-crud-page--contract-form .contract-file-form-item .el-form-item__label) {
+ display: block;
+ float: none;
+ flex: none !important;
+ width: auto !important;
+ margin-bottom: 8px;
+ text-align: left;
+}
+
+:global(.business-crud-page--contract-form .contract-file-form-item .el-form-item__content) {
+ display: block;
+ margin-left: 0 !important;
+}
+
+:global(.business-crud-page--contract-form .business-crud-page__date-range),
+:global(.business-crud-page--contract-form .business-crud-page__inline-number) {
+ width: 360px;
+ max-width: 100%;
+}
+
+:global(.business-crud-page--contract-form .business-crud-page__date-range .el-date-editor),
+:global(.business-crud-page--contract-form .business-crud-page__inline-number .el-input) {
+ width: auto;
+}
+
+:global(.avue--collapse .el-overlay:has(.contract-manage-form-dialog)) {
+ left: 60px !important;
+}
+
+:global(.avue-layout--horizontal .el-overlay:has(.contract-manage-form-dialog)) {
+ top: 92px !important;
+ left: 0 !important;
+}
diff --git a/src/views/business/components/master-order-detail.vue b/src/views/business/components/master-order-detail.vue
index 591d06f..13b592f 100644
--- a/src/views/business/components/master-order-detail.vue
+++ b/src/views/business/components/master-order-detail.vue
@@ -144,7 +144,7 @@ export default {
.segment-detail__header-right { display: flex; align-items: center; gap: 12px; }
.segment-index { display: inline-flex; width: 36px; height: 36px; align-items: center; justify-content: center; border-radius: 50%; background: #2088ee; color: #fff; font-size: 20px; font-weight: 500; }
.segment-execution { padding-top: 12px; }
-.segment-stats { display: flex; gap: 72px; padding: 4px 0 24px; div { display: flex; flex-direction: column; gap: 8px; } span { color: #8a9bb8; font-size: 14px; } strong { color: #1f2d3d; font-size: 32px; line-height: 1; } small { margin-left: 6px; color: #8a9bb8; font-size: 16px; font-weight: 400; } .dispatched { color: #16a34a; } .remaining { color: #f59e0b; } }
+.segment-stats { display: flex; gap: 72px; padding: 4px 0 24px; div { display: flex; flex-direction: column; gap: 8px; } span { color: #8a9bb8; font-size: 14px; } strong { color: #1f2d3d; font-size: 32px; line-height: 1; } small { margin-left: 6px; color: #8a9bb8; font-size: 16px; font-weight: 400; } .dispatched { color: #409eff; } .remaining { color: #f56c6c; } }
.waybill-table { :deep(th.el-table__cell) { background: #f5f7fa; color: #60738f; } }
.transport-plan-detail { margin-top: 20px; h4 { margin: 0 0 12px; padding-left: 12px; border-left: 4px solid #409eff; font-size: 15px; } }
.master-goods-card { margin-bottom: 8px; border: 1px solid #eff1f7; background: #fff; }
diff --git a/src/views/business/components/master-order-dispatch.vue b/src/views/business/components/master-order-dispatch.vue
index 5a8545f..22fb9a0 100644
--- a/src/views/business/components/master-order-dispatch.vue
+++ b/src/views/business/components/master-order-dispatch.vue
@@ -12,8 +12,8 @@
客户{{ master.customerName || '-' }}
合同编号{{ master.contractNo || '-' }}
项目{{ master.projectName || '-' }}
-
货物名称{{ goodsNames }}
-
货物类型{{ goodsTypes }}
+
货物名称{{ goodsNames }}
+
货物类型{{ goodsTypes }}
运输周期{{ dateRange }}
@@ -39,7 +39,19 @@
@@ -49,13 +61,6 @@
-
-
-
- 计划单运单
-
-
-
@@ -78,8 +83,8 @@
- handleCargoTypeChange(route, row, value)" />
-
+ handleCargoTypeChange(route, row, value)" />
+
{{ formatQuantity(goodsRemainingQuantity(route, row)) }}
handleDispatchQuantityInput(route, row, value)" />
@@ -95,14 +100,14 @@
-
+
handleFreightUnitPriceInput(item, value)">
-
+
handleFreightQuantityUnitChange(route, item, value)">
@@ -142,7 +147,7 @@
- handleMileageInput(route, value)" />
+ handleMileageInput(route, value)" />
@@ -433,9 +438,7 @@ export default {
validateFreightItems(route) {
for (const [index, item] of (route.freightItems || []).entries()) {
const fields = [
- ['unitPrice', '单价'],
['priceUnit', '单价单位'],
- ['quantity', '数量'],
['quantityUnit', '数量单位'],
];
const emptyField = fields.find(
@@ -590,10 +593,10 @@ export default {
if (!this.validateRoutePhones(route)) return;
if (route.documentType === '运单') {
if (this.isRoad(route)) {
- if (route.carrierType === '承运商' && (!route.carrierName || !route.vehicleNo || !route.mileage)) return this.$message.warning('请填写承运商、车牌号和里程');
- if (route.carrierType !== '承运商' && (!route.driverName || !route.driverPhone || !route.vehicleNo || !route.trailerVehicleNo || !route.escortName || !route.escortPhone || route.mileage === undefined || route.mileage === null || route.mileage === '')) return this.$message.warning('请补全自运或网货平台的车辆与人员信息');
- } else if (!route.vehicleNo || !route.captainName || !route.driverPhone || !route.containerNo || !route.cabinNo || route.mileage === undefined || route.mileage === null || route.mileage === '' || (route.carrierType === '承运商' && !route.carrierName)) {
- return this.$message.warning('请补全非公路运输的承运信息和里程');
+ if (route.carrierType === '承运商' && (!route.carrierName || !route.vehicleNo)) return this.$message.warning('请填写承运商和车牌号');
+ if (route.carrierType !== '承运商' && (!route.driverName || !route.driverPhone || !route.vehicleNo || !route.trailerVehicleNo || !route.escortName || !route.escortPhone)) return this.$message.warning('请补全自运或网货平台的车辆与人员信息');
+ } else if (!route.vehicleNo || !route.captainName || !route.driverPhone || !route.containerNo || !route.cabinNo || (route.carrierType === '承运商' && !route.carrierName)) {
+ return this.$message.warning('请补全非公路运输的承运信息');
}
}
const batchNo = `${route.segmentNo}-${Date.now()}`;
@@ -666,9 +669,13 @@ export default {
.pending-list-spacer { height: min(436px, calc(100vh - 130px)); }
.master-overview, .dispatch-section { margin-bottom: 8px; border: 1px solid #eff1f7; background: #fff; }
.overview-heading, .segment-header, .pending-bar { display: flex; align-items: center; justify-content: space-between; }
+.segment-header :deep(.el-checkbox.is-checked .el-checkbox__label) { font-size: 16px; font-weight: 700; }
+.segment-checkbox-label { display: inline-flex; align-items: center; min-width: 0; }
+.segment-checkbox-path { display: inline-block; white-space: nowrap; }
.overview-heading { padding: 18px 24px 12px; h2 { display: inline-block; margin: 0 16px 0 0; font-size: 20px; } h2 span { margin: 0 8px; color: #909399; font-weight: 400; } }
.overview-content { display: grid; grid-template-columns: minmax(400px, .9fr) minmax(620px, 1.6fr); gap: 28px; padding: 8px 24px 20px; }
.overview-meta { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px 24px; margin: 0; dt { margin-bottom: 6px; color: #909399; font-size: 13px; } dd { margin: 0; color: #409eff; font-size: 14px; word-break: break-all; } }
+.overview-meta dd.overview-meta__plain-value { color: #303133; }
.route-overview { display: flex; align-items: flex-start; justify-content: flex-end; padding-top: 8px; overflow-x: auto; }
.route-overview__node { display: grid; flex: 0 0 130px; justify-items: center; gap: 6px; text-align: center; strong { font-size: 16px; white-space: nowrap; } small { color: #606266; white-space: nowrap; } }
.route-badge { display: inline-flex; width: 32px; height: 32px; align-items: center; justify-content: center; border-radius: 4px; background: #67c23a; color: #fff; font-weight: 600; &.start { background: #409eff; } &.end { background: #e6a23c; } }
@@ -679,7 +686,7 @@ export default {
.transport-type-field :deep(.el-input) { width: 240px; }
.goods-heading { display: flex; align-items: center; justify-content: space-between; margin: 0 -24px 12px; padding: 14px 24px; border-top: 1px solid #eff1f7; border-bottom: 1px solid #eff1f7; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } span { color: #909399; font-size: 13px; } }
.freight-heading { margin: 16px 0 12px; h3 { margin: 0; padding-left: 12px; border-left: 4px solid #409eff; font-size: 16px; } }
-.goods-table { :deep(th.el-table__cell), :deep(td.el-table__cell) { border-color: #eff1f7; } :deep(.el-table__row--striped td.el-table__cell) { background: #fafafa; } :deep(.goods-table__remaining .cell) { white-space: nowrap; } :deep(.goods-table__dispatch .el-input) { width: 100%; min-width: 0; } }
+.goods-table { :deep(th.el-table__cell), :deep(td.el-table__cell) { border-color: #eff1f7; } :deep(.el-table__row--striped td.el-table__cell) { background: #fafafa; } :deep(.goods-table__remaining .cell) { white-space: nowrap; } :deep(.goods-table__dispatch .el-input) { width: 100%; min-width: 0; } :deep(.goods-table__cargo-type .el-input__inner), :deep(.goods-table__cargo-name .el-select__selected-item) { color: #303133; } }
.freight-form { :deep(.freight-unit-select) { width: 92px; } }
.carrier-type-form { margin-top: 16px; }
.carrier-form { padding-top: 8px; }
diff --git a/src/views/business/components/master-order-editor.vue b/src/views/business/components/master-order-editor.vue
index 55e04c3..a3ce199 100644
--- a/src/views/business/components/master-order-editor.vue
+++ b/src/views/business/components/master-order-editor.vue
@@ -63,7 +63,7 @@
@@ -84,12 +84,12 @@
经
- 段{{ index + 1 }}{{ getRouteTitle(index).replace(`段${index + 1}:`, '') }}运输方式
+ 段{{ index + 1 }}{{ formatRouteTitle(getRouteTitle(index), index + 1) }}运输方式
@@ -98,12 +98,12 @@
终
- 段{{ form.routes.length + 1 }}{{ getFinalRouteTitle().replace(`段${form.routes.length + 1}:`, '') }}运输方式
+ 段{{ form.routes.length + 1 }}{{ formatRouteTitle(getFinalRouteTitle(), form.routes.length + 1) }}运输方式
@@ -112,9 +112,9 @@
@@ -299,6 +299,31 @@
width="1100px"
@opened="loadAddressList"
>
+