From 7fa2bc657d4f6ff8dcf8ee9b3fa9470485e1a9ac Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 24 二月 2026 13:49:25 +0800
Subject: [PATCH] #

---
 src/main/webapp/components/MapCanvas.js |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 103 insertions(+), 15 deletions(-)

diff --git a/src/main/webapp/components/MapCanvas.js b/src/main/webapp/components/MapCanvas.js
index 5306b43..795f549 100644
--- a/src/main/webapp/components/MapCanvas.js
+++ b/src/main/webapp/components/MapCanvas.js
@@ -1,7 +1,7 @@
 Vue.component('map-canvas', {
   template: `
     <div style="width: 100%; height: 100%; position: relative;">
-      <div ref="pixiView"></div>
+      <div ref="pixiView" style="position: absolute; inset: 0;"></div>
       <div v-show="shelfTooltip.visible"
            :style="shelfTooltipStyle()">
         {{ shelfTooltip.text }}
@@ -57,6 +57,9 @@
       mapRowHeights: [],
       mapColOffsets: [],
       mapColWidths: [],
+      mapRowColOffsets: [],
+      mapRowColWidths: [],
+      mapRowShelfCells: [],
       hoveredShelfCell: null,
       hoverPointer: { x: 0, y: 0 },
       hoverRaf: null,
@@ -77,6 +80,7 @@
         item: null
       },
       shelfTooltipMinScale: 0.4,
+      containerResizeObserver: null,
       timer: null,
       adjustLabelTimer: null,
       isSwitchingFloor: false
@@ -85,6 +89,7 @@
     mounted() {
     this.currentLev = this.lev || 1;
     this.createMap();
+    this.startContainerResizeObserve();
     this.loadMapTransformConfig();
     this.loadLocList();
     this.connectWs();
@@ -105,6 +110,7 @@
 
     if (this.hoverRaf) { cancelAnimationFrame(this.hoverRaf); this.hoverRaf = null; }
     if (this.pixiApp) { this.pixiApp.destroy(true, { children: true }); }
+    if (this.containerResizeObserver) { this.containerResizeObserver.disconnect(); this.containerResizeObserver = null; }
     window.removeEventListener('resize', this.resizeToContainer);
     if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
     if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) { try { this.ws.close(); } catch (e) {} }
@@ -274,11 +280,33 @@
       });
       //*******************FPS*******************
     },
+    startContainerResizeObserve() {
+      if (typeof ResizeObserver === 'undefined' || !this.$el) { return; }
+      this.containerResizeObserver = new ResizeObserver(() => {
+        this.resizeToContainer();
+      });
+      this.containerResizeObserver.observe(this.$el);
+    },
+    getViewportSize() {
+      if (!this.pixiApp || !this.pixiApp.renderer) { return { width: 0, height: 0 }; }
+      const screen = this.pixiApp.renderer.screen;
+      if (screen && screen.width > 0 && screen.height > 0) {
+        return { width: screen.width, height: screen.height };
+      }
+      const rect = this.pixiApp.view ? this.pixiApp.view.getBoundingClientRect() : null;
+      return { width: rect ? rect.width : 0, height: rect ? rect.height : 0 };
+    },
     resizeToContainer() {
       const w = this.$el.clientWidth || 0;
       const h = this.$el.clientHeight || 0;
       if (w > 0 && h > 0 && this.pixiApp) {
+        const vw = this.pixiApp.renderer && this.pixiApp.renderer.screen ? this.pixiApp.renderer.screen.width : 0;
+        const vh = this.pixiApp.renderer && this.pixiApp.renderer.screen ? this.pixiApp.renderer.screen.height : 0;
+        if (vw === w && vh === h) { return; }
         this.pixiApp.renderer.resize(w, h);
+        if (this.mapContentSize && this.mapContentSize.width > 0 && this.mapContentSize.height > 0) {
+          this.applyMapTransform(true);
+        }
       }
     },
     getMap() {
@@ -1393,24 +1421,27 @@
       if (!map || !Array.isArray(map)) { return; }
       this.mapRowOffsets = Array.isArray(rowOffsets) ? rowOffsets.slice() : [];
       this.mapRowHeights = Array.isArray(rowHeights) ? rowHeights.slice() : [];
+      const rowColOffsets = [];
+      const rowColWidths = [];
+      const rowShelfCells = new Array(map.length);
       let maxCols = 0;
       for (let r = 0; r < map.length; r++) {
         const row = map[r];
         if (row && row.length > maxCols) { maxCols = row.length; }
+        rowShelfCells[r] = [];
       }
       const colWidths = new Array(maxCols);
       for (let c = 0; c < maxCols; c++) {
         let w = null;
         for (let r = 0; r < map.length; r++) {
           const cell = map[r] && map[r][c];
-          if (!cell || cell.type === 'merge' || cell.isMergedPart) { continue; }
-          if (cell.width != null && cell.width > 0) {
-            const span = cell.colSpan || 1;
-            w = cell.width / span;
-            break;
+          if (!cell) { continue; }
+          if (cell.cellWidth != null && cell.cellWidth !== '') {
+            const base = Number(cell.cellWidth);
+            if (isFinite(base) && base > 0) { w = base / 40; break; }
           }
         }
-        colWidths[c] = w || 25;
+        colWidths[c] = (w && isFinite(w) && w > 0) ? w : 25;
       }
       const colOffsets = new Array(maxCols);
       let xCursor = 0;
@@ -1418,8 +1449,54 @@
         colOffsets[c] = xCursor;
         xCursor += colWidths[c];
       }
+      for (let r = 0; r < map.length; r++) {
+        const row = map[r];
+        if (!row || row.length === 0) {
+          rowColOffsets[r] = [];
+          rowColWidths[r] = [];
+          continue;
+        }
+        const widths = new Array(row.length);
+        for (let c = 0; c < row.length; c++) {
+          const cell = row[c];
+          let w = null;
+          if (cell && cell.cellWidth != null && cell.cellWidth !== '') {
+            const base = Number(cell.cellWidth);
+            if (isFinite(base) && base > 0) { w = base / 40; }
+          }
+          widths[c] = (w && isFinite(w) && w > 0) ? w : 25;
+        }
+        const offsets = new Array(row.length);
+        let x = 0;
+        for (let c = 0; c < row.length; c++) {
+          offsets[c] = x;
+          x += widths[c];
+        }
+        rowColOffsets[r] = offsets;
+        rowColWidths[r] = widths;
+      }
       this.mapColWidths = colWidths;
       this.mapColOffsets = colOffsets;
+      this.mapRowColOffsets = rowColOffsets;
+      this.mapRowColWidths = rowColWidths;
+      this.mapRowShelfCells = rowShelfCells;
+
+      for (let r = 0; r < map.length; r++) {
+        const row = map[r];
+        if (!row) { continue; }
+        for (let c = 0; c < row.length; c++) {
+          const cell = row[c];
+          if (!cell || cell.type !== 'shelf') { continue; }
+          const startRow = this.findIndexByOffsets(this.mapRowOffsets, this.mapRowHeights, cell.posY + 0.01);
+          const endRow = this.findIndexByOffsets(this.mapRowOffsets, this.mapRowHeights, cell.posY + cell.height - 0.01);
+          if (startRow < 0) { continue; }
+          const last = endRow >= 0 ? endRow : startRow;
+          for (let rr = startRow; rr <= last; rr++) {
+            if (!rowShelfCells[rr]) { rowShelfCells[rr] = []; }
+            rowShelfCells[rr].push(cell);
+          }
+        }
+      }
     },
     findIndexByOffsets(offsets, sizes, value) {
       if (!offsets || !sizes || offsets.length === 0) { return -1; }
@@ -1436,9 +1513,19 @@
       const local = this.mapRoot.toLocal(new PIXI.Point(globalPos.x, globalPos.y));
       const rowIndex = this.findIndexByOffsets(this.mapRowOffsets, this.mapRowHeights, local.y);
       if (rowIndex < 0) { if (this.hoveredShelfCell) { this.hoveredShelfCell = null; this.hideShelfTooltip(); } return; }
-      const colIndex = this.findIndexByOffsets(this.mapColOffsets, this.mapColWidths, local.x);
-      if (colIndex < 0) { if (this.hoveredShelfCell) { this.hoveredShelfCell = null; this.hideShelfTooltip(); } return; }
-      const cell = this.resolveMergedCell(this.map, rowIndex, colIndex);
+      let cell = null;
+      if (this.mapRowShelfCells && this.mapRowShelfCells[rowIndex]) {
+        const list = this.mapRowShelfCells[rowIndex];
+        for (let i = 0; i < list.length; i++) {
+          const it = list[i];
+          if (!it) { continue; }
+          if (local.x >= it.posX && local.x < it.posX + it.width &&
+              local.y >= it.posY && local.y < it.posY + it.height) {
+            cell = it;
+            break;
+          }
+        }
+      }
       if (!cell || cell.type !== 'shelf') { if (this.hoveredShelfCell) { this.hoveredShelfCell = null; this.hideShelfTooltip(); } return; }
       if (this.hoveredShelfCell !== cell) {
         this.hoveredShelfCell = cell;
@@ -1580,8 +1667,9 @@
     adjustLabelScale() {
       const s = this.pixiApp && this.pixiApp.stage ? Math.abs(this.pixiApp.stage.scale.x || 1) : 1;
       const minPx = 14;
-      const vw = this.pixiApp.view.width;
-      const vh = this.pixiApp.view.height;
+      const viewport = this.getViewportSize();
+      const vw = viewport.width;
+      const vh = viewport.height;
       const margin = 50;
       const mirrorSign = this.mapMirrorX ? -1 : 1;
       const inverseRotation = -((this.mapRotation % 360) * Math.PI / 180);
@@ -1759,8 +1847,9 @@
       const contentW = size.width || 0;
       const contentH = size.height || 0;
       if (contentW <= 0 || contentH <= 0) { return; }
-      const vw = this.pixiApp.view.width;
-      const vh = this.pixiApp.view.height;
+      const viewport = this.getViewportSize();
+      const vw = viewport.width;
+      const vh = viewport.height;
       let scale = Math.min(vw / contentW, vh / contentH) * 0.95;
       if (!isFinite(scale) || scale <= 0) { scale = 1; }
       const baseW = this.mapContentSize.width || contentW;
@@ -1794,7 +1883,6 @@
     }
   }
 });
-
 
 
 

--
Gitblit v1.9.1