From c1813e308f417df1154c8d7b49e94a73cbabb837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Wed, 9 Sep 2026 19:06:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(vehicle):=20=E9=87=8D=E6=9E=84=E8=BD=A6?= =?UTF-8?q?=E8=BE=86=E8=AE=A4=E8=AF=81=E5=AE=A1=E6=A0=B8=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E4=B8=8E=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增车辆认证审核弹窗,取消独立尺寸重量卡片,外廓尺寸改为长/宽/高组合布局 - 基础信息调整为3行4列,证件信息新增车辆资质图片行,所属组织标签更名为所有组织 - 行驶证有效期必填星号动态显示,长期有效时不显示且不校验,删除旧校验方法 - driver.vue中从业资格证有效期改为起止日期区间,新增起始日期字段,调整验证规则 - 驾驶证和从业资格证长期有效时禁用起止日期输入,校验逻辑同步调整,提交保留旧值 - contract-manage-change.vue合同文件批量下载按钮移入标题栏,与其它附件分区样式统一 - 样式更新,新增 dimension-group 用于外廓尺寸排版复用及其他局部样式调整 - 修复因后端未实现接口导致的降级方案预留,等待后端补充支持 --- .workbuddy/memory/2026-09-09.md | 9 + src/views/business/contract-manage-change.vue | 5 +- src/views/transportCapacity/driver.vue | 58 +++-- src/views/transportCapacity/vehicle.vue | 223 ++++++++++-------- 4 files changed, 173 insertions(+), 122 deletions(-) diff --git a/.workbuddy/memory/2026-09-09.md b/.workbuddy/memory/2026-09-09.md index c45e331..152dc68 100644 --- a/.workbuddy/memory/2026-09-09.md +++ b/.workbuddy/memory/2026-09-09.md @@ -203,3 +203,12 @@ - 样式:`.settlement-switch-tip { margin:0 4px; color:#a8abb2; cursor:help; font-size:14px }`,各文件 scoped 样式内一份(contract-manage 写在 `&__settlement-switch` 内)。 - 注意:图标走 main.js 全局注册(@element-plus/icons-vue 全量注册),无需 import;写法与 `project-apply.vue` 的 `__label-tip` 一致。 - 这三个大文件本身已存在 prettier 格式问题(改动前 git HEAD 版本同样 fail),非本次引入。 + +## 车辆认证审核弹窗排版对齐新增弹窗(vehicle.vue) +- 诊断 `/project-apply/fund-risk-stats` No endpoint:前端已定义 getFundRiskStats(api/business/project-apply.js:13),后端未实现;方案已给(后端补 R<{high,medium}> / 前端 catch 降级),待主人选。 +- vehicle.vue 认证审核弹窗重排对齐新增弹窗:取消独立「尺寸重量」卡片,外廓尺寸改长/宽/高组合(span12,dimension-group);基础信息 3 行×4 列(车牌号/车辆类型/外廓尺寸;载质量/牵引质量/业务关系/能源类型;强制报废日期/海关备案号/所有组织/使用部门);证件信息按新增「车辆资质图片」行分布(止+运输证号+止+年审 / 登记编号+登记日期+档案编号+行驶证起 / 运输证起 / 备注整行);label「所属组织」改「所有组织」对齐新增;dimension-group 样式复制进 .certification-audit 作用域。@vue/compiler-sfc 编译校验通过。 +- vehicle.vue 行驶证有效期必填星号:原规则是纯 validator(Element Plus 不渲染星号),改为 data 内 baseRules + computed formRules,drivingLicenseEndDate 动态返回 required 规则(长期有效=1 时返回 [],星号与校验同步消失);删除 validateDrivingLicenseEndDate。经验:Element Plus 星号只在规则含 required:true 时渲染,且 el-form-item 的 :required 属性会被注入为 {required} 规则并产生英文默认提示,不宜用它控制星号。 +- 备注:车辆保存的「车牌颜色不能为空」「行驶证有效期:必填」均为后端校验(前端无对应规则),需后端改。 +- driver.vue 从业资格证有效期对齐驾驶证:单日期改 date-range 起/止(列宽 6+6+6+6 → 6+6+8+4),新增 qualificationStartDate 字段(emptyForm + handleSubmit normalize);qualificationEndDate 规则加 required:true(渲染星号,validator 豁免长期);删除 qualificationLongTerm 的 required 规则(长期有效不必填);勾长期后起止均 disabled(比驾驶证更严,驾驶证起仍可编辑)。⚠️ 后端需新增 qualification_start_date 字段否则起日期无法存取。 +- driver.vue 补充:驾驶证「有效期起」加 :disabled(长期=1 时禁用);驾驶证与从业资格证两个 validator 统一在「长期有效=1」时直接 callback() 放行(起止都不校验、不提示)。禁用不清空旧值,提交时保留原日期(后端以 longTerm 为准)。 +- contract-manage-change.vue「合同文件」批量下载按钮上移:标题与按钮合并进 .section-head(flex space-between 同排),与「其它附件/计费信息」分区一致;删除无引用的 .attachment-head 样式。 diff --git a/src/views/business/contract-manage-change.vue b/src/views/business/contract-manage-change.vue index 6e57471..5360a4d 100644 --- a/src/views/business/contract-manage-change.vue +++ b/src/views/business/contract-manage-change.vue @@ -30,8 +30,8 @@
-
合同文件
-
+
+
合同文件
批量下载
@@ -215,7 +215,6 @@ export default { .change-table { margin: 16px 0; } .ratio-tip { margin-bottom: 8px; color: #f56c6c; } .unit { margin-left: 8px; } -.attachment-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 12px; } .attachment-upload { display: flex; justify-content: flex-start; margin-top: 12px; } .attachment-upload .vehicle-attachment-upload { width: auto; } .attachment-upload .el-upload { display: inline-flex; } diff --git a/src/views/transportCapacity/driver.vue b/src/views/transportCapacity/driver.vue index cc21b73..40389ee 100644 --- a/src/views/transportCapacity/driver.vue +++ b/src/views/transportCapacity/driver.vue @@ -325,6 +325,7 @@ type="date" value-format="YYYY-MM-DD" placeholder="起" + :disabled="driverForm.drivingLicenseLongTerm === 1" @change="validateFormField('drivingLicenseEndDate')" /> - + - +
+ + +
- + ({ drivingLicenseBack: '', qualificationType: '', qualificationNo: '', + qualificationStartDate: '', qualificationEndDate: '', qualificationLongTerm: 0, qualificationFront: '', @@ -819,9 +831,8 @@ export default { { required: true, message: '请选择从业资格认证类型', trigger: 'change' }, ], qualificationNo: [{ required: true, message: '请输入资格证号', trigger: 'blur' }], - qualificationEndDate: [{ validator: this.validateQualificationEndDate, trigger: 'change' }], - qualificationLongTerm: [ - { required: true, message: '请选择从业资格证是否长期有效', trigger: 'change' }, + qualificationEndDate: [ + { required: true, validator: this.validateQualificationEndDate, trigger: 'change' }, ], driverType: [{ required: true, message: '请选择司机类型', trigger: 'change' }], mobile: [{ required: true, message: '请输入手机号', trigger: 'blur' }], @@ -1056,19 +1067,33 @@ export default { } }, validateDrivingLicenseEndDate(rule, value, callback) { + // 勾选长期有效:起止均已禁用,不再校验 + if (this.driverForm.drivingLicenseLongTerm === 1) { + callback(); + return; + } if (!this.driverForm.drivingLicenseStartDate) { callback(new Error('请选择驾驶证有效期起')); return; } - if (this.driverForm.drivingLicenseLongTerm !== 1 && !value) { + if (!value) { callback(new Error('请选择驾驶证有效期止')); return; } callback(); }, validateQualificationEndDate(rule, value, callback) { - if (this.driverForm.qualificationLongTerm !== 1 && !value) { - callback(new Error('请选择从业资格证有效期')); + // 勾选长期有效:起止均已禁用,不再校验 + if (this.driverForm.qualificationLongTerm === 1) { + callback(); + return; + } + if (!this.driverForm.qualificationStartDate) { + callback(new Error('请选择从业资格证有效期起')); + return; + } + if (!value) { + callback(new Error('请选择从业资格证有效期止')); return; } callback(); @@ -1580,6 +1605,7 @@ export default { birthday: this.normalizeBirthday(this.driverForm.birthday), drivingLicenseStartDate: this.normalizeBirthday(this.driverForm.drivingLicenseStartDate), drivingLicenseEndDate: this.normalizeBirthday(this.driverForm.drivingLicenseEndDate), + qualificationStartDate: this.normalizeBirthday(this.driverForm.qualificationStartDate), qualificationEndDate: this.normalizeBirthday(this.driverForm.qualificationEndDate), qualificationNo: this.driverForm.qualificationNo || this.driverForm.idCardNo, posts: this.driverForm.postList.join(','), diff --git a/src/views/transportCapacity/vehicle.vue b/src/views/transportCapacity/vehicle.vue index 751f7a8..f4cd7d5 100644 --- a/src/views/transportCapacity/vehicle.vue +++ b/src/views/transportCapacity/vehicle.vue @@ -129,13 +129,6 @@ > - - - - {{ auditValue('organizationName') }} - - - @@ -147,43 +140,22 @@ {{ auditValue('vehicleType') }} - - - - - {{ auditValue('businessRelation') }} - - - - - {{ auditValue('energyType') }} - - - - - - {{ auditValue('compulsoryScrapDate') }} - - - - - - - - - - - {{ auditValue('outerLength') }} - - - - - {{ auditValue('outerWidth') }} - - - - - {{ auditValue('outerHeight') }} + + +
+
+ + {{ auditValue('outerLength') }} +
+
+ + {{ auditValue('outerWidth') }} +
+
+ + {{ auditValue('outerHeight') }} +
+
@@ -198,14 +170,85 @@ {{ auditValue('tractionMassKg') }}
+ + + {{ auditValue('businessRelation') }} + + + + + {{ auditValue('energyType') }} + + + + + + + + {{ auditValue('compulsoryScrapDate') }} + + + + + + {{ auditValue('customsRecordNo') }} + + + + + + {{ auditValue('organizationName') }} + + + + + + {{ auditValue('useDepartment') }} + + - - {{ auditValue('customsRecordNo') }} + + + {{ auditValue('drivingLicenseEndDate') }} + + + + + + + {{ auditValue('roadTransportCertNo') }} + + + + + + + {{ auditValue('roadTransportCertEndDate') }} + + + + + + + {{ auditValue('annualReviewEndDate') }} + + + + + + + + {{ auditValue('registrationNo') }} + + + + + {{ auditValue('registrationDate') }} @@ -222,20 +265,6 @@ - - - - {{ auditValue('drivingLicenseEndDate') }} - - - - - - - {{ auditValue('roadTransportCertNo') }} - - - @@ -244,34 +273,6 @@ - - - - - {{ auditValue('roadTransportCertEndDate') }} - - - - - - - {{ auditValue('annualReviewEndDate') }} - - - - - - {{ auditValue('registrationNo') }} - - - - - - - {{ auditValue('registrationDate') }} - - - @@ -866,7 +867,7 @@ export default { ], businessRelationOptions: ['自有', '管理挂靠', '业务合作'], energyTypeOptions: ['柴油', '汽油', '新能源', '天然气'], - formRules: { + baseRules: { organizationName: [{ required: true, message: '请选择所属组织', trigger: 'change' }], plateNo: [ { required: true, message: '请输入车牌号', trigger: 'change' }, @@ -877,9 +878,6 @@ export default { businessRelation: [{ required: true, message: '请选择业务关系', trigger: 'change' }], energyType: [{ required: true, message: '请选择能源类型', trigger: 'change' }], drivingLicenseNo: [{ required: true, message: '请输入行驶证档案编号', trigger: 'blur' }], - drivingLicenseEndDate: [ - { validator: this.validateDrivingLicenseEndDate, trigger: 'change' }, - ], roadTransportCertNo: [{ required: true, message: '请输入道路运输证号', trigger: 'blur' }], roadTransportCertEndDate: [ { validator: this.validateRoadTransportCertEndDate, trigger: 'change' }, @@ -891,6 +889,16 @@ export default { }, computed: { ...mapGetters(['permission', 'userInfo']), + // 行驶证有效期:用 required 规则渲染必填星号;勾选「长期有效」后免填,星号同步消失 + formRules() { + return { + ...this.baseRules, + drivingLicenseEndDate: + this.vehicleForm.drivingLicenseLongTerm === 1 + ? [] + : [{ required: true, message: '请选择行驶证有效期', trigger: 'change' }], + }; + }, // 所属组织级联:表单存组织名称,级联控件用 id 路径,两者在此双向转换 organizationCascaderValue: { get() { @@ -1001,17 +1009,6 @@ export default { } this.$refs.vehicleForm?.validateField(dateProp); }, - validateDrivingLicenseEndDate(rule, value, callback) { - if (this.vehicleForm.drivingLicenseLongTerm === 1 && !value) { - callback(); - return; - } - if (!value) { - callback(new Error('请选择行驶证有效期')); - return; - } - callback(); - }, validateRoadTransportCertEndDate(rule, value, callback) { if (this.vehicleForm.roadTransportCertLongTerm === 1 && !value) { callback(); @@ -1638,6 +1635,26 @@ export default { word-break: break-all; } + // 外廓尺寸长/宽/高组合,排版复用编辑弹窗的 dimension-group + .dimension-group { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + align-items: center; + } + + .dimension-group__item { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; + } + + .dimension-group__label { + flex-shrink: 0; + color: #303133; + } + &__reason { margin-top: 12px; }