diff --git a/.workbuddy/memory/2026-09-09.md b/.workbuddy/memory/2026-09-09.md index 95b4d95..c45e331 100644 --- a/.workbuddy/memory/2026-09-09.md +++ b/.workbuddy/memory/2026-09-09.md @@ -150,6 +150,7 @@ - 注意:此前日志记录的「3 列 span=8」方案已被后续改动覆盖为 span=6,本次以当前文件实际状态为准。 ## 客商档案:客商类型→客商分类 + 新增客商类型(customer-archive.vue) +- ⚠️ 补救(17:34):data 里的 `customerKindOptions`/`customerKindMap` 定义一度丢失(模板 v-for 空 → 下拉显示「无数据」,主人截图反馈),已补回 data(customerTypeOptions 之后)。其余 8 处改动经 grep 确认完好。 - 需求:原「客商类型」(prop `customerType`,字典 customer_type:客户/承运商,多选)改名「客商分类」;另新增「客商类型」字段,取值为 外部客商 / 内部组织。 - 约定:prop `customerType` 不动(其它页面 loading-manage / dept / business-crud-page 都以 `customerType:'承运商'` 作为后端查询参数),只改中文标签。 - 新增字段 prop = **`customerKind`**(前端自定义命名,后端尚无对应字段,需后端在客商表加列并透传),值 `external`(外部客商) / `internal`(内部组织),单选下拉,默认 `external`。 @@ -168,3 +169,37 @@ - 症状:driver.vue 司机弹窗「驾驶证主页/副页」「封面页/内容页」等证件上传项(el-form-item 内容高 151px)label 文字贴顶,普通 32px 控件行看不出来。 - 根因:`archive-form` class 被 driver / vehicle / ship / credit-score-quantification / loading-manage / waybill-import-dialog 等 8+ 页面复用,但「label 与控件垂直居中」规则 `.archive-form :deep(.el-form-item){align-items:center}` 锁在 customer-archive.vue 的 scoped 样式里,其它页面拿不到;flex 容器默认 stretch,label(32px) 在高控件行内贴顶。 - 修复:规则提升到 `src/styles/element-ui.scss` 全局(紧跟 is-required 星号配套规则之后):`.archive-form .el-form-item { align-items:center }`。全站 archive-form 表单一并生效,label 与控件垂直居中。SCSS 编译通过。 + +## 司机弹窗「驾驶证信息」:有效期必填、长期有效不必填(transportCapacity/driver.vue) +- 需求:驾驶证信息区「有效期」(起/止,prop `drivingLicenseEndDate`)要必填(显示红*),「长期有效」复选框(prop `drivingLicenseLongTerm`)不必填(去掉红*)。 +- 改动(formRules 两处): + 1. `drivingLicenseEndDate` 规则加 `required: true`(`{ required: true, validator: this.validateDrivingLicenseEndDate, trigger: 'change' }`)——仅用于渲染红*,实际校验仍走自定义 validator。 + 2. 删除 `drivingLicenseLongTerm` 的 `{ required: true, message: '请选择驾驶证是否长期有效' }` 规则块。 +- 关键机制(Element Plus 2.14 + async-validator 4.2.5 已核实): + - 红* 由 `form-item` 的 `isRequired = normalizedRules.some(rule => rule.required)` 决定,只要规则对象带 `required` 就显示。 + - async-validator 的 `rule.validate` 中,若存在 `rule.validator`,直接走自定义 validator 并 return,**不会**再执行 required 空值检查 → 勾「长期有效」时止日被清空/disabled 也不会误报必填。 + - 校验逻辑保持原样:起始日期恒必填;`longTerm !== 1` 时止日必填。 +- 未同步:「从业资格证信息」区仍是「有效期无红* + 长期有效有红*」的旧形态(待主人确认是否一并统一)。 + +## 司机弹窗 placeholder 统一为「请输入/请选择」(transportCapacity/driver.vue) +- 需求:新增/修改司机弹窗输入框 placeholder 去掉后面的字段名称,只保留「请输入」「请选择」。 +- 改动:18 处 placeholder 简化(7 处 → `请输入`,10 处 → `请选择`,1 处动态 cascader `driverForm.addressRegion || '请选择省市区'` → `|| '请选择'`)。 +- **保留 4 处**(主人明确确认): + 1. 驾驶车辆 `请输入或选择车辆` —— 复合操作(既可输入又可点按钮选车),去掉会丢语义。 + 2. 日期范围 `起` / `止` —— 起止标记,非字段提示。 + 3. 资格证号 `默认身份证号` —— 默认值说明,非「请输入」格式。 +- 未动:表单**校验错误提示 message 仍带字段名**(如「请选择准驾车型」),因报错需指明具体字段,与 placeholder 定位不同;主人未要求,暂保持。 +- 做法:Python 脚本按完整 placeholder 字符串精确替换(18 规则全命中,未匹配即 exit 1 中断),比逐个 Edit 高效且不会误伤。 +- 校验:`@vue/compiler-sfc` parse + compileTemplate + compileScript 三项全通过。注意脚本必须放在**项目根目录**下运行(放 /tmp 解析不到 node_modules 里的 @vue/compiler-sfc)。 +- ⚠️ git diff 显示的 `drivingLicenseLongTerm` 校验规则变动是**本次之前工作区已有的未提交改动**(见上一条日志),非本次引入,勿混淆。 + +## 「自动生成结算单」开关加 ? 悬浮提示(3 处) +- 需求:开关「开启」后面加问号图标,hover 提示「开启时,系统根据配置规则归集运单,定时生成结算单」。 +- 改动文件(同一文案,为保持全站一致): + 1. `src/views/business/components/business-crud-page.vue`(1884 行附近,`.business-crud-page__settlement-switch`) + 2. `src/views/business/contract-manage.vue`(357 行附近,`.contract-manage-form__settlement-switch`) + 3. `src/views/business/contract-manage-change.vue`(55 行,`.settlement-switch`,原为单行长标签已拆行) +- 写法:`开启` 后插 ``,再接「关闭」radio。 +- 样式:`.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),非本次引入。 diff --git a/.workbuddy/memory/MEMORY.md b/.workbuddy/memory/MEMORY.md index ce2389b..be1c62d 100644 --- a/.workbuddy/memory/MEMORY.md +++ b/.workbuddy/memory/MEMORY.md @@ -2,6 +2,17 @@ ## 设计约定(已确认) +### 表单 placeholder 统一为「请输入 / 请选择」(不带字段名) +- **规范**:输入框 placeholder 只写动作词 `请输入` / `请选择`,**后面不跟字段名称**(label 已说明是什么字段,重复无意义)。 +- 已生效页面:waybill-manage、transport-plan、shipping-template、temporary-credit-limit(搜索栏 + 弹窗表单)、**driver.vue**(2026-09-09 补齐 18 处)。 +- **3 类例外必须保留,不要误简化**: + 1. 复合操作:如 `请输入或选择车辆`(既可键盘输入又可点按钮弹窗选车),丢掉会损失语义。 + 2. 日期区间的 `起` / `止`:是起止标记,不是字段提示。 + 3. 默认值说明:如资格证号 `默认身份证号`、车牌号 `如:京A12345`,属于示例/默认值提示,非「请输入」格式。 +- **校验错误提示 message 保持带字段名**(如「请选择准驾车型」「请输入档案编号」),与 placeholder 定位不同——报错必须指明具体哪个字段,不能只说「请选择」。 +- Avue 配置化表单:在 option 各列加 `placeholder`;搜索栏可用通用工具 `withSearchPlaceholders([...])`(见 temporary-credit-limit.js)。 +- 批量改法:Python 脚本按**完整 placeholder 字符串**做精确替换,每规则校验 `count > 0` 否则中断,避免误伤;改完用 `@vue/compiler-sfc` 的 parse + compileTemplate + compileScript 验证(脚本须放项目根目录下跑,放 /tmp 解析不到 node_modules)。 + ### 弹窗分组:统一用全局 `` - 弹窗 body 背景由 `src/styles/element-ui.scss` 全局 `.el-dialog__body { background:#f5f6fa; padding:16px }` 统一灰底。 - 每组 = 白底卡片:4px 主色竖条 + 8px 间距 + 圆角 6px + 淡阴影。组件全局注册 ``,支持 `#title` / `#extra` slot。 diff --git a/src/views/business/components/business-crud-page.vue b/src/views/business/components/business-crud-page.vue index d56a38e..f237a35 100644 --- a/src/views/business/components/business-crud-page.vue +++ b/src/views/business/components/business-crud-page.vue @@ -1883,6 +1883,12 @@ 自动生成结算单 开启 + + + 关闭 @@ -14453,6 +14459,13 @@ export default { color: #303133; } + .settlement-switch-tip { + margin: 0 4px; + color: #a8abb2; + cursor: help; + font-size: 14px; + } + &__module-form { width: 100%; diff --git a/src/views/business/contract-manage-change.vue b/src/views/business/contract-manage-change.vue index 612a872..6e57471 100644 --- a/src/views/business/contract-manage-change.vue +++ b/src/views/business/contract-manage-change.vue @@ -52,7 +52,16 @@ -
自动生成结算单开启关闭
+
+ 自动生成结算单 + + 开启 + + + + 关闭 + +
@@ -211,6 +220,7 @@ export default { .attachment-upload .vehicle-attachment-upload { width: auto; } .attachment-upload .el-upload { display: inline-flex; } .settlement-switch { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; } +.settlement-switch-tip { margin: 0 4px; color: #a8abb2; cursor: help; font-size: 14px; } .settlement-form { display: grid; grid-template-columns: repeat(3, minmax(240px, 1fr)); gap: 8px 28px; } .change-reason-section { margin: 20px 0; } .page-footer { diff --git a/src/views/business/contract-manage.vue b/src/views/business/contract-manage.vue index 6fc60f8..c8fc9fd 100644 --- a/src/views/business/contract-manage.vue +++ b/src/views/business/contract-manage.vue @@ -356,6 +356,12 @@ 自动生成结算单 开启 + + + 关闭 @@ -2758,6 +2764,13 @@ export default { align-items: center; gap: 20px; margin-bottom: 16px; + + .settlement-switch-tip { + margin: 0 4px; + color: #a8abb2; + cursor: help; + font-size: 14px; + } } &__settlement-grid { diff --git a/src/views/transportCapacity/driver.vue b/src/views/transportCapacity/driver.vue index 11fce48..cc21b73 100644 --- a/src/views/transportCapacity/driver.vue +++ b/src/views/transportCapacity/driver.vue @@ -131,7 +131,7 @@ v-model="driverForm.driverName" maxlength="10" show-word-limit - placeholder="请输入司机姓名" + placeholder="请输入" /> @@ -141,7 +141,7 @@ v-model="driverForm.idCardNo" maxlength="18" show-word-limit - placeholder="请输入身份证号" + placeholder="请输入" @input="driverForm.idCardNo = String(driverForm.idCardNo || '').toUpperCase()" /> @@ -152,13 +152,13 @@ v-model="driverForm.birthday" type="date" value-format="YYYY-MM-DD" - placeholder="请选择出生年月" + placeholder="请选择" /> - + @@ -166,7 +166,7 @@ - + @@ -297,7 +297,7 @@ filterable allow-create default-first-option - placeholder="请选择准驾车型" + placeholder="请选择" > @@ -389,7 +389,7 @@ v-model="driverForm.qualificationType" clearable filterable - placeholder="请选择从业资格认证类型" + placeholder="请选择" > @@ -464,7 +464,7 @@ - + @@ -476,7 +476,7 @@ @@ -485,7 +485,7 @@ @@ -495,7 +495,7 @@ @@ -507,7 +507,7 @@ filterable allow-create default-first-option - placeholder="请选择与联系人关系" + placeholder="请选择" > @@ -813,10 +813,7 @@ export default { drivingType: [{ required: true, message: '请选择准驾车型', trigger: 'change' }], drivingLicenseNo: [{ required: true, message: '请输入档案编号', trigger: 'blur' }], drivingLicenseEndDate: [ - { validator: this.validateDrivingLicenseEndDate, trigger: 'change' }, - ], - drivingLicenseLongTerm: [ - { required: true, message: '请选择驾驶证是否长期有效', trigger: 'change' }, + { required: true, validator: this.validateDrivingLicenseEndDate, trigger: 'change' }, ], qualificationType: [ { required: true, message: '请选择从业资格认证类型', trigger: 'change' }, diff --git a/src/views/vehicle/customer-archive.vue b/src/views/vehicle/customer-archive.vue index b821cec..1fbd0f8 100644 --- a/src/views/vehicle/customer-archive.vue +++ b/src/views/vehicle/customer-archive.vue @@ -1645,6 +1645,14 @@ export default { regionOptions: [], customerNatureOptions: [], customerTypeOptions: [], + customerKindOptions: [ + { label: '外部客商', value: 'external' }, + { label: '内部组织', value: 'internal' }, + ], + customerKindMap: { + external: '外部客商', + internal: '内部组织', + }, businessScopeOptions: [], qualificationTypeOptions: [], creditLevelOptions: ['A', 'B', 'C', 'D', 'E', 'F'].map(item => ({