From dc8dc3083fecbe1d874584beec5e472fd2e9e1e7 Mon Sep 17 00:00:00 2001 From: zhang1106 <849185023@qq.com> Date: Thu, 30 Apr 2026 17:00:25 +0800 Subject: [PATCH] =?UTF-8?q?fix(floorplan):=20=E4=BF=AE=E5=A4=8D=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=9C=A8=E6=9C=BA=E6=9E=B6=E4=B8=AD=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E7=9A=84=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floorplan/canvas/CanvasRenderer.js | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/floorplan/canvas/CanvasRenderer.js b/frontend/src/components/floorplan/canvas/CanvasRenderer.js index 63ca519..7f72768 100644 --- a/frontend/src/components/floorplan/canvas/CanvasRenderer.js +++ b/frontend/src/components/floorplan/canvas/CanvasRenderer.js @@ -151,12 +151,13 @@ class CanvasRenderer { const bodyX = rackBounds.x + RACK_PADDING + leftLabelW; const bodyW = U_BODY_WIDTH; - // 从底部开始计算坐标(和渲染逻辑一致) + // 从底部开始计算坐标(和渲染逻辑一致,设备向上扩展) const bodyStartY = bodyY + 4 + (totalU * uHeight); // 底部Y坐标 - const deviceY = bodyStartY - device.position * uHeight; - const deviceH = uHeight * (device.height || 1); + const deviceHeight = device.height || 1; + const deviceStartY = bodyStartY - (device.position + deviceHeight - 1) * uHeight; + const deviceH = uHeight * deviceHeight; - return { x: bodyX, y: deviceY, width: bodyW, height: deviceH }; + return { x: bodyX, y: deviceStartY, width: bodyW, height: deviceH }; } hitTest(canvasX, canvasY) { @@ -349,30 +350,34 @@ class CanvasRenderer { // U位高度 const uHeight = Math.min(U_HEIGHT, (h - 8) / totalU); - // 设备数据 - 按position分组 + // 设备数据 - 按position分组(注意:设备从position向上扩展) const devices = (rack.Devices || []).filter(d => d.position != null); const deviceByU = new Map(); devices.forEach(d => { + const deviceHeight = d.height || 1; const startU = d.position; - const endU = startU + (d.height || 1) - 1; + const endU = startU + deviceHeight - 1; // 向上扩展 for (let u = startU; u <= endU; u++) { deviceByU.set(u, d); } }); - // 渲染左侧U位标签(从下到上:1U在底部) + // 渲染左侧U位标签(从下到上:1U在底部,totalU在顶部) this.drawULabels(ctx, leftLabelX, y + 4, leftLabelW, totalU, uHeight, 'left'); - // 渲染设备区域和空闲U位(从下到上:1U在底部) + // 渲染设备区域和空闲U位(从下到上:1U在底部,totalU在顶部) // 从底部开始渲染 const bodyStartY = y + 4 + (totalU * uHeight); // 底部Y坐标 for (let u = 1; u <= totalU; u++) { - // 计算当前U位的Y坐标(从底部向上) + // 计算当前U位的Y坐标(从底部向上,u越大Y越小) const currentY = bodyStartY - u * uHeight; const d = deviceByU.get(u); if (d && d.position === u) { + // 设备从position向上显示,所以起始Y坐标要计算正确 + const deviceHeight = d.height || 1; + const deviceStartY = bodyStartY - (u + deviceHeight - 1) * uHeight; const isHovered = this.hoveredDevice?.deviceId === d.deviceId; - this.drawDevice(ctx, d, bodyX, currentY, bodyW, uHeight * (d.height || 1), isHovered); + this.drawDevice(ctx, d, bodyX, deviceStartY, bodyW, uHeight * deviceHeight, isHovered); } else if (!d) { this.drawEmptyU(ctx, bodyX, currentY, bodyW, uHeight); }