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

10 KiB
Raw Blame History

项目长期记忆(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×151pxel-col 内 margin:0 左对齐。
  • <image-upload-field large> 适用(身份证/行驶证/道路运输证/登记本/船舶各证)。每页 scoped 覆盖 .xxx-uploader--largewidth:240px)与 --large .el-uploadwidth: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.scss5b 段):18px/600/#303133 + margin-bottom:20px + ::before 4px 主色竖条 + 8px 间距。原 customer-archive.vuescoped)与 business-crud-page.vue:global)两处本地重复定义已删除,改由全局规则统一驱动(全站任意页面用此 class 即得统一标题)。
  • business-crud-page 系列shipping-template / transport-plan / waybill-manage / contract-manage 独立表单页):PageAvueFormrender 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.titleisWaybillDetailLayout = 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=editormaster-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-tagclass="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 crudOptioncloneOption 克隆(保留所有顶层属性)。给各页 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,底部按钮随内容滚动不浮动。pageFormOption6205 行)负责装配。contract 用 buildContractFormGroupOption6861 行)按 order 分 7 组白卡。
  • 查看详情弹窗(detailBox)自定义机制:列表"查看/详情"按钮默认调 Avue 内置 rowView(列数复用 column.span,常呈 3 列)。要改成自定义两列白卡详情,在页面 configdetailButton: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'。