侧边栏收起缩放适配方案
一、问题描述
在 OverallProcurementDashboard 和 OrderDataPanel 两个大屏看板页面中,使用 CSS scale 缩放方案来适配不同屏幕尺寸。当用户点击收起左侧菜单栏时,会出现以下两个问题:
- 竖向滚动条出现:侧边栏收起后可用宽度变大,仅按宽度计算的 scale 值增大,导致缩放后的内容高度超出视口高度,出现竖向滚动条。
- 右侧留白 :如果仅用
Math.min(宽度比, 高度比)限制 scale,缩放后的内容无法填满右侧多出的空间,出现大片空白区域。
二、根本原因分析
原始方案中 scale-wrapper 的尺寸固定为设计稿尺寸(1700×835),缩放计算逻辑如下:
ini
原始方案:
scale = parentWidth / DESIGN_WIDTH // 仅按宽度计算
wrapper 尺寸 = 1700 × 835(固定)
问题 1 :侧边栏收起后 parentWidth 变大 → scale 变大 → 835 × scale > parentHeight → 出现竖向滚动条。
问题 2 :若改为 scale = Math.min(sw, sh),侧边栏收起后 sh < sw → scale 被高度限制 → 1700 × scale < parentWidth → 右侧留白。
三、解决方案
核心思路:同时考虑宽度和高度约束计算 scale,并动态扩展 wrapper 尺寸使缩放后内容恰好填满父容器。
ini
新方案:
sw = parentWidth / DESIGN_WIDTH
sh = parentHeight / DESIGN_HEIGHT
scale = Math.min(sw, sh) // 取较小值,避免任何方向溢出
wrapper 宽度 = parentWidth / scale // 动态扩展
wrapper 高度 = parentHeight / scale // 动态扩展
原理说明
当 scale 被高度限制(sh < sw)时:
wrapperWidth = parentWidth / scale = parentWidth / sh- 缩放后实际宽度 =
wrapperWidth × scale = (parentWidth / sh) × sh = parentWidth✅
即:wrapper 在缩放前被放大,经过 scale 缩小后恰好等于父容器宽度,内部的 grid/flex 布局会自然扩展来填补右侧空白。
四、代码变更
4.1 整体修改文件
| 文件 | 修改内容 |
|---|---|
src/views/wms/OverallProcurementDashboard/index.vue |
缩放逻辑 + 外层容器 overflow |
src/views/wms/daPing/OrderDataPanel copy.vue |
缩放逻辑 + 外层容器 overflow |
4.2 JavaScript 逻辑变更
typescript
// ===== 修改前 =====
function useWidthScale(containerRef: Ref<HTMLElement | null>) {
const DESIGN_WIDTH = 1700;
const DESIGN_HEIGHT = 835;
const scaleValue = ref(1);
const { getCollapsed, getRealWidth } = useMenuSetting();
function updateScale() {
const el = containerRef.value;
if (!el) return;
const parentWidth = el.parentElement?.clientWidth || el.clientWidth;
const sw = parentWidth / DESIGN_WIDTH;
scaleValue.value = sw;
}
const scaleStyle = computed(() => ({
transform: `scale(${scaleValue.value})`,
transformOrigin: 'top left',
width: `${DESIGN_WIDTH}px`,
height: `${DESIGN_HEIGHT}px`,
}));
// ...
}
// ===== 修改后 =====
function useWidthScale(containerRef: Ref<HTMLElement | null>) {
const DESIGN_WIDTH = 1700;
const DESIGN_HEIGHT = 835;
const scaleValue = ref(1);
const wrapperWidth = ref(DESIGN_WIDTH); // 新增:动态宽度
const wrapperHeight = ref(DESIGN_HEIGHT); // 新增:动态高度
const { getCollapsed, getRealWidth } = useMenuSetting();
function updateScale() {
const el = containerRef.value;
if (!el) return;
// 获取实际内容区域尺寸(父容器)
const parentWidth = el.parentElement?.clientWidth || el.clientWidth;
const parentHeight = el.parentElement?.clientHeight || window.innerHeight;
// 同时基于宽度和高度计算缩放比,取较小值避免内容溢出
const sw = parentWidth / DESIGN_WIDTH;
const sh = parentHeight / DESIGN_HEIGHT;
scaleValue.value = Math.min(sw, sh);
// 动态扩展包装器尺寸,使缩放后内容恰好填满父容器
wrapperWidth.value = parentWidth / scaleValue.value;
wrapperHeight.value = parentHeight / scaleValue.value;
}
const scaleStyle = computed(() => ({
transform: `scale(${scaleValue.value})`,
transformOrigin: 'top left',
width: `${wrapperWidth.value}px`, // 改为动态值
height: `${wrapperHeight.value}px`, // 改为动态值
}));
// ...
}
4.3 CSS 样式变更
less
/* 修改前 */
.dashboard-outer {
overflow-x: hidden; /* 只隐藏横向溢出 */
}
/* 修改后 */
.dashboard-outer {
overflow: hidden; /* 完全隐藏溢出,禁止滚动条 */
}
五、效果验证
| 场景 | 修改前 | 修改后 |
|---|---|---|
| 侧边栏展开 | ✅ 正常 | ✅ 正常 |
| 侧边栏收起 | ❌ 竖向滚动条 + 右侧留白 | ✅ 无滚动条,内容填满 |
| 窗口缩放 | ✅ 正常 | ✅ 正常 |
| 全屏模式 | ✅ 正常 | ✅ 正常 |
| 内容完整性 | ✅ 无隐藏 | ✅ 无隐藏 |
六、注意事项
parentHeight取值 :优先使用el.parentElement?.clientHeight,降级使用window.innerHeight。clientHeight能准确获取父容器的实际可用高度(不含导航栏等)。- 侧边栏动画延迟 :
watch中已设置 250ms 延迟等待侧边栏动画完成后再重新计算 scale,无需修改。 overflow: hidden:外层容器必须禁止所有方向的溢出,否则动态扩展的 wrapper 可能导致意外滚动条。- 内部布局 :各模块使用
grid(1fr列)或flex布局,wrapper 尺寸扩展后会自动按比例分配空间,无需额外调整。

