Files
tms-erp-web/.workbuddy/memory/MEMORY.md
T
gxwebsoft 8883186344 style(business): 统一业务状态标签为文字+颜色样式
- 新增全局 `.status-text` 样式,去除 el-tag 背景和边框,仅保留彩色文字和跟随文字颜色的圆点
- 业务状态相关的 el-tag 标签全部加上 `class="status-text"`,覆盖调度状态、审批状态、运单状态等全站业务状态展示
- 统一发货模板查看弹窗的卡片样式,新增分区块样式与运费信息展示板块
- 调整发货模板弹窗详情 label 宽度,所有 el-descriptions 的 label 宽度统一为 140px 以保证视觉一致
- 表格列内嵌输入控件全宽默认样式生效,无需单独设置跨度,解决输入框显示不足问题
- 弹窗中的部分表单和导入区域使用 `section-card` 统一卡片风格
- 客商档案查看模式改为独立路由,实现查看与编辑隔离并调整对应操作按钮文案
- 相关样式调整及细节优化,包括运费单位颜色等辅助样式,保证界面细节统一规范
2026-08-24 20:15:14 +08:00

64 lines
10 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.
# 项目长期记忆(tms-erp-web-ws / Saber3 客商模块)
## 设计约定(经用户确认的决策)
### 弹窗分组:统一用全局 `<section-card>` 组件
- 整弹窗 body 由 `src/styles/element-ui.scss` 全局 `.el-dialog__body { background:#f5f6fa; padding:16px }` 统一灰底;每组 = 一张白底卡片(4px 主色竖条 + 8px 间距卡头 + 白底 body,圆角 6px + 极淡阴影)。
- 组件已全局注册 `<section-card title="...">`,支持 `#title` / `#extra` slot。严禁再手写 `.xxx-form__block` + `.dialog-section-title` 拼凑卡片。
- 仅 3 项的小分组用 `el-col :span="8"` 均分一行。
### Avue 内置弹窗内用 section-card:需 dialogCustomClass 透明化 avue-form
- 全站 `.el-dialog .avue-form { background:#fff; padding:8px 16px 4px }` 会把表单整体包白卡,内置弹窗放 section-card 会白卡叠白卡。
- 解法:option 顶层加 `dialogCustomClass:'xxx-dialog'`,再在 element-ui.scss 写三条:
`.xxx-dialog .avue-form { background:transparent; box-shadow:none; padding:0 }`
`.xxx-dialog .avue-form__group > .el-col > .el-form-item { margin-bottom:0 }`(防 form-item margin 与卡距叠加)
`.xxx-dialog .avue-dialog__footer, .avue-crud__dialog .xxx-dialog .avue-dialog__footer { margin-top:0 !important }`(抵消全局 947 行 `-30px !important` 上移)。
### 弹窗底部操作栏浮动(全站统一,全局 CSS 实现)
- `.el-dialog__body { max-height: calc(100vh - 200px); overflow-y:auto; overflow-x:hidden }``.el-dialog__footer { margin:0; padding:12px 20px; background:#fff; border-top:1px solid #ebeef5; box-shadow:0 -2px 8px rgba(0,0,0,.04) }`
- **易踩坑**Avue 内置弹窗 footer 真实 class 是 `.avue-dialog__footer`(非 `.el-dialog__footer`),且渲染在 `.el-dialog__body` 内、随 body 滚动滚出视口。要让它贴底须 `position:sticky; bottom:0; flex:none; background:#fff`(配合 body flex 列布局 + overflow-y:auto)。手写 el-dialog 的 `.el-dialog__footer` 在 body 外天然可见。
- **弹窗高度链**:① `.avue-dialog`(库内置)`max-height:calc(100% - 200px)` 控制整体上限;② `.avue-crud__dialog .el-dialog__body { max-height:calc(100vh - 200px); overflow-y:auto }`(451-457 行);③ 专项弹窗(shipping-template-dialog / transport-plan-dialog`.el-dialog` 自身 `margin-top:4vh; height/max-height:calc(100vh-4vh-24px); display:flex; flex-direction:column` + header flex:none / body flex:1 1 auto; min-height:0; overflow-y:auto; max-height:none!important / footer sticky。**改这类弹窗尺寸只改 section-card 周边规则,不要动 body 内 max-height。**
### 上传证件区域尺寸规范(transportCapacity 强制)
- 二代身份证 85.6×53.98mm → 宽:高 ≈ **1.586:1**;取 ~75% → 固定 **240×151px**el-col 内 `margin:0` 左对齐。
-`<image-upload-field large>` 适用(身份证/行驶证/道路运输证/登记本/船舶各证)。每页 scoped 覆盖 `.xxx-uploader--large``width:240px`)与 `--large .el-upload``width:100%; height:151px`);注意 `.xxx-uploader` 须写在 `.xxx-uploader--large` 之前(同特定性,源码顺序决胜)。
### 上传图片点击放大预览(全局组件 `image-upload-field`
- `src/components/image-upload-field/main.vue`:裸 `<img>``<el-image :preview-src-list="[value]" fit="contain" preview-teleported :z-index="3000" @click.stop>`。图片 `@click.stop` 阻止冒泡到 el-upload(否则重传);"更换"经隐藏 `input.el-upload__input``.click()`el-upload 无 openFileDialog)。readonly 仅预览。driver/vehicle/ship 三页自动获得。z-index 必须 3000 + teleported 否则被 dialog 遮罩盖住。
### 独立表单页标题 `archive-page-form__title`(全局统一,参考 customer-archive
- 样式已**全局化**到 `src/styles/element-ui.scss`5b 段):18px/600/#303133 + margin-bottom:20px + `::before` 4px 主色竖条 + 8px 间距。原 `customer-archive.vue`scoped)与 `business-crud-page.vue``:global`)两处本地重复定义已删除,改由全局规则统一驱动(全站任意页面用此 class 即得统一标题)。
- **business-crud-page 系列**shipping-template / transport-plan / waybill-manage / contract-manage 独立表单页):`PageAvueForm`render `h('div',{class:dialogCustomClass},[titleDiv, avue-form])`)声明 `props.formPageTitle`,模板 `:form-page-title="isStandaloneFormPage ? formPageTitle : undefined"`computed `formPageTitle()``isStandaloneFormPage && (isShippingTemplatePage || isTransportPlanPage || isWaybillDetailLayout || isContractConfig)` 时返回 `this.$route.query.name || '新增'/'编辑'+config.title``isWaybillDetailLayout` = `config.permission==='waybill_manage'``isContractConfig` = `config.permission==='contract_manage'`)。
- **loading-manage/form**:路由直接映射 `loading-manage.vue`(非 business-crud-page)。新增 computed `formPageTitle()``query.name || '新增/编辑配载管理'`),并在 `<component :is="isStandaloneFormPage?'div':'el-dialog'">` 内、body 前加 `<div v-if="isStandaloneFormPage" class="archive-page-form__title">`
- **master-order?mode=editor**`master-order.vue``<master-order-editor>` 包进 `<template v-else-if="mode==='editor'">`,前置 `<div class="archive-page-form__title">{{ masterEditorTitle }}</div>`computed `masterEditorTitle` = `routeId ? '编辑总单' : '新增总单'`)。
- 扩展原则:新增独立表单页要带此标题,要么并入 business-crud-page 的 `formPageTitle` 条件(business-crud-page 系列),要么在对应页面模板手写 `<div class="archive-page-form__title">`loading-manage / master-order 模式)。
### 表格列内嵌输入控件:全宽(全局 CSS,不动手写 scoped)
- `element-ui.scss` 在 660-678 行加了一条全局规则:`.el-table .el-table__body td.el-table__cell .cell > .el-input-number/.el-input/.el-select/.el-date-editor/.el-cascader { width:100%; --el-*-width:100% }`(带对应 `--el-input-number-width` 等变量兜底)。
- 适用场景:可编辑 el-table 列、弹窗内编辑表格。原先容易踩坑的是 el-plus 的 el-input-number 默认根 width=150pxcell 给到 min-width=150 后输入框只占自然宽度、看着"显示不全"。**新增任何"el-table cell 内嵌 el-input-number/el-input/el-select"需求不用再写 scoped 宽度**——已全局兜底。
- 与"表单内 250px 全宽"互不冲突:本规则只命中 `.el-table .el-table__body td`,表单内 `.el-form-item__content >` 的 250px 规则仍生效。
- 已覆盖:pre-settlement-editor「结算明细调整」弹窗(adjustDialog 列内 el-input-number/el-input 全宽)、transport-reconciliation-editor/formal-settlement-editor/settlement-adjustment-editor 同款结构。
### 业务状态标签文字化:全局 `.status-text` 工具类
- 需求:全站"调度状态/运单状态/审批状态"等用 `el-tag` 展示的字段,统一改为"纯文字 + 颜色"(不用 tag 背景/边框)。
- 实现:`element-ui.scss` 末尾新增 `.el-tag.status-text { background:transparent!important; border-color:transparent!important; padding:0; margin-left:8px; font-weight:500 }` + `&::before` 6px 圆点(`background:currentColor`,颜色随 el-tag 的 `:type`)。
- 用法:业务状态 `el-tag``class="status-text"`,颜色仍由现有 `statusTagType/statusType/waybillStatusType/detailStatusType` 返回的 success/warning/danger/info/primary 决定。
- 已覆盖:`business-crud-page.vue`#status/#businessStatus/#approvalStatus 插槽 + 运输计划详情头 + 运单详情头 + 调度弹窗头)、`master-order.vue`/`master-order-detail.vue`/`master-order-dispatch.vue` 的 businessStatus、`loading-manage.vue` 详情弹窗、结算三处 approvalStatus、`process-config.vue` 流程状态、`credit-score-quantification.vue` 状态列。
- 例外:`loading-manage.vue` 列表状态列本就用 `<span class="loading-manage-page__status is-${status}">` 文字化(先例),不动;"类型标签"transport-flow-tag、transportTypeName 等 `type="primary"`)非状态语义,保持 tag 样式。
## 关键文件
- 分组白卡:`src/components/section-card/main.vue`
- 全局弹窗/section-card 样式:`src/styles/element-ui.scss`
- 客商档案弹窗:`src/views/vehicle/customer-archive.vue`(用 `archive-page-form__title` 作页面标题,`:deep(.archive-dialog .el-dialog__body){max-height:72vh}`)。
- 司机/车辆/船舶档案:`src/views/transportCapacity/{driver,vehicle,ship}.vue`(手写 el-form + section-card + 240×151 证件图)。
- 项目补录弹窗:`src/views/business/project-apply.vue`(手写 el-dialog + #footer 浮动,视觉参照)。
## 环境注意
- Vite 代理跨域:axios `withCredentials=true`,直连绝对地址后端须 CORS `Allow-Origin` 为具体域名(不能用 `*`)。改 `.env`/`vite.config.mjs` 必须重启 dev。
## business-crud-page 复用模式(被 waybill/transport-plan/shipping-template/contract 共用)
- option 由 prop `crudOption``cloneOption` 克隆(保留所有顶层属性)。给各页 option 顶层加 `dialogCustomClass:'xxx-dialog'` + element-ui.scss `.xxx-dialog.el-dialog{height/max-height:calc(100vh - 40px)!important}` 可只影响该页。
- avue-crud 弹窗带 `avue-crud__dialog` class,受全局 `.avue-crud__dialog .avue-dialog__footer{margin-top:-30px!important}` 影响,自定义 footer 须加 `margin-top:0!important` 抵消。
- 独立表单页(contract-manage / shipping-template / waybill / transport-plan)走 `PageAvueForm`,不包 el-dialog,底部按钮随内容滚动不浮动。`pageFormOption`6205 行)负责装配。contract 用 `buildContractFormGroupOption`6861 行)按 order 分 7 组白卡。
- **查看详情弹窗(detailBox)自定义机制**:列表"查看/详情"按钮默认调 Avue 内置 `rowView`(列数复用 column.span,常呈 3 列)。要改成自定义两列白卡详情,在页面 `config``detailButton:true` + `detailSections:[{title, fields:[[prop,label,span],...]}]`,组件渲染 `section-card` + `el-descriptions(:column=2)`field 默认占 1 列,span:2 整行)。数据经 `api.getDetail(row.id)` 拉取,值用 `formatDetailValue` 经 column.dicData 转字典显示 label。开关:`showDetailButton` 默认仅非草稿态显示"详情"(草稿态仍走 rowView 3 列);加 `config.detailButtonIgnoreDraftStatus:true` 可让所有状态(含草稿)都走自定义两列详情。statusProp='approvalStatus' 的页面草稿值须为 'draft'。