style(business): 调整弹窗样式实现居中加高并优化滚动体验

- 修改 shipping-template 新增/编辑弹窗宽度为 92%,顶部边距调为 4vh,新增自定义 class 实现视觉居中
- 在全局样式中增加 .shipping-template-dialog,弹窗高度占满视口并解除最大高度限制,底部操作栏持续可见且固定贴底
- 调整 transport-plan 弹窗样式,限制最大高度 72vh,内容超出时内部滚动,底部操作栏同样固定
- 统一多处业务弹窗 dialogTop 属性由 '10px' 修改为 '4vh',增强界面一致性
- 调整 waybill-manage 模块部分表格列宽,优化显示效果
- 更新 vite 配置,启用本地开发服务器端口为 2889,更新代理目标地址
This commit is contained in:
2026-08-14 15:24:29 +08:00
parent a69a2efe45
commit a68cf04ff1
9 changed files with 111 additions and 19 deletions
+26
View File
@@ -50,3 +50,29 @@
- 需求:用户截图反馈 `/business/contract-manage` 搜索栏中「全部/30天内到期/90天内到期/90天以上/已到期」标签需要靠右对齐。 - 需求:用户截图反馈 `/business/contract-manage` 搜索栏中「全部/30天内到期/90天内到期/90天以上/已到期」标签需要靠右对齐。
- 改动:`src/views/business/components/business-crud-page.vue``.business-crud-page__contract-expiry-search` 样式由 `order: -1; margin-right: auto` 改为 `margin-left: auto`。这样该 slot 内容会被推到 `#search-menu` 行的右侧,搜索/重置按钮留在左侧,与 vehicle/ship 的左侧标签方案相反,符合用户本次要求。 - 改动:`src/views/business/components/business-crud-page.vue``.business-crud-page__contract-expiry-search` 样式由 `order: -1; margin-right: auto` 改为 `margin-left: auto`。这样该 slot 内容会被推到 `#search-menu` 行的右侧,搜索/重置按钮留在左侧,与 vehicle/ship 的左侧标签方案相反,符合用户本次要求。
- 验证:`vite build --outDir /tmp/pc-build-check-2` 全量编译通过。 - 验证:`vite build --outDir /tmp/pc-build-check-2` 全量编译通过。
## shipping-template 新增/编辑弹窗居中 + 加高(对齐 customer-archive
- 需求:用户反馈 `/business/shipping-template` 新增弹窗「没居中、高度不够高」,要求参照 `/vehicle/customer-archive` 的做法。
- 根因排查:
- shipping-template 的弹窗是 avue-crud 内置弹窗(business-crud-page + `:crud-option``$refs.crud.rowAdd()` 触发),option 里 `dialogWidth:'96%'``dialogTop:'10px'`
- avue 把 `dialogTop` 映射为 Element Plus `--el-dialog-margin-top``'10px'` 把弹窗死顶在顶部 → 视觉「没居中」。
- avue 内置 footer`.avue-dialog__footer`)渲染在**可滚动 body 内部**,不像 customer-archive 那样用 `#footer` 插槽在滚动区之外;字段多时「保存」按钮要滚动才看得到 → 视觉「高度不够高」。
- customer-archive 真正做法是:手写 `<el-dialog width="92%" top="4vh">` + `#footer` 按钮浮动 + body `max-height:72vh` 内部滚动。
- 改动:
1. `src/option/business/shipping-template.js``dialogWidth:'96%'→'92%'``dialogTop:'10px'→'4vh'`,新增 `dialogCustomClass:'shipping-template-dialog'`avue 会把它作为 class 加到 dialog 上,作为样式钩子)。
2. `src/styles/element-ui.scss`:新增 `.shipping-template-dialog` 规则——弹窗体 `height: calc(100vh - 4vh - 24px)` + flex 列布局占满视口(顶部 4vh、底部留白,视觉居中高大);body `max-height:none !important; overflow-y:auto` 解除全局 80vh 上限;`.avue-dialog__footer``position:sticky; bottom:0; background:#fff` 贴底始终可见,对齐 customer-archive 浮动按钮效果。
- 注意:class 唯一,仅作用于 shipping-templatebusiness-crud-page 被多页共用,但其余页 option 未设该 class);弹窗 `append-to-body`,故样式必须放全局(element-ui.scss)而非组件 scoped 样式。
- 验证:dev server(2889) HMR 自动生效;刷新后重开「新增」即可见效果(未跑全量 build,改动为纯 CSS + option 属性)。
## transport-plan 新增/编辑弹窗封顶 72vh(对齐 customer-archive
- 需求:用户要求 `/business/transport-plan` 新增/编辑弹窗高度"封顶 72vh",与 `/vehicle/customer-archive` 一致。
- 排查发现:上次给 shipping-template 加的 `.shipping-template-dialog` 全局 CSS 规则**未持久化**option 钩子 `dialogCustomClass:'shipping-template-dialog'` 还在,但 `element-ui.scss` 里对应规则丢失),即 shipping-template 弹窗样式实际一直未生效。本次一并补回。
- 改动:
1. `src/option/business/transport-plan.js`:补 `dialogCustomClass:'transport-plan-dialog'`option 已有 `dialogWidth:'96%'``dialogTop:'4vh'`)。
2. `src/styles/element-ui.scss`
- 补回 `.shipping-template-dialog` 规则(弹窗体 `height: calc(100vh - 4vh - 24px)` 占满视口 + flex 列布局;body `max-height:none !important; overflow-y:auto``.avue-dialog__footer { position:sticky; bottom:0; background:#fff }` 贴底)。
- 新增 `.transport-plan-dialog` 规则(与 shipping-template 同结构,但弹窗体用 `max-height:72vh` **封顶**而非占满整屏,内容少时随内容变矮、内容多时窗内滚动;footer 同样 sticky 贴底)。
- 关键技术点:Avue 内置弹窗 footer 的真实 class 是 `.avue-dialog__footer`,且**渲染在 `.el-dialog__body` 内部**;贴底必须用 `position: sticky; bottom: 0`flex `margin-top:auto` 在滚动容器内仍会随内容滚走,无效)。这与手写 el-dialogfooter 在 body 外、class 为 `.el-dialog__footer`)不同。
- 验证:dev server(2889) HMR 自动生效;刷新后重开「新增」即可见(弹窗封顶 72vh、底部"提交/取消"常驻可见)。
+1
View File
@@ -31,6 +31,7 @@
- `.el-dialog__body { max-height: calc(100vh - 200px); overflow-y: auto; overflow-x: hidden; }` —— 内容超高时独立滚动,footer(位于 body 之外)始终可见。 - `.el-dialog__body { max-height: calc(100vh - 200px); overflow-y: auto; overflow-x: hidden; }` —— 内容超高时独立滚动,footer(位于 body 之外)始终可见。
- `.el-dialog__footer { margin:0; padding:12px 20px; background:#fff; border-top:1px solid var(--el-border-color-lighter,#ebeef5); box-shadow:0 -2px 8px rgba(0,0,0,.04); border-radius:0 0 var(--el-dialog-border-radius,4px); .el-button+.el-button{margin-left:8px} }` —— 视觉底栏(白底+上边框+轻阴影),与主内容区分。 - `.el-dialog__footer { margin:0; padding:12px 20px; background:#fff; border-top:1px solid var(--el-border-color-lighter,#ebeef5); box-shadow:0 -2px 8px rgba(0,0,0,.04); border-radius:0 0 var(--el-dialog-border-radius,4px); .el-button+.el-button{margin-left:8px} }` —— 视觉底栏(白底+上边框+轻阴影),与主内容区分。
- **注意**`.el-dialog__body``max-height` 会作用于所有弹窗(含纯展示/表格弹窗),无 footer 的弹窗不受影响;project-apply 自身 `.project-apply-dialog .el-dialog__body{76vh}` 特异性更高仍优先。如需让某弹窗豁免,加更具体 class 覆盖即可。 - **注意**`.el-dialog__body``max-height` 会作用于所有弹窗(含纯展示/表格弹窗),无 footer 的弹窗不受影响;project-apply 自身 `.project-apply-dialog .el-dialog__body{76vh}` 特异性更高仍优先。如需让某弹窗豁免,加更具体 class 覆盖即可。
- **Avue 内置 CRUD 弹窗的 footer 真实 class(重要,易踩坑)**:Avue 内置弹窗的"提交/取消"按钮 class 是 `.avue-dialog__footer`**不是** `.el-dialog__footer`),且**渲染在 `.el-dialog__body` 内部**、随 body 滚动会滚出视口。要让它像手写 `#footer` 那样始终贴底,必须针对 `.avue-dialog__footer``position: sticky; bottom: 0; flex: none; background: #fff`(配合 body `flex` 列布局 + `overflow-y:auto`)。手写 `el-dialog` 的 footer 才是 `.el-dialog__footer` 且在 body 外、天然可见。典型落地见 `shipping-template-dialog` / `transport-plan-dialog` 两条全局规则。
### 上传证件区域尺寸规范(transportCapacity 模块强制) ### 上传证件区域尺寸规范(transportCapacity 模块强制)
- **比例**:中国二代身份证标准尺寸 85.6 × 53.98 mm → 宽:高 = **1.586 : 1**(横放) - **比例**:中国二代身份证标准尺寸 85.6 × 53.98 mm → 宽:高 = **1.586 : 1**(横放)
+1 -1
View File
@@ -619,6 +619,6 @@ export const option = createCrudOption([
option.span = 8; option.span = 8;
option.dialogWidth = 1480; option.dialogWidth = 1480;
option.dialogTop = '10px'; option.dialogTop = '4vh';
option.dialogCloseBtn = true; option.dialogCloseBtn = true;
option.menuWidth = 320; option.menuWidth = 320;
+1 -1
View File
@@ -181,7 +181,7 @@ export const option = {
viewBtn: false, viewBtn: false,
editBtn: false, editBtn: false,
delBtn: false, delBtn: false,
dialogTop: '10px', dialogTop: '4vh',
dialogWidth: '96%', dialogWidth: '96%',
menuWidth: 220, menuWidth: 220,
}; };
+4 -2
View File
@@ -269,6 +269,8 @@ export const option = {
})), })),
]) ])
), ),
dialogWidth: '96%', dialogWidth: '92%',
dialogTop: '10px', dialogTop: '4vh',
// 自定义弹窗 class,用于让新增/编辑弹窗体占满视口高度、视觉居中(参照 vehicle/customer-archive
dialogCustomClass: 'shipping-template-dialog',
}; };
+2
View File
@@ -603,4 +603,6 @@ export const option = {
]) ])
), ),
dialogWidth: '96%', dialogWidth: '96%',
dialogTop: '4vh',
dialogCustomClass: 'transport-plan-dialog',
}; };
+2 -2
View File
@@ -707,7 +707,7 @@ export const option = {
searchLabel: '状态', searchLabel: '状态',
searchOrder: 11, searchOrder: 11,
dicData: waybillStatusOptions, dicData: waybillStatusOptions,
minWidth: 120, minWidth: 82,
fixed: 'right', fixed: 'right',
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
@@ -930,6 +930,6 @@ export const option = {
]) ])
), ),
dialogWidth: '96%', dialogWidth: '96%',
dialogTop: '10px', dialogTop: '4vh',
menuWidth: 280, menuWidth: 280,
}; };
+61
View File
@@ -456,6 +456,67 @@
//background: #f5f6fa; //background: #f5f6fa;
} }
// 发货模板新增/编辑弹窗:参照 vehicle/customer-archive 的视觉
// 弹窗体占满视口高度(顶部 4vh、底部留白),内容较少时也保持高大、视觉居中;
// 解除全局 80vh 上限并由 flex 控制,底部操作栏(avue 内置 footer,渲染在 body 内部)sticky 贴底始终可见
.shipping-template-dialog.el-dialog {
margin-top: 4vh !important;
margin-bottom: 0 !important;
height: calc(100vh - 4vh - 24px);
display: flex;
flex-direction: column;
}
.shipping-template-dialog .el-dialog__header {
flex: none;
}
.shipping-template-dialog .el-dialog__body {
flex: 1 1 auto;
min-height: 0;
max-height: none !important;
display: flex;
flex-direction: column;
overflow-y: auto;
}
.shipping-template-dialog .avue-dialog__footer {
position: sticky;
bottom: 0;
flex: none;
background: #fff;
}
// 运输计划新增/编辑弹窗:参照 vehicle/customer-archive,弹窗体封顶 72vh
// 内容较少时弹窗随内容变矮,内容超出 72vh 时窗内滚动;
// 底部操作栏(avue 内置 footer,渲染在 body 内部)sticky 贴底始终可见
.transport-plan-dialog.el-dialog {
margin-top: 4vh !important;
max-height: 72vh;
display: flex;
flex-direction: column;
}
.transport-plan-dialog .el-dialog__header {
flex: none;
}
.transport-plan-dialog .el-dialog__body {
flex: 1 1 auto;
min-height: 0;
max-height: none !important;
display: flex;
flex-direction: column;
overflow-y: auto;
}
.transport-plan-dialog .avue-dialog__footer {
position: sticky;
bottom: 0;
flex: none;
background: #fff;
}
// 统一表格线条颜色 // 统一表格线条颜色
.el-table { .el-table {
--el-table-border-color: #eff1f7; --el-table-border-color: #eff1f7;
+13 -13
View File
@@ -50,26 +50,26 @@ export default ({
__VUE_I18N_LEGACY_API__: true, __VUE_I18N_LEGACY_API__: true,
__INTLIFY_PROD_DEVTOOLS__: false, __INTLIFY_PROD_DEVTOOLS__: false,
}, },
server: {
port: 2888,
proxy: {
'/api': {
target: 'http://localhost',
//target: 'https://saber3.bladex.cn/api',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
},
},
},
// server: { // server: {
// port: 2889, // port: 2888,
// proxy: { // proxy: {
// '/api': { // '/api': {
// target: 'http://172.16.203.228:8000', // target: 'http://localhost',
// //target: 'https://saber3.bladex.cn/api',
// changeOrigin: true, // changeOrigin: true,
// rewrite: path => path.replace(/^\/api/, ''),
// }, // },
// }, // },
// }, // },
server: {
port: 2889,
proxy: {
'/api': {
target: 'http://172.16.203.228:8000',
changeOrigin: true,
},
},
},
resolve: { resolve: {
alias: { alias: {
'~': resolve(__dirname, './'), '~': resolve(__dirname, './'),