diff --git a/.workbuddy/memory/2026-08-14.md b/.workbuddy/memory/2026-08-14.md index f9cb19d..15b7311 100644 --- a/.workbuddy/memory/2026-08-14.md +++ b/.workbuddy/memory/2026-08-14.md @@ -22,6 +22,13 @@ - 用户要求 `/business/transport-plan` 新增/编辑弹窗同样改为接近全屏(原来固定 max-height: 72vh,内容少时下方留白)。 - 改动:`src/styles/element-ui.scss` 的 `.transport-plan-dialog.el-dialog` 规则,由 `margin-top:4vh; max-height:72vh` 改为 `margin-top:20px !important; margin-bottom:20px !important; height:calc(100vh - 40px); max-height:calc(100vh - 40px) !important`,与 shipping-template 弹窗完全对齐(压过库内置 `.avue-dialog` 的 max-height: calc(100% - 200px))。 - 已确认 `src/option/business/transport-plan.js:607` 有 `dialogCustomClass: 'transport-plan-dialog'`,CSS 生效。body/footer flex 分摊规则(504-520 行)保持不变。 + +## waybill-manage 弹窗高度也改为接近全屏 + +- 用户要求 `/business/waybill-manage` 新增/编辑弹窗同样接近全屏。 +- 机制澄清:waybill-manage 用封装组件 `src/views/business/components/business-crud-page.vue`,它内部 ``,option 由传入的 `crudOption`(即 waybill-manage.js 的 option)经 `cloneOption`(组件内 6261 行,浅展开+重映射 column,保留所有顶层属性)克隆而来。因此给 waybill-manage.js 的 option 顶层加 `dialogCustomClass` 即可只影响本页(不影响共用 business-crud-page 的其他页面)。Avue crud 弹窗 `dialog-form3.js:21` 会读取并应用 dialogCustomClass。 +- 改动1:`src/option/business/waybill-manage.js` 的 `export const option = {` 顶层加 `dialogCustomClass: 'waybill-manage-dialog'`(在展开 `...createCrudOption(` 之前)。 +- 改动2:`src/styles/element-ui.scss` 新增 `.waybill-manage-dialog.el-dialog / .el-dialog__header / .el-dialog__body / .avue-dialog__footer` 四条规则,复刻 shipping-template 方案(height/max-height: calc(100vh - 40px) !important;body max-height:none !important 解开全局 `.avue-crud__dialog .el-dialog__body` 的 200px 限制;footer sticky)。额外在 footer 加 `margin-top: 0 !important` 抵消全局 `.avue-crud__dialog .avue-dialog__footer { margin-top: -30px !important }`(863 行)的上移副作用(shipping-template 是 dialog-form 弹窗无 avue-crud__dialog class 故不受影响,waybill-manage 是 avue-crud 弹窗会受影响,必须处理)。 - 宽度来源: - `src/option/business/common.js` 的 `createCrudOption` 中 `labelWidth: 'auto'`; - Avue 会按当前弹窗内最长 label 自动计算宽度,故出现 227px。 @@ -95,3 +102,11 @@ - 新增 `.transport-plan-dialog` 规则(弹窗体用 `height:72vh` **固定**高度,内容少时 body 下方留白、内容多时窗内滚动;footer 同样 sticky 贴底)。 - 关键技术点:Avue 内置弹窗 footer 的真实 class 是 `.avue-dialog__footer`,且**渲染在 `.el-dialog__body` 内部**;贴底必须用 `position: sticky; bottom: 0`(flex `margin-top:auto` 在滚动容器内仍会随内容滚走,无效)。这与手写 el-dialog(footer 在 body 外、class 为 `.el-dialog__footer`)不同。 - 验证:dev server(2889) HMR 自动生效;刷新后重开「新增」即可见(弹窗固定 72vh、底部"提交/取消"常驻可见)。 + +## contract-manage 新增/编辑弹窗也改为接近全屏 + +- 用户要求 `/business/contract-manage` 新增/编辑弹窗同样接近全屏(与前几个 business 弹窗对齐)。 +- 机制:该页同样用 `business-crud-page` 封装 → avue-crud 弹窗(带 `avue-crud__dialog` class),与 waybill-manage 完全一致。 +- 改动: + 1. `src/option/business/contract-manage.js`:该文件 option 在 `createCrudOption([...])` 之后本就用 `option.xxx = ...` 顶层赋值(span/dialogWidth/dialogTop 等),故在末尾追加 `option.dialogCustomClass = 'contract-manage-dialog';`(无需改结构,与文件既有写法一致)。 + 2. `src/styles/element-ui.scss`:新增 `.contract-manage-dialog` 四条规则,复刻 waybill-manage 方案——`height/max-height: calc(100vh - 40px) !important` 压过库内置 `.avue-dialog` 的 200px 上限;`.el-dialog__header { flex:none }`、`.el-dialog__body { flex:1 1 auto; min-height:0; max-height:none !important; overflow-y:auto }` 解开全局 avue-crud 200px body 限制;`.avue-dialog__footer { position:sticky; bottom:0; margin-top:0 !important; background:#fff }` 抵消全局 footer 的 -30px 上移。 diff --git a/.workbuddy/memory/MEMORY.md b/.workbuddy/memory/MEMORY.md index 9b44b7c..da65791 100644 --- a/.workbuddy/memory/MEMORY.md +++ b/.workbuddy/memory/MEMORY.md @@ -77,3 +77,8 @@ ## 环境注意 - Vite 代理跨域:Saber3 axios 开 `withCredentials=true`,直连绝对地址后端须让 CORS `Allow-Origin` 为具体域名(不能用 `*`),否则浏览器拒绝。改 `.env`/`vite.config.mjs` 必须重启 dev。 + +### business-crud-page 封装页面的弹窗高度改法(重要,复用模式) +- `src/views/business/components/business-crud-page.vue` 被 waybill-manage / transport-plan 等多个业务页共用,内部 ``,option 由传入 prop `crudOption` 经 `cloneOption`(组件内 6261 行,浅展开+重映射 column,**保留所有顶层属性**)克隆而来。 +- 因此给各业务页 `option` 顶层加 `dialogCustomClass: 'xxx-dialog'`,再在 `element-ui.scss` 写 `.xxx-dialog.el-dialog { height/max-height: calc(100vh - 40px) !important; ... }` 等规则,即可**只影响该页**、不波及其他共用页面(已验证 waybill-manage / transport-plan 走同一机制生效)。 +- 注意 avue-crud 弹窗带 `avue-crud__dialog` class,会被全局 `.avue-crud__dialog .avue-dialog__footer { margin-top: -30px !important }`(element-ui.scss 863 行)影响,自定义 footer 规则需加 `margin-top: 0 !important` 抵消;纯 dialog-form 弹窗(如 shipping-template)无此 class 不受影响。 diff --git a/src/option/business/contract-manage.js b/src/option/business/contract-manage.js index fd5ba32..b7f1290 100644 --- a/src/option/business/contract-manage.js +++ b/src/option/business/contract-manage.js @@ -622,3 +622,4 @@ option.dialogWidth = 1480; option.dialogTop = '4vh'; option.dialogCloseBtn = true; option.menuWidth = 320; +option.dialogCustomClass = 'contract-manage-dialog'; diff --git a/src/option/business/waybill-manage.js b/src/option/business/waybill-manage.js index 8ebee78..08651f1 100644 --- a/src/option/business/waybill-manage.js +++ b/src/option/business/waybill-manage.js @@ -323,6 +323,7 @@ export const config = { }; export const option = { + dialogCustomClass: 'waybill-manage-dialog', ...createCrudOption( withSearchPlaceholders([ { diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss index 6177876..0f1865e 100644 --- a/src/styles/element-ui.scss +++ b/src/styles/element-ui.scss @@ -521,6 +521,71 @@ background: #fff; } +// 运单管理新增/编辑弹窗:参照 vehicle/customer-archive,弹窗体接近全屏(上下各留 20px 边距); +// 同时覆盖 Avue 库内置 .avue-dialog 的 max-height: calc(100% - 200px) 上限, +// 并解开 .avue-crud__dialog .el-dialog__body 的 max-height: calc(100vh - 200px) 限制; +// 底部操作栏(avue 内置 footer,渲染在 body 内部)sticky 贴底始终可见 +// (额外用 margin-top: 0 !important 抵消全局 .avue-crud__dialog .avue-dialog__footer 的 -30px 上移) +.waybill-manage-dialog.el-dialog { + margin-top: 20px !important; + margin-bottom: 20px !important; + height: calc(100vh - 40px); + max-height: calc(100vh - 40px) !important; + display: flex; + flex-direction: column; +} + +.waybill-manage-dialog .el-dialog__header { + flex: none; +} + +.waybill-manage-dialog .el-dialog__body { + flex: 1 1 auto; + min-height: 0; + max-height: none !important; + display: flex; + flex-direction: column; + overflow-y: auto; +} + +.waybill-manage-dialog .avue-dialog__footer { + position: sticky; + bottom: 0; + flex: none; + margin-top: 0 !important; + background: #fff; +} + +// 合同管理新增/编辑弹窗(business-crud-page 封装 → avue-crud,弹窗带 avue-crud__dialog class) +// 复刻 waybill-manage 方案:接近全屏、压过库内置 .avue-dialog 的 calc(100% - 200px), +// 并解开 body 的 200px 上限、抵消全局 footer 的 -30px 上移 +.contract-manage-dialog.el-dialog { + margin-top: 20px !important; + margin-bottom: 20px !important; + height: calc(100vh - 40px); + max-height: calc(100vh - 40px) !important; + display: flex; + flex-direction: column; +} +.contract-manage-dialog .el-dialog__header { + flex: none; +} +.contract-manage-dialog .el-dialog__body { + flex: 1 1 auto; + min-height: 0; + max-height: none !important; + display: flex; + flex-direction: column; + overflow-y: auto; +} +.contract-manage-dialog .avue-dialog__footer { + position: sticky; + bottom: 0; + flex: none; + margin-top: 0 !important; + background: #fff; +} + // 统一表格线条颜色 .el-table { --el-table-border-color: #eff1f7; diff --git a/src/views/business/loading-manage.vue b/src/views/business/loading-manage.vue index e9f7527..6f756c4 100644 --- a/src/views/business/loading-manage.vue +++ b/src/views/business/loading-manage.vue @@ -764,7 +764,7 @@ @drop="handleRouteDrop(index)" > - {{ routeTypeText(index) }} + {{ routeTypeText(index) }} {{ node.address }} {{ tag }} @@ -933,7 +933,7 @@ -
{{ routeChangeTypeText(index) }}{{ node.address }}{{ tag }}
+
{{ routeChangeTypeText(index) }}{{ node.address }}{{ tag }}
@@ -1612,6 +1612,11 @@ export default { if (index === this.routeChangeNodes.length - 1) return '终'; return '经'; }, + routeChangeTypeClass(index) { + if (index === 0) return 'start'; + if (index === this.routeChangeNodes.length - 1) return 'end'; + return 'middle'; + }, handleRouteChangeDragStart(index) { this.routeChangeDragIndex = index; }, @@ -1843,6 +1848,11 @@ export default { if (index === this.routeNodes.length - 1) return '终'; return '经'; }, + routeTypeClass(index) { + if (index === 0) return 'start'; + if (index === this.routeNodes.length - 1) return 'end'; + return 'middle'; + }, handleRouteDragStart(index) { this.routeDragIndex = index; }, @@ -2373,7 +2383,10 @@ export default { text-align: center; border-radius: 50%; color: #fff; - background: #409eff; + + &--start { background: #409eff; } + &--middle { background: #e6a23c; } + &--end { background: #67c23a; } } .loading-manage-dialog__route-address { @@ -2458,7 +2471,20 @@ export default { .loading-detail__process-actions .el-select { width: 180px; } .loading-detail__map { width: 100%; min-height: 260px; border: 1px solid #eff1f7; } } -.loading-route-change-dialog { .loading-route-change-dialog__original { color: #a8abb2; line-height: 20px; margin-bottom: 4px; }.loading-route-change-dialog__location { cursor: pointer; color: #909399; }.loading-route-change-dialog__hint { color: #909399; }.loading-route-change-dialog__route-list { display: flex; flex-direction: column; gap: 8px; }.loading-route-change-dialog__route-item { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto 24px; align-items: center; gap: 12px; padding: 10px 12px; background: #f5f6f7; cursor: move; }.loading-route-change-dialog__route-type { width: 30px; height: 30px; border-radius: 50%; background: #dcdfe6; text-align: center; line-height: 30px; }.loading-route-change-dialog__tags { display: flex; gap: 4px; }.loading-route-change-dialog__record-content { white-space: normal; overflow-wrap: anywhere; line-height: 22px; } } +.loading-route-change-dialog { + .loading-route-change-dialog__original { color: #a8abb2; line-height: 20px; margin-bottom: 4px; } + .loading-route-change-dialog__location { cursor: pointer; color: #909399; } + .loading-route-change-dialog__hint { color: #909399; } + .loading-route-change-dialog__route-list { display: flex; flex-direction: column; gap: 8px; } + .loading-route-change-dialog__route-item { display: grid; grid-template-columns: 34px minmax(0, 1fr) auto 24px; align-items: center; gap: 12px; padding: 10px 12px; background: #f5f6f7; cursor: move; } + .loading-route-change-dialog__route-type { width: 30px; height: 30px; border-radius: 50%; text-align: center; line-height: 30px; color: #fff; + &--start { background: #409eff; } + &--middle { background: #e6a23c; } + &--end { background: #67c23a; } + } + .loading-route-change-dialog__tags { display: flex; gap: 4px; } + .loading-route-change-dialog__record-content { white-space: normal; overflow-wrap: anywhere; line-height: 22px; } +} .loading-common-address-dialog__toolbar { display: flex; gap: 8px; margin-bottom: 12px; }.loading-common-address-dialog__toolbar .el-input { flex: 1; } @media (max-width: 900px) { .loading-manage-dialog__grid {