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 @@ + + + + + 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 @@ + + + + +