From acbc9d3322c9142fffda136f17c3b10500993a27 Mon Sep 17 00:00:00 2001
From: b2894lxlx <517289602@qq.com>
Date: Mon, 14 Sep 2026 01:49:23 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=20=E5=9F=BA=E7=A1=80?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E3=80=81=E8=BF=90=E5=8A=9B=E3=80=81=E8=BD=A6?=
=?UTF-8?q?=E8=88=B9=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/base/measurement-unit.js | 52 +++
src/api/transportCapacity/vehicle-dispatch.js | 25 +
src/option/base/measurement-unit.js | 133 ++++++
.../transportCapacity/vehicle-dispatch.js | 171 +++++++
src/views/base/measurement-unit.vue | 255 +++++++++++
src/views/base/region.vue | 7 +-
.../components/waybill-manage-page.vue | 12 +
.../components/formal-settlement-editor.vue | 50 +-
.../settlement/formal-settlement-form.vue | 10 +-
src/views/settlement/formal-settlement.vue | 6 +-
src/views/transportCapacity/driver.vue | 22 +-
.../transportCapacity/vehicle-dispatch.vue | 429 ++++++++++++++++++
12 files changed, 1157 insertions(+), 15 deletions(-)
create mode 100644 src/api/base/measurement-unit.js
create mode 100644 src/api/transportCapacity/vehicle-dispatch.js
create mode 100644 src/option/base/measurement-unit.js
create mode 100644 src/option/transportCapacity/vehicle-dispatch.js
create mode 100644 src/views/base/measurement-unit.vue
create mode 100644 src/views/transportCapacity/vehicle-dispatch.vue
diff --git a/src/api/base/measurement-unit.js b/src/api/base/measurement-unit.js
new file mode 100644
index 0000000..c1eee7e
--- /dev/null
+++ b/src/api/base/measurement-unit.js
@@ -0,0 +1,52 @@
+import request from '@/axios';
+
+export const getList = (current, size, params) => {
+ return request({
+ url: '/blade-system/measurement-unit/list',
+ method: 'get',
+ params: {
+ ...params,
+ current,
+ size,
+ },
+ });
+};
+
+export const getDetail = id => {
+ return request({
+ url: '/blade-system/measurement-unit/detail',
+ method: 'get',
+ params: {
+ id,
+ },
+ });
+};
+
+export const remove = ids => {
+ return request({
+ url: '/blade-system/measurement-unit/remove',
+ method: 'post',
+ params: {
+ ids,
+ },
+ });
+};
+
+export const submit = row => {
+ return request({
+ url: '/blade-system/measurement-unit/submit',
+ method: 'post',
+ data: row,
+ });
+};
+
+export const changeStatus = (id, status) => {
+ return request({
+ url: '/blade-system/measurement-unit/status',
+ method: 'post',
+ params: {
+ id,
+ status,
+ },
+ });
+};
diff --git a/src/api/transportCapacity/vehicle-dispatch.js b/src/api/transportCapacity/vehicle-dispatch.js
new file mode 100644
index 0000000..7256578
--- /dev/null
+++ b/src/api/transportCapacity/vehicle-dispatch.js
@@ -0,0 +1,25 @@
+import request from '@/axios';
+
+const baseUrl = '/blade-transport/vehicle-dispatch';
+
+export const getList = (current, size, params) =>
+ request({ url: `${baseUrl}/list`, method: 'get', params: { ...params, current, size } });
+
+export const getDetail = id => request({ url: `${baseUrl}/detail`, method: 'get', params: { id } });
+
+export const submit = row => request({ url: `${baseUrl}/submit`, method: 'post', data: row });
+
+export const remove = ids => request({ url: `${baseUrl}/remove`, method: 'post', params: { ids } });
+
+export const submitApproval = id =>
+ request({ url: `${baseUrl}/submit-approval`, method: 'post', params: { id } });
+
+export const approve = id => request({ url: `${baseUrl}/approve`, method: 'post', params: { id } });
+
+export const exportVehicleDispatch = params =>
+ request({
+ url: `${baseUrl}/export-vehicle-dispatch`,
+ method: 'get',
+ params,
+ responseType: 'blob',
+ });
diff --git a/src/option/base/measurement-unit.js b/src/option/base/measurement-unit.js
new file mode 100644
index 0000000..c135823
--- /dev/null
+++ b/src/option/base/measurement-unit.js
@@ -0,0 +1,133 @@
+const dimensionOptions = [
+ { label: '重量', value: '重量' },
+ { label: '体积', value: '体积' },
+ { label: '数量', value: '数量' },
+];
+
+const statusOptions = [
+ { label: '启用', value: 1 },
+ { label: '停用', value: 2 },
+];
+
+export const createOption = () => ({
+ height: 'auto',
+ calcHeight: 32,
+ dialogWidth: 680,
+ labelPosition: 'right',
+ labelWidth: 'auto',
+ tip: false,
+ searchBtnText: '查询',
+ emptyBtnText: '重置',
+ saveBtnText: '提交',
+ updateBtnText: '提交',
+ searchShow: true,
+ searchMenuSpan: 24,
+ searchIcon: true,
+ searchIndex: 4,
+ searchMenuPosition: 'right',
+ border: true,
+ index: true,
+ indexLabel: '序号',
+ indexWidth: 70,
+ addBtn: false,
+ viewBtn: false,
+ editBtn: false,
+ delBtn: false,
+ selection: true,
+ dialogClickModal: false,
+ menuWidth: 240,
+ menuFixed: 'right',
+ column: [
+ {
+ label: '计量单位',
+ prop: 'unitName',
+ minWidth: 150,
+ search: true,
+ searchOrder: 3,
+ searchSpan: 6,
+ maxlength: 50,
+ showWordLimit: true,
+ rules: [
+ { required: true, message: '请输入计量单位', trigger: 'blur' },
+ { max: 50, message: '计量单位不能超过50个字', trigger: 'blur' },
+ ],
+ },
+ {
+ label: '计量维度',
+ prop: 'dimension',
+ type: 'select',
+ minWidth: 130,
+ search: true,
+ searchOrder: 2,
+ searchSpan: 6,
+ dicData: dimensionOptions,
+ rules: [{ required: true, message: '请选择计量维度', trigger: 'change' }],
+ },
+ {
+ label: '备注',
+ prop: 'remark',
+ type: 'textarea',
+ minRows: 2,
+ span: 24,
+ minWidth: 200,
+ maxlength: 200,
+ showWordLimit: true,
+ overHidden: true,
+ rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
+ },
+ {
+ label: '状态',
+ prop: 'status',
+ type: 'select',
+ search: true,
+ searchOrder: 1,
+ searchSpan: 6,
+ slot: true,
+ dataType: 'number',
+ dicData: statusOptions,
+ clearable: true,
+ value: 1,
+ addDisplay: false,
+ editDisplay: false,
+ minWidth: 100,
+ },
+ {
+ label: '创建人',
+ prop: 'createUserName',
+ addDisplay: false,
+ editDisplay: false,
+ viewDisplay: false,
+ display: false,
+ },
+ {
+ label: '更新人',
+ prop: 'updateUserName',
+ addDisplay: false,
+ editDisplay: false,
+ viewDisplay: false,
+ display: false,
+ },
+ {
+ label: '创建时间',
+ prop: 'createTime',
+ type: 'datetime',
+ format: 'YYYY-MM-DD HH:mm:ss',
+ valueFormat: 'YYYY-MM-DD HH:mm:ss',
+ sortable: true,
+ addDisplay: false,
+ editDisplay: false,
+ display: false,
+ },
+ {
+ label: '更新时间',
+ prop: 'updateTime',
+ type: 'datetime',
+ format: 'YYYY-MM-DD HH:mm:ss',
+ valueFormat: 'YYYY-MM-DD HH:mm:ss',
+ sortable: true,
+ addDisplay: false,
+ editDisplay: false,
+ display: false,
+ },
+ ],
+});
diff --git a/src/option/transportCapacity/vehicle-dispatch.js b/src/option/transportCapacity/vehicle-dispatch.js
new file mode 100644
index 0000000..f8ab8d7
--- /dev/null
+++ b/src/option/transportCapacity/vehicle-dispatch.js
@@ -0,0 +1,171 @@
+const approvalStatusOptions = [
+ { label: '草稿', value: 'draft' },
+ { label: '审批中', value: 'reviewing' },
+ { label: '已驳回', value: 'rejected' },
+ { label: '审批通过', value: 'approved' },
+];
+
+export const statusName = status =>
+ approvalStatusOptions.find(item => item.value === status)?.label || status || '-';
+
+export const option = {
+ height: 'auto',
+ calcHeight: 32,
+ dialogWidth: 1200,
+ labelPosition: 'right',
+ labelWidth: 'auto',
+ tip: false,
+ searchBtnText: '查询',
+ emptyBtnText: '重置',
+ saveBtnText: '提交',
+ updateBtnText: '提交',
+ searchShow: true,
+ searchMenuSpan: 24,
+ searchIndex: 4,
+ searchMenuPosition: 'right',
+ border: true,
+ index: true,
+ indexLabel: '序号',
+ indexWidth: 70,
+ addBtn: false,
+ editBtn: false,
+ delBtn: false,
+ viewBtn: false,
+ selection: false,
+ dialogClickModal: false,
+ menuFixed: 'right',
+ menuWidth: 320,
+ column: [
+ {
+ label: '申请单号',
+ prop: 'applicationNo',
+ search: true,
+ searchOrder: 5,
+ searchPlaceholder: '请输入',
+ minWidth: 180,
+ slot: true,
+ addDisplay: true,
+ editDisabled: true,
+ disabled: true,
+ placeholder: '保存后自动生成',
+ },
+ {
+ label: '调度车辆',
+ prop: 'plateNo',
+ search: true,
+ searchOrder: 4,
+ searchPlaceholder: '请输入',
+ minWidth: 120,
+ formslot: true,
+ rules: [{ required: true, message: '请输入车牌号', trigger: 'blur' }],
+ },
+ {
+ label: '所属组织',
+ prop: 'organizationName',
+ search: true,
+ searchOrder: 3,
+ searchPlaceholder: '请输入',
+ minWidth: 140,
+ disabled: true,
+ placeholder: '选择调度车辆后自动填充',
+ rules: [{ required: true, message: '请输入所属组织', trigger: 'blur' }],
+ },
+ {
+ label: '使用部门',
+ prop: 'useDepartment',
+ search: true,
+ searchOrder: 2,
+ searchPlaceholder: '请输入',
+ minWidth: 140,
+ formslot: true,
+ span: 12,
+ rules: [{ required: true, message: '请输入使用部门', trigger: 'blur' }],
+ },
+ {
+ label: '审批状态',
+ prop: 'approvalStatus',
+ search: true,
+ searchOrder: 1,
+ type: 'select',
+ dicData: approvalStatusOptions,
+ slot: true,
+ minWidth: 120,
+ addDisplay: false,
+ editDisplay: false,
+ },
+ {
+ label: '当前节点',
+ prop: 'currentNode',
+ minWidth: 120,
+ addDisplay: false,
+ editDisplay: false,
+ },
+ {
+ label: '当前处理人',
+ prop: 'currentProcessor',
+ minWidth: 130,
+ addDisplay: false,
+ editDisplay: false,
+ },
+ {
+ label: '申请人',
+ prop: 'createUserName',
+ hide: true,
+ display: true,
+ addDisplay: true,
+ editDisplay: true,
+ viewDisplay: true,
+ disabled: true,
+ span: 12,
+ },
+ {
+ label: '申请时间',
+ prop: 'createTime',
+ type: 'datetime',
+ format: 'YYYY-MM-DD HH:mm:ss',
+ valueFormat: 'YYYY-MM-DD HH:mm:ss',
+ hide: true,
+ display: true,
+ addDisplay: true,
+ editDisplay: true,
+ viewDisplay: true,
+ disabled: true,
+ span: 12,
+ },
+ {
+ label: '创建人',
+ prop: 'createUserName',
+ minWidth: 120,
+ addDisplay: false,
+ editDisplay: false,
+ },
+ {
+ label: '创建时间',
+ prop: 'createTime',
+ type: 'datetime',
+ format: 'YYYY-MM-DD HH:mm:ss',
+ valueFormat: 'YYYY-MM-DD HH:mm:ss',
+ minWidth: 170,
+ addDisplay: false,
+ editDisplay: false,
+ },
+ {
+ label: '备注',
+ prop: 'remark',
+ type: 'textarea',
+ span: 24,
+ maxlength: 200,
+ showWordLimit: true,
+ rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
+ },
+ {
+ label: '附件',
+ prop: 'attachments',
+ hide: true,
+ span: 24,
+ minWidth: 100,
+ slot: true,
+ formslot: true,
+ },
+ ],
+};
diff --git a/src/views/base/measurement-unit.vue b/src/views/base/measurement-unit.vue
new file mode 100644
index 0000000..11d1181
--- /dev/null
+++ b/src/views/base/measurement-unit.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+ 新增
+
+
+ 批量删除
+
+
+
+ {{ row.dimension || '-' }}
+
+
+
+ {{ row.status === 1 ? '启用' : '停用' }}
+
+
+
+
+ 编辑
+
+
+ {{ row.status === 1 ? '停用' : '启用' }}
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/base/region.vue b/src/views/base/region.vue
index 8e40bc1..62adceb 100644
--- a/src/views/base/region.vue
+++ b/src/views/base/region.vue
@@ -251,7 +251,12 @@ export default {
prop: 'regionLevel',
type: 'radio',
dicUrl: '/blade-system/dict/dictionary?code=region',
- dicFormatter: list => list.filter(item => Number(item.dictKey) !== 0),
+ dicFormatter: response => {
+ const list = Array.isArray(response) ? response : response?.data;
+ return (Array.isArray(list) ? list : [])
+ .filter(item => Number(item.dictKey) !== 0)
+ .map(item => ({ ...item, dictKey: Number(item.dictKey) }));
+ },
props: {
label: 'dictValue',
value: 'dictKey',
diff --git a/src/views/business/components/waybill-manage-page.vue b/src/views/business/components/waybill-manage-page.vue
index 39ee839..5a6d7ab 100644
--- a/src/views/business/components/waybill-manage-page.vue
+++ b/src/views/business/components/waybill-manage-page.vue
@@ -4796,6 +4796,13 @@ export default {
},
normalizeRow(row, saveAsDraft = false) {
const submitRow = { ...row };
+ const isAddMode =
+ this.crudDialogType === 'add' ||
+ (this.isStandaloneWaybillFormPage && this.$route.query.mode === 'add');
+ if (isAddMode) {
+ delete submitRow.id;
+ delete submitRow.waybillNo;
+ }
const skipValidation = saveAsDraft && this.config.skipDraftValidation === true;
if (
!skipValidation &&
@@ -5166,6 +5173,7 @@ export default {
// 清除不应该复制的字段
delete sourceData.id;
delete sourceData.code;
+ delete sourceData.waybillNo;
delete sourceData.waybillStatus;
delete sourceData.createTime;
delete sourceData.updateTime;
@@ -5236,6 +5244,10 @@ export default {
['quantity', 'mileage', 'unitPrice'].forEach(prop => {
if (Number(this.form[prop]) === -1) this.form[prop] = '';
});
+ if ([this.form.planId, this.form.planName].some(value => Number(value) === -1)) {
+ this.form.planId = '';
+ this.form.planName = '';
+ }
this.form.mileage = this.normalizeMileageValue(this.form.mileage);
this.$nextTick(() => {
this.suppressTransportTypeClear = false;
diff --git a/src/views/settlement/components/formal-settlement-editor.vue b/src/views/settlement/components/formal-settlement-editor.vue
index 7fbdf3c..93cd0bd 100644
--- a/src/views/settlement/components/formal-settlement-editor.vue
+++ b/src/views/settlement/components/formal-settlement-editor.vue
@@ -1199,9 +1199,7 @@ export default {
this.selectedAttachmentRows = [];
this.invoices = data.invoices || [];
this.sortAttachments();
- this.contracts = this.allContracts.filter(
- item => String(item.projectId) === String(this.form.projectId)
- );
+ this.contracts = this.filterContracts(this.allContracts, this.form.projectId);
},
async initialize() {
const newRecordAudit = this.recordId
@@ -1211,6 +1209,11 @@ export default {
createTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'),
};
this.form = createFormalSettlementForm();
+ if (['receivable', 'payable'].includes(this.initialData?.settlementType)) {
+ this.form.settlementType = this.initialData.settlementType;
+ this.form.settlementTypeName =
+ this.initialData.settlementType === 'receivable' ? '应收' : '应付';
+ }
if (newRecordAudit) Object.assign(this.form, newRecordAudit);
this.sources = [];
this.details = [];
@@ -1276,7 +1279,7 @@ export default {
if (!rows.length) return;
const first = rows[0];
const settlementType = this.initialData.settlementType || first.settlementType || 'payable';
- const matchedContract = this.allContracts.find(
+ const matchedContract = this.filterContracts(this.allContracts, null, settlementType).find(
item =>
(first.contractId && String(item.id) === String(first.contractId)) ||
(first.contractNo && String(item.contractNo) === String(first.contractNo))
@@ -1284,9 +1287,7 @@ export default {
const contractId = first.contractId || matchedContract?.id || null;
const projectId = first.projectId || matchedContract?.projectId || null;
const projectName = first.projectName || matchedContract?.projectName || '';
- this.contracts = this.allContracts.filter(
- item => projectId && String(item.projectId) === String(projectId)
- );
+ this.contracts = this.filterContracts(this.allContracts, projectId, settlementType);
if (projectId && !this.projects.some(item => String(item.id) === String(projectId))) {
this.projects.push({ id: projectId, name: projectName });
}
@@ -1404,6 +1405,25 @@ export default {
this.projects = [...projectMap.values()];
this.contracts = [];
},
+ contractCategory(settlementType = this.form.settlementType) {
+ if (settlementType === 'receivable') return '客户合同';
+ if (settlementType === 'payable') return '承运商合同';
+ return '';
+ },
+ filterContracts(items, projectId, settlementType = this.form.settlementType) {
+ const category = this.contractCategory(settlementType);
+ return (items || []).filter(item => {
+ if (projectId && String(item.projectId) !== String(projectId)) return false;
+ if (!category) return true;
+ const itemCategory = String(item.contractCategory || '').trim();
+ if (itemCategory) return itemCategory === category;
+ const itemSettlementType = String(item.settlementType || '').trim();
+ return (
+ (category === '客户合同' && itemSettlementType === 'receivable') ||
+ (category === '承运商合同' && itemSettlementType === 'payable')
+ );
+ });
+ },
async loadContracts(keyword = '') {
const projectId = this.form.projectId;
if (!projectId) {
@@ -1412,7 +1432,7 @@ export default {
}
const response = await getContractOptions(keyword, projectId);
if (String(this.form.projectId) === String(projectId)) {
- this.contracts = this.unwrapData(response) || [];
+ this.contracts = this.filterContracts(this.unwrapData(response), projectId);
}
},
async loadFeeOptions() {
@@ -1444,16 +1464,24 @@ export default {
const contract = this.contracts.find(item => String(item.id) === String(id));
if (!contract) return;
const formalSettlementId = this.form.id;
+ const settlementType =
+ contract.settlementType ||
+ (contract.contractCategory === '客户合同'
+ ? 'receivable'
+ : contract.contractCategory === '承运商合同'
+ ? 'payable'
+ : this.form.settlementType);
Object.assign(this.form, contract, {
id: formalSettlementId,
contractId: contract.id,
payerName:
contract.payerName ||
- (contract.settlementType === 'receivable' ? contract.partyB : contract.partyA),
+ (settlementType === 'receivable' ? contract.partyB : contract.partyA),
payeeName:
contract.payeeName ||
- (contract.settlementType === 'receivable' ? contract.partyA : contract.partyB),
- settlementTypeName: contract.settlementType === 'receivable' ? '应收' : '应付',
+ (settlementType === 'receivable' ? contract.partyA : contract.partyB),
+ settlementType,
+ settlementTypeName: settlementType === 'receivable' ? '应收' : '应付',
});
this.sources = [];
this.details = [];
diff --git a/src/views/settlement/formal-settlement-form.vue b/src/views/settlement/formal-settlement-form.vue
index ce8253d..999e8bd 100644
--- a/src/views/settlement/formal-settlement-form.vue
+++ b/src/views/settlement/formal-settlement-form.vue
@@ -7,7 +7,7 @@
page-mode
:record-id="recordId"
:readonly="readonly"
- :initial-data="transferPayload"
+ :initial-data="editorInitialData"
/>
@@ -35,6 +35,14 @@ export default {
pageTitle() {
return this.readonly ? '查看正式结算' : this.recordId ? '编辑正式结算' : '新增正式结算';
},
+ editorInitialData() {
+ const settlementType = this.$route.query.settlementType;
+ if (!this.transferPayload && !settlementType) return null;
+ return {
+ ...(this.transferPayload || {}),
+ ...(settlementType ? { settlementType } : {}),
+ };
+ },
},
watch: {
editorVisible(value) {
diff --git a/src/views/settlement/formal-settlement.vue b/src/views/settlement/formal-settlement.vue
index 2fbe65e..002b5d5 100644
--- a/src/views/settlement/formal-settlement.vue
+++ b/src/views/settlement/formal-settlement.vue
@@ -299,7 +299,11 @@ export default {
openCreate() {
this.$router.push({
path: '/settlement/formal-settlement/form',
- query: { mode: 'add', name: '新增正式结算' },
+ query: {
+ mode: 'add',
+ name: '新增正式结算',
+ settlementType: this.activeSettlementType,
+ },
});
},
openEdit(row) {
diff --git a/src/views/transportCapacity/driver.vue b/src/views/transportCapacity/driver.vue
index 79227ee..3992019 100644
--- a/src/views/transportCapacity/driver.vue
+++ b/src/views/transportCapacity/driver.vue
@@ -143,7 +143,7 @@
maxlength="18"
show-word-limit
placeholder="请输入"
- @input="driverForm.idCardNo = String(driverForm.idCardNo || '').toUpperCase()"
+ @input="handleIdCardInput"
/>
@@ -1121,6 +1121,26 @@ export default {
removeDigits(value = '') {
return String(value).replace(/\d/g, '');
},
+ handleIdCardInput(value) {
+ const idCardNo = String(value || '').toUpperCase();
+ this.driverForm.idCardNo = idCardNo;
+ const idCardInfo = this.parseIdCardInfo(idCardNo);
+ if (idCardInfo.birthday) {
+ this.driverForm.birthday = idCardInfo.birthday;
+ } else {
+ this.driverForm.birthday = '';
+ }
+ if (idCardInfo.gender) {
+ this.driverForm.gender = idCardInfo.gender;
+ } else {
+ this.driverForm.gender = '';
+ }
+ if (this.submitAttempted) {
+ this.$nextTick(() => {
+ this.$refs.driverForm?.validateField(['idCardNo', 'birthday', 'gender']);
+ });
+ }
+ },
openDriver(row, readonly = false) {
this.readonly = readonly;
this.submitAttempted = false;
diff --git a/src/views/transportCapacity/vehicle-dispatch.vue b/src/views/transportCapacity/vehicle-dispatch.vue
new file mode 100644
index 0000000..20e0d54
--- /dev/null
+++ b/src/views/transportCapacity/vehicle-dispatch.vue
@@ -0,0 +1,429 @@
+
+
+
+
+
+ 新增
+
+
+ 导出
+
+
+
+ {{ row.applicationNo }}
+
+
+
+
+
+
+
+
+ {{ formatAttachments(row.attachments) }}
+
+
+
+
+
+
+
+
+
+ {{ statusName(row.approvalStatus) }}
+
+
+
+
+ 查看
+
+
+ 编辑
+
+
+ 提交
+
+
+ 审核通过
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+