Files
tms-erp-web/.workbuddy/memory/2026-09-09.md
T
gxwebsoft 1972115173 feat(transportCapacity): 优化车辆与司机弹窗布局并新增字段支持
- 车辆新增弹窗:所有组织移至基础车辆信息区末尾,新增使用部门字段,使用部门复用部门下拉
- 车牌号三段合并为整体输入框,优化样式为flex布局,去除多余边框及阴影,统一视觉
- 长期有效勾选时清空对应日期且禁用输入,新增handleLongTermChange方法,表单校验支持长期有效跳过必填
- 司机弹窗基础身份信息新增placeholder,调整布局,基础身份三列保持不变,其他信息行按需求拆分重排为一致三列
- 后端新增use_department字段,相关mapper、service及校验同步更新,新增增量迁移脚本支持
- 车辆表单相关输入控件宽度统一调整为6列布局,保持与其它区块一致,提升整体UI协调性
- 移除车辆车牌号拆分相关字段及逻辑,车牌号统一管理为单个字段,简化处理流程
- 代码中新增校验规则validateDrivingLicenseEndDate及validateRoadTransportCertEndDate,支持长期有效逻辑
- 优化图片上传区和证件信息区表单字段排列,提升表单整体易用性与规范性
2026-09-09 15:37:40 +08:00

