# 项目长期记忆(tms-erp-web-ws / Saber3 客商模块) ## 设计约定(经用户确认的决策) ### 弹窗分组:统一用全局 `` 组件 - 整弹窗 body 由 `src/styles/element-ui.scss` 全局 `.el-dialog__body { background:#f5f6fa; padding:16px }` 统一灰底;每组 = 一张白底卡片(4px 主色竖条 + 8px 间距卡头 + 白底 body,圆角 6px + 极淡阴影)。 - 组件已全局注册 ``,支持 `#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` 左对齐。 - 全 `` 适用(身份证/行驶证/道路运输证/登记本/船舶各证)。每页 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`:裸 `` → ``。图片 `@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 || '新增/编辑配载管理'`),并在 `` 内、body 前加 `
`。 - **master-order?mode=editor**:`master-order.vue` 把 `` 包进 `