From 197211517355ed8122258d7f0cc4c86647259967 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 15:37:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(transportCapacity):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=BD=A6=E8=BE=86=E4=B8=8E=E5=8F=B8=E6=9C=BA=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E5=B9=B6=E6=96=B0=E5=A2=9E=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 车辆新增弹窗:所有组织移至基础车辆信息区末尾,新增使用部门字段,使用部门复用部门下拉 - 车牌号三段合并为整体输入框,优化样式为flex布局,去除多余边框及阴影,统一视觉 - 长期有效勾选时清空对应日期且禁用输入,新增handleLongTermChange方法,表单校验支持长期有效跳过必填 - 司机弹窗基础身份信息新增placeholder,调整布局,基础身份三列保持不变,其他信息行按需求拆分重排为一致三列 - 后端新增use_department字段,相关mapper、service及校验同步更新,新增增量迁移脚本支持 - 车辆表单相关输入控件宽度统一调整为6列布局,保持与其它区块一致,提升整体UI协调性 - 移除车辆车牌号拆分相关字段及逻辑,车牌号统一管理为单个字段,简化处理流程 - 代码中新增校验规则validateDrivingLicenseEndDate及validateRoadTransportCertEndDate,支持长期有效逻辑 - 优化图片上传区和证件信息区表单字段排列,提升表单整体易用性与规范性 --- .workbuddy/memory/2026-09-09.md | 29 ++ src/views/transportCapacity/driver.vue | 84 ++++-- src/views/transportCapacity/vehicle.vue | 352 +++++++++++++----------- 3 files changed, 279 insertions(+), 186 deletions(-) diff --git a/.workbuddy/memory/2026-09-09.md b/.workbuddy/memory/2026-09-09.md index 05c0cec..8c736c1 100644 --- a/.workbuddy/memory/2026-09-09.md +++ b/.workbuddy/memory/2026-09-09.md @@ -83,3 +83,32 @@ 3. `loadSettlementDictionaries` 的 `Promise.all` 追加 `getBizDictionary({ code: 'contractCategory' })`,映射填充后**条件覆盖** `contractCategory` 列 dicData(仅非空时)。 - 列表页列显示/搜索下拉、详情页(detailValue 已有 `prop==='contractCategory'` 分支走 displayStatus)均因 column.dicData 覆盖而自动跟随业务字典。 - 注意:`config.defaultForm.contractCategory: '客户合同'`(option/contract-manage.js)为硬编码中文默认值,若业务字典 dictKey 非中文需同步调整。 + +## 车辆新增弹窗:所有组织移位 + 使用部门 + 长期有效清空(vehicle.vue + 后端) +- 需求(transportCapacity/vehicle):①所有组织移到「基础车辆信息」区末尾;②新增「使用部门」字段(后端 transport_vehicle 无该字段,需加);③车牌号三段(省/号码/颜色)包成整体输入框+减宽;④勾选「长期有效」清空对应日期且不可编辑。 +- 用户确认:所有组织+使用部门放「基础车辆信息」区末尾;使用部门用部门下拉(复用 getDeptTree→organizationOptions,存部门名,仅部门名非级联);车牌号包成整体输入框+减宽;长期有效 4 组全部统一清空(强制报废/行驶证/道路运输证/年审)。 +- 前端(vehicle.vue): + 1. emptyForm 加 `useDepartment: ''`。 + 2. 删「基础车辆信息」首行的「所有组织」(原 span24),在区末新增一行:`使用部门`(span8, el-select+organizationOptions, 存 rawLabel) + `所有组织`(span8, el-cascader)。organizationOptions 由 initDeptTree 填充。 + 3. `.plate-group` 由 grid(112px 1fr 112px) 改为 flex 整体输入框:外层 border+radius+focus-within 变化;内部 el-select/el-input 去 box-shadow、无边框,第一/最后 select flex 0 0 30%、中间 input flex 1,子项间用 `::before` 竖线分隔。 + 4. 4 组 date-picker 加 `:disabled="xxxLongTerm === 1"`(行驶证/道路运输证原缺,补上),checkbox 加 `@change="handleLongTermChange(日期prop, longterm prop)"`;新增方法 handleLongTermChange(勾选时清空日期并 validateField)。 + 5. formRules:drivingLicenseEndDate / roadTransportCertEndDate 由 required 改为 validator(新增 validateDrivingLicenseEndDate / validateRoadTransportCertEndDate,longTerm===1 时跳过必填),annualReview 原 validator 已支持。 +- 后端(tms-erp-api-ws,新增 use_department 列): + - `TransportVehicle.java` 加 `private String useDepartment`。 + - `blade_transport_vehicle.sql` 建表加 `use_department varchar(50)`。 + - `TransportVehicleExcel.java` 加 `使用部门` 列。 + - `TransportVehicleMapper.xml` resultMap + BaseColumn + QueryCondition(useDepartment LIKE) 各加。 + - `TransportVehicleServiceImpl.prepare()` trim useDepartment;validate() 加长度≤50 校验。 + - 新增增量迁移 `doc/sql/transport/blade_transport_vehicle_use_department_patch_20260909.sql`(ALTER ADD use_department AFTER organization_name)。 +- 注意:VO 继承 entity 无需改;Wrapper BeanUtil 同名透传。已上线库须执行 patch SQL(建表脚本是 DROP+CREATE,勿直接跑)。 +- 后续补充(vehicle.vue「车辆资质图片」区输入框对齐):第一行原 span `6/8/10` 不等宽(行驶证档案编号 6 / 行驶证有效期 8 / 道路运输证号 10)导致输入框宽度不齐,统一改为 `8/8/8`,与下方各行 span=8 一致。仅改 2 处 span,无逻辑改动。 + +## 司机弹窗:补 placeholder + 每行统一 3 列(transportCapacity/driver.vue) +- 需求:新增/编辑司机弹窗 ①输入框无提示文案;②基础身份信息 3 列,其它 4 列 / 6 列行不统一。 +- 改动(仅 1819 行 driver.vue 的 126-540 行 `` 模板,script/style 不动): + 1. **基础身份信息**:行结构不动,7 个 el-form-item 控件补 placeholder(司机姓名/身份证号/出生年月/性别/民族/学历/详细地址)。住址已有「请选择省市区」、驾驶车辆已有「请输入或选择车辆」,不动。 + 2. **驾驶证信息**:第一行 4 列(:span=6)拆为两行 — 行 1(准驾车型 / 档案编号 / 有效期 date-range,:span=8)+ 行 2(长期有效,:span=8)。起/止 placeholder 保留简短「起」「止」,符合主人 1.B 偏好(保留原 date-range 二联结构,不改 daterange)。 + 3. **从业资格证信息**:第一行 4 列拆为两行 — 行 1(从业资格认证类型 / 资格证号 / 有效期,:span=8)+ 行 2(长期有效,:span=8)。资格证号 placeholder 保留「默认身份证号」不动。 + 4. **司机联系信息**:一行 6 列拆为两行 — 行 1(司机类型 / 手机号 / 紧急联系人姓名,:span=8)+ 行 2(紧急联系人手机号 / 与联系人关系 / 所属组织,:span=8)。所属组织已有 placeholder,不动。 +- 决策点(主人确认):1.B(保留原 date-range 二联 + 第三列留空后拆行的方案);2 保留;3.A(驾驶证主页/副页、封面页/内容页两组上传图仍 :span=12,与占整行宽的原貌一致)。 +- 校验:node 脚本统计 4 个 section-card / 13 个 el-row / 31 个 el-col / 24 个 el-form-item,全平衡。改动只在 driver.vue 一文件,~25 处 Edit 调用。 diff --git a/src/views/transportCapacity/driver.vue b/src/views/transportCapacity/driver.vue index 708249e..9f9e9a7 100644 --- a/src/views/transportCapacity/driver.vue +++ b/src/views/transportCapacity/driver.vue @@ -125,43 +125,50 @@ > - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -238,7 +255,7 @@ - + - + - + - + @@ -320,6 +342,8 @@ + + + + - + @@ -453,7 +481,11 @@ - + @@ -461,13 +493,20 @@ + + - + @@ -478,6 +517,7 @@ filterable allow-create default-first-option + placeholder="请选择与联系人关系" > - + {{ auditValue('plateNo') }} - + {{ auditValue('plateColor') }} - + {{ auditValue('vehicleType') }} - + {{ auditValue('businessRelation') }} - + {{ auditValue('energyType') }} - + {{ auditValue('compulsoryScrapDate') }} @@ -176,29 +176,29 @@ - + {{ auditValue('outerLength') }} - + {{ auditValue('outerWidth') }} - + {{ auditValue('outerHeight') }} - + {{ auditValue('approvedLoadKg') }} - + {{ auditValue('tractionMassKg') }} @@ -208,17 +208,17 @@ - + {{ auditValue('customsRecordNo') }} - + {{ auditValue('drivingLicenseNo') }} - + {{ auditValue('drivingLicenseStartDate') }} @@ -227,21 +227,21 @@ - + {{ auditValue('drivingLicenseEndDate') }} - + {{ auditValue('roadTransportCertNo') }} - + {{ auditValue('roadTransportCertStartDate') }} @@ -250,28 +250,28 @@ - + {{ auditValue('roadTransportCertEndDate') }} - + {{ auditValue('annualReviewEndDate') }} - + {{ auditValue('registrationNo') }} - + {{ auditValue('registrationDate') }} @@ -288,7 +288,7 @@ - + - + - + - + - + - + - - - - - - - -
- - - - - - - -
+
@@ -462,7 +423,7 @@
- +
@@ -494,7 +455,7 @@ - + - + - + - + - +
长期有效
- +
+ + + + + + + + + + + + + + @@ -577,50 +570,54 @@ - +
长期有效
- + - +
长期有效
- +
长期有效 @@ -641,12 +639,12 @@ - + - + - + - + - + - + - + - + ({ id: '', organizationName: '', - plateProvince: '', - plateNoBody: '', + useDepartment: '', plateNo: '', plateColor: '', vehicleType: '', @@ -823,44 +820,6 @@ const emptyForm = () => ({ status: 1, }); -const plateProvinceOptions = [ - '京', - '津', - '沪', - '渝', - '冀', - '豫', - '云', - '辽', - '黑', - '湘', - '皖', - '鲁', - '新', - '苏', - '浙', - '赣', - '鄂', - '桂', - '甘', - '晋', - '蒙', - '陕', - '吉', - '闽', - '贵', - '粤', - '青', - '藏', - '川', - '宁', - '琼', - '港', - '澳', -].map(item => ({ label: item, value: item })); - -const plateColorOptions = ['黄牌', '蓝牌', '绿牌'].map(item => ({ label: item, value: item })); - export default { components: { ImageUploadField, @@ -904,8 +863,6 @@ export default { vehicleCertificateUploads: {}, uploadHeaders: getUploadHeaders(), organizationOptions: [], - plateProvinceOptions, - plateColorOptions, vehicleTypeOptions: [ { label: '高栏车', value: '高栏' }, { label: '低栏车', value: '低栏' }, @@ -928,11 +885,11 @@ export default { energyType: [{ required: true, message: '请选择能源类型', trigger: 'change' }], drivingLicenseNo: [{ required: true, message: '请输入行驶证档案编号', trigger: 'blur' }], drivingLicenseEndDate: [ - { required: true, message: '请选择行驶证有效期', trigger: 'change' }, + { validator: this.validateDrivingLicenseEndDate, trigger: 'change' }, ], roadTransportCertNo: [{ required: true, message: '请输入道路运输证号', trigger: 'blur' }], roadTransportCertEndDate: [ - { required: true, message: '请选择道路运输证有效期', trigger: 'change' }, + { validator: this.validateRoadTransportCertEndDate, trigger: 'change' }, ], annualReviewEndDate: [{ validator: this.validateAnnualReviewEndDate, trigger: 'change' }], registrationNo: [{ required: true, message: '请输入机动车登记编号', trigger: 'blur' }], @@ -1021,19 +978,20 @@ export default { return String(value).replace(/\D/g, ''); }, validatePlateNo(rule, value, callback) { - const plateProvince = String(this.vehicleForm.plateProvince || '').trim(); - const plateNoBody = String(this.vehicleForm.plateNoBody || '') + const plateNo = String(value || '') .trim() .toUpperCase(); - const plateColor = String(this.vehicleForm.plateColor || '').trim(); - if (!plateProvince || !plateNoBody || !plateColor) { - callback(new Error('请完整填写车牌号')); + if (!plateNo) { + callback(new Error('请输入车牌号')); return; } - if (!/^[A-Z][A-Z0-9挂学警港澳]{5,6}$/.test(plateNoBody)) { - callback(new Error('请输入标准车牌号')); + if (!/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼港澳]{1}[A-Z][A-Z0-9挂学警港澳]{5,6}$/.test(plateNo)) { + callback(new Error('请输入标准车牌号(如:京A12345)')); return; } + if (this.vehicleForm.plateNo !== plateNo) { + this.vehicleForm.plateNo = plateNo; + } callback(); }, validateAnnualReviewEndDate(rule, value, callback) { @@ -1043,6 +1001,35 @@ export default { } callback(); }, + // 长期有效勾选:勾选时清空对应日期(不可编辑由 date-picker :disabled 控制),取消勾选后可重新填报 + handleLongTermChange(dateProp, longTermProp) { + if (this.vehicleForm[longTermProp] === 1) { + this.vehicleForm[dateProp] = ''; + } + 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(); + return; + } + if (!value) { + callback(new Error('请选择道路运输证有效期')); + return; + } + callback(); + }, openVehicle(row, readonly = false) { this.readonly = readonly; if (!row?.id) { @@ -1420,28 +1407,16 @@ export default { this.syncPlateNo(); }, syncPlateNo(validate = true) { - const plateProvince = String(this.vehicleForm.plateProvince || '').trim(); - const plateNoBody = String(this.vehicleForm.plateNoBody || '') - .trim() + const plateNo = String(this.vehicleForm.plateNo || '') + .replace(/\s/g, '') .toUpperCase(); - const plateColor = String(this.vehicleForm.plateColor || '').trim(); - this.vehicleForm.plateNoBody = plateNoBody; - this.vehicleForm.plateNo = - plateProvince && plateNoBody ? `${plateProvince}${plateNoBody}` : ''; - this.vehicleForm.plateColor = plateColor; + this.vehicleForm.plateNo = plateNo; if (validate) { this.$refs.vehicleForm?.validateField('plateNo'); } }, splitPlateNo() { - const plateNo = String(this.vehicleForm.plateNo || '').trim(); - if (!plateNo) { - this.vehicleForm.plateProvince = ''; - this.vehicleForm.plateNoBody = ''; - return; - } - this.vehicleForm.plateProvince = plateNo.slice(0, 1); - this.vehicleForm.plateNoBody = plateNo.slice(1).toUpperCase(); + // 车牌号已统一为单一 input,无需拆分 }, handleSubmit() { this.syncPlateNo(); @@ -1681,10 +1656,60 @@ export default { } .plate-group { - display: grid; - grid-template-columns: 112px minmax(0, 1fr) 112px; - gap: 8px; + display: flex; align-items: center; + overflow: hidden; + border: 1px solid #dcdfe6; + border-radius: 4px; + background: #fff; + transition: border-color 0.2s; + + &:hover { + border-color: #c0c4cc; + } + + &:focus-within { + border-color: #409eff; + } + + // 三个子控件:去掉各自边框,整体形成一个输入框 + :deep(.el-select), + :deep(.el-input) { + position: relative; + flex: 1; + min-width: 0; + height: 32px; + } + + :deep(.el-select:first-child) { + flex: 0 0 12%; + } + + :deep(.el-select:last-child) { + flex: 0 0 18%; + } + + :deep(.el-input__wrapper), + :deep(.el-select__wrapper) { + box-shadow: none !important; + border-radius: 0; + padding: 0 8px; + } + + // 子项之间用竖线分隔,视觉上是一个整体 + :deep(.el-select + .el-select), + :deep(.el-select + .el-input), + :deep(.el-input + .el-select) { + &::before { + content: ''; + position: absolute; + left: 0; + top: 6px; + bottom: 6px; + width: 1px; + background: #e4e7ed; + } + } } .dimension-group { @@ -1704,7 +1729,6 @@ export default { .dimension-group__label { flex-shrink: 0; color: #303133; - font-weight: 500; } .date-with-flag {