115 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 付款比例设置提示改为 tooltipcontract-manage / contract-manage-change
- 需求:将「付款比例设置」区块原有的红色文字提示改为标题右侧的 `?` 图标悬停提示。
- 改动:编辑弹窗、详情弹窗、合同变更页三处标题后添加 `el-tooltip` + `el-icon-question-filled`,content 为「非必填;配置付款比例时,合计必须等于100%。」;同时移除 contract-manage.vue 中原 `.contract-manage-form__tip` 红色提示文字及对应样式。
## 必填星号与 label 首行齐平(全局)
- 根因:`element-ui.scss``.el-form-item--label-right .el-form-item__label { align-items:center }` 使 inline-flex label 的星号 `::before`(独立 flex 子项)在多行折行时被垂直居中。
- 修复:label 改 `align-self:center`(整体仍随行垂直居中)+ `align-items:flex-start`(星号/文字首行齐平),覆盖 label-right/left/top 三种位置;旧 inline-block 注释已修正。
- 影响页面:project-apply 独立表单页等所有多行 label 场景(弹窗内 `white-space:nowrap` 不受影响)。
## 必填星号首行对齐:改用 align-items: normalstretch 方案)
- 最终写法(`src/styles/element-ui.scss`):`.is-required .el-form-item__label { align-self:center; align-items:normal; }` + `::before { display:inline-block; height:auto; line-height:inherit; margin-right:4px }`
- 原理:stretch 让星号盒子在「换行时」被拉伸到 label 全高、内容从顶部排布 → 贴首行;单行时盒子=一行高,视觉不变(比 flex-start 更贴合「只换行才生效」)。
- 前提:::before 高度必须 auto 且继承行高;label 不能是 固定 height + 等高 line-height,否则退化成居中,需 JS 判行数加 class。
## 合同变更页(contract-manage-change.vue
- 「其它附件」上传按钮改为 `type="primary" plain icon="el-icon-upload"`,与「变更材料」区 vehicle-attachment-upload 内置按钮一致。
- 分区标题必填星号:`.dialog-section-title.is-required::after { content:'*'; color:#f56c6c }``::before` 已被蓝色竖条占用,星号走 `::after`)。
- 再次变更逻辑:`load()` 里 form 强制重置 `changeContent/changeReason/changeAttachmentsJson = ''``changeMaterials = []`(不带上一次内容);新增 `mergeChangeAttachments()` 把上一次的 `changeAttachmentsJson` 归集进 `attachments`(其它附件),按 url/名去重,数字 size 转格式化文本,提交时随 attachmentsJson 持久化。
## 合同变更记录对齐客商变更记录(contract-manage.vue
- 编辑页与详情弹窗的两处「变更记录」表格新增「变更内容」列:`formatContractChangeContent(row)` 复用 `buildDetailChangeRecordRows` 生成「字段:变更前:x → 变更后:y」摘要,单行省略 + `el-tooltip` 全量悬浮(样式 `.contract-change-record-content-cell/-tooltip` 照搬客商 `change-record-content-*`)。
- 编辑页操作列由单个「流程」改为「详情 + 流程」(`openDetailChangeRecord` + `openFlow`,宽度 120→150);详情弹窗表格「查看详情」改「详情」与客商一致。
- 值格式化增强:`billingPlanJson`→方案名(默认)列表、`paymentRatioJson`→「第N笔 xx%」、`settlementRuleJson/preSettlementConfigJson/formalSettlementConfigJson`→可读摘要(自动生成开关/结算类型/周期类型/截单日/周期天数,含预结算+正式结算双段)。
- `buildDetailChangeRecordRows` 过滤条件补「前后都为空则跳过」(原来只比 JSON 字符串,'' 与 null 会漏)。
## 星号方案补丁(关键)
- EP 的 `.el-form-item__label` 写死 `height:32px; line-height:32px`(项目只覆盖了 line-height:14px),导致 stretch 方案文字顶到 32px 盒子顶部、单行不居中。
- 修复:`.is-required .el-form-item__label { height:auto; align-self:center; align-items:normal }`——height:auto 收缩到内容高 + align-self:center 行内居中 + normal(stretch) 仅换行时星号贴首行。
## 车辆认证审核弹窗重构(transportCapacity/vehicle.vue
- 背景:用户反馈「样式不统一、内容不全」。根因是审核弹窗用 `<el-descriptions :column="3" border>`(大白表 + 居中 label),与同页编辑弹窗的 `<section-card>` 白卡分组风格不一致。
- 改造:弹窗主体改为 4 个 `section-card` 分组 —— 基础信息 / 尺寸重量 / 证件信息 / 证件图片;内部 `el-form label-position="right" label-width="auto"` + `el-row/el-col`3 列 `:span="8"`,所属组织与备注占 `:span="24"`)。
- 内容补全:新增「证件图片」分组,6 张证件照用 `<image-upload-field readonly large class-prefix="vehicle">` 只读展示(可点击放大);证件图片尺寸 240×151 复用已有全局 `:deep(.vehicle-uploader--large)` 规则,无需新写。
- label 单位统一为中文全角括号:`外廓长度(毫米)` / `核定载质量(KG`(原为半角 `外廓长度(mm)`)。
- 方法重构:`formatAuditValue(item)``auditValue(prop)`,签名更简洁;新增 longTermMap,对 drivingLicenseEndDate / roadTransportCertEndDate / annualReviewEndDate / compulsoryScrapDate 在勾选长期有效时返回「长期有效」,避免与未填写的「-」混淆(与列表页 formatEndDate 行为一致)。
- 删除已无引用的 `auditDetailItems` computed。
## 全站弹窗标题补 4px 主色竖条(全局 element-ui.scss
- 发现:`.el-dialog__title` 全局只配了 `inline-flex + gap:8px`**没有竖条**(竖条此前只在 `.dialog-section-title::before`),导致全站 el-dialog 标题都不带竖条,不符合 AGENTS.md 4.8。
- 修复:新增 `.el-dialog__title:not(:empty)::before { width:4px; height:16px; border-radius:2px; background:var(--el-color-primary) }`
- 注意:必须加 `:not(:empty)`,否则无标题弹窗会出现孤立蓝条。
- customer-archive.vue 评分详情弹窗:将「临时额度申请使用期限」区间行(span=12 + 至 连接)拆分为两个 span=6 独立字段「临时申请额度有效期起 / 止」,字段名 tempCreditStartDate/End 不变,删除废弃样式 .score-detail-form__range。
- temporary-credit-limit 文案调整:option 增加 addTitle/editTitle/viewTitle=「新增/编辑/查看临时额度申请」(覆盖 crud-dialog-title mixin 按菜单名注入的「临时额度管理」);remark label 改「临时额度信息」(hide:true 无表格副作用,rules 同步);projectName 表单 label 用 `#projectName-label` 插槽改「项目额度信息」,列 label 保持「项目名称」不动表格列头/搜索。Avue 支持-{prop}-label / -header / -search 插槽分离表单/表头/搜索文案。
- temporary-credit-limit「申请有效期至」增加「必须晚于当前日期」校验:common.js 新增通用 `futureDateRule(label)`trigger: ['change','blur'],空值/非法值放行,按 0 点比较,当天也算过期),temporary-credit-limit.js 的 validUntil rules 追加该规则。已验证 Element Plus 通用 picker 在选中日期时调用 formItem.validate('change'),故选择即刻提示;form.validate() 不带 trigger 时会跑全部规则,提交仍拦截。
- temporary-credit-limit 搜索占位文案统一:createCrudOption(withSearchPlaceholders([...])),搜索栏 placeholder 变为「请输入/请选择」不带字段名,与 waybill-manage / transport-plan / shipping-template 同一模式。
- temporary-credit-limit 弹窗表单 placeholder 统一为「请输入/请选择」不带字段名:option 各列加 placeholderprojectCode/undertakeDeptName/projectFundLimit/usedFundLimit/remainingFundLimit/remark=请输入,validUntil=请选择),视图 formslot 自定义控件(projectName select、applyLimit inputplaceholder 同步改。
## 【项目管理】列表增加「项目资金使用预警」(project-apply
- 需求:列表新增「资金使用风险」列,高风险红色、中风险黄色;列表头部增加「资金使用风险」快速筛选标签(高风险(数)/中风险(数)),点击筛选。规则 tooltip:中风险≥80%、高风险≥90%,使用率=已使用资金/项目资金使用额度×100%。
- 前端(已落地,src/views/business/project-apply.vue + src/option/business/project-apply.js + src/api/business/project-apply.js):
- option/project-apply.js 新增列 `fundUseRisk`(slot:true, hide 列表显示) + 导出 `fundUseRiskOptions`(high/medium/none) 与 `fundUseRiskThreshold`{high:90, medium:80}。
- view 新增 `#header` 插槽:`el-check-tag` 快速筛选(复用 contract-manage 到期标签交互),带数量(fundRiskStats[statKey])与 `?` tooltip 规则;新增 `#fundUseRisk` 插槽渲染彩色 `el-tag`high→type=danger 红,medium→type=warning 黄,无→"-")。
- data 加 fundRiskScope/fundRiskStats{high,medium,none}/fundRiskTagOptionsonLoad 追加 `fundUseRisk` 筛选参数 + 成功后 refreshFundRiskStats;新增 changeFundRiskScope(再次点击取消)、refreshFundRiskStatssearchReset 清空风险筛选。
- api 新增 `getFundRiskStats` → GET /blade-transport/project-apply/fund-risk-stats。
- 后端契约(未改,待确认数据来源):ProjectApplyVO 补齐 `fundUseRisk`(high/medium/none)、`fundUseRiskName``fundUseRate``usedFundLimit`/`remainingFundLimit`;列表 selectProjectApplyPage 填充每行风险 + buildQuery 支持 `fundUseRisk` 过滤;新增 `/fund-risk-stats` 返回 {high,medium,none}。
- ⚠️ 关键阻塞:系统里项目与任何费用表(运输计划/运单/账单/客商)均无关联字段,`usedFundLimit`(已使用资金) 无真实取数来源;临时额度模块的 project-apply/list 返回里 usedFundLimit 实际为空。需业务方确认「已使用资金」口径后才能算风险等级,否则列表风险列全空、统计为 0。
## 合同文件「批量下载」按钮与标题同排(contract-manage.vue 内联 AttachmentSection
- 需求:编辑页「合同文件」分组里「批量下载」按钮目前独立一行、靠右偏上,高度与标题区错位;要放到「合同文件」标题右侧同排、垂直居中。
- 修复:`const AttachmentSection = defineComponent(...)` 内联组件 render() —— 原结构是 `div.dialog-section-title`(标题) 与 `div.contract-manage-form__attachment-head`(批量下载按钮) 两个并列 div;改为把标题与按钮放进同一个 `contract-manage-form__attachment-head` flex 容器(标题左、按钮右)。
- 样式:`:deep(.contract-manage-form__attachment-head)``justify-content:flex-end` 改为 `space-between` + `align-items:center`,并 `.dialog-section-title { margin-bottom:0 }` 抵消标题自身 20px 下边距(2674 行 `:deep(.dialog-section-title)` 会命中子组件渲染的标题)。
- 注意:AttachmentSection 用 render 函数产出 DOM,不带当前组件 scoped data 属性,因此样式必须走 `:deep()`scoped 的 `&__billing-head, &__attachment-head`(2723) 只作用于当前组件模板内(计费信息),对子组件 DOM 无效。
- 影响:4 处使用(编辑/详情 × 合同文件/其它附件)布局统一变为「标题 + 批量下载」同排。
- 主人二次反馈「下面的其它附件也一样」——确认 L463(编辑/其它附件 description) / L765(详情/其它附件 description+readonly) 与 L313(编辑/合同文件) / L671(详情/合同文件) 都走同一份 render+样式,无需新代码;指挥浏览器 Cmd+Shift+R 硬刷即可看到效果(render 函数组件的 :deep() 样式改 HMR 经常不传播)。
## 合同格式下拉改读业务字典 contractFormatcontract-manage.vue
- 需求:新增/编辑合同管理页「合同格式」下拉由硬编码改为读取业务字典 `contractFormat`
- 原实现:`option/business/contract-manage.js``contractFormat``dicData` 硬编码 `[{label:'电子合同',value:'电子合同'},{label:'纸质合同',value:'纸质合同'}]`view 里 `contractFormatOptions` computed 直接 `columnOptions('contractFormat')` 读 column.dicData。
- 修复(4 处):
1. data 加 `contractFormatDictOptions: []`(与 settlementModeDictOptions 并列)。
2. computed `contractFormatOptions` 改为优先 `contractFormatDictOptions`,为空回退 `columnOptions('contractFormat')`(保留静态兜底)。
3. `loadSettlementDictionaries``Promise.all` 追加 `getBizDictionary({ code: 'contractFormat' })`,用 `records()` 映射 `{label:dictValue,value:dictKey}` 填充 `contractFormatDictOptions`;再**条件覆盖** column.dicData(仅当字典非空时),避免字典未配时清掉静态兜底。
4. `detailValue` 的字典映射分支加入 `prop === 'contractFormat'`,详情页「合同格式」也走 `displayStatus` 显示 label。
- 后端契约:`getBizDictionary``GET /blade-system/dict-biz/dictionary?code=contractFormat`,返回 `List<DictBiz>{code,dictKey,dictValue,remark}`DictBizController#dictionary 按 code 精确匹配)。字典 code 按用户口述用驼峰 `contractFormat`(现有 settle_method 为下划线,若后台实际是 `contract_format` 需调整 code)。
- 参考模式:与 `settlementMode`settle_method)完全一致。
## 合同类别 contractCategory 也读业务字典(contract-manage.vue,续上)
- 需求:模板里 label 实为「合同类型」(prop `contractCategory`),下拉由硬编码 `common.js#contractCategoryOptions`(客户合同/承运商合同/补充协议,value 中文)改为读业务字典 `contractCategory`
- 修复(3 处,与 contractFormat 同模式):
1. data 加 `contractCategoryDictOptions: []`
2. computed `contractCategoryOptions` 改为优先 `contractCategoryDictOptions`,空回退 `columnOptions('contractCategory')`(静态兜底)。
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. formRulesdrivingLicenseEndDate / roadTransportCertEndDate 由 required 改为 validator(新增 validateDrivingLicenseEndDate / validateRoadTransportCertEndDatelongTerm===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 useDepartmentvalidate() 加长度≤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 行 `<driver-dialog>` 模板,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 调用。