From bfcd7f5b405e431a5c07fe3fa77d74c892d4e66b Mon Sep 17 00:00:00 2001
From: xiazhengtongxue <133085197+xiazhengtongxue@users.noreply.github.com>
Date: 星期四, 19 三月 2026 15:52:42 +0800
Subject: [PATCH] fix: 修复出入库冲突拦截,系统位置与实际位置的映射和修复

---
 项目代码/WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue | 1328 ++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 942 insertions(+), 386 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue"
index fc8b569..aeba5a1 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS/WIDESEA_WMSClient/src/views/stock/stockView.vue"
@@ -1,392 +1,948 @@
-
 <template>
-  <view-grid
-    ref="grid"
-    :columns="columns"
-    :detail="detail"
-    :editFormFields="editFormFields"
-    :editFormOptions="editFormOptions"
-    :searchFormFields="searchFormFields"
-    :searchFormOptions="searchFormOptions"
-    :table="table"
-    :extend="extend"
-  >
-  </view-grid>
+  <div class="container">
+    <div class="content-wrapper">
+      <!-- 鎺у埗闈㈡澘鍖哄煙 -->
+      <div class="control-panel">
+        <div class="panel-header">
+          <h3>鎺у埗闈㈡澘</h3>
+        </div>
+
+        <div class="panel-body">
+          <div class="form-group">
+            <label class="form-label">浠撳簱锛�</label>
+            <el-select size="mini" filterable v-model="selectedWarehouse" placeholder="璇烽�夋嫨浠撳簱" class="full-width"
+              @change="handleWarehouseChange">
+              <el-option v-for="item in warehouseList" :key="item.warehouseId" :value="item.warehouseId"
+                :label="getWarehouseName(item.warehouseId)">
+              </el-option>
+            </el-select>
+          </div>
+
+          <div class="form-group">
+            <label class="form-label">宸烽亾锛�</label>
+            <el-select size="mini" clearable filterable v-model="selectedRoadwayNo" placeholder="璇烽�夋嫨宸烽亾"
+              class="full-width" @change="handleRoadwayNoChange">
+              <el-option v-for="item in roadwayNoList" :key="item" :value="item" :label="'宸烽亾 ' + item"></el-option>
+            </el-select>
+          </div>
+
+          <el-button type="success" class="refresh-btn" @click="fetchLocationStatus" :loading="loading">
+            鍒锋柊
+          </el-button>
+
+          <div class="legend-section">
+            <div class="legend-header">
+              <h4>鍥句緥璇存槑</h4>
+            </div>
+            <div class="legend-list">
+              <div class="legend-item" v-for="(item, index) in infoMsg" :key="index">
+                <span class="color-box" :style="{ 'background-color': item.bgcolor }"></span>
+                <span class="legend-label">{{ item.msg }}</span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 璐т綅灞曠ず鍖哄煙 -->
+      <div class="main-content">
+        <div v-if="loading" class="loading-container">
+          <el-skeleton :rows="6" animated />
+        </div>
+
+        <div v-else-if="locationData.length > 0" class="location-container">
+          <div class="location-header">
+            <div class="location-info">
+              <span>褰撳墠鏌ョ湅锛歿{ getWarehouseName(selectedWarehouse) }} - 宸烽亾 {{ selectedRoadwayNo }}</span>
+              <span class="total-count">鍏� {{ totalLocations }} 涓揣浣�</span>
+            </div>
+          </div>
+
+          <div class="layers-container">
+            <!-- 閬嶅巻姣忎竴灞� -->
+            <div class="layer-row" v-for="layer in sortedLayerData" :key="layer.layer">
+              <div class="layer-title-area">
+                <h3 class="layer-title">灞� {{ layer.layer }}</h3>
+                <span class="layer-count">{{ getLayerLocations(layer) }} 涓揣浣�</span>
+              </div>
+
+              <div class="layer-content-wrap">
+                <!-- 鎸夎鍒嗙粍鏄剧ず -->
+                <div class="row-group" v-for="rowGroup in getRowGroups(layer)" :key="rowGroup.row">
+                  <div class="row-title">
+                    <span class="row-label">{{ rowGroup.row }}鎺�</span>
+                    <span class="row-count">{{ rowGroup.locations.length }} 涓揣浣�</span>
+                  </div>
+                  
+                  <div class="row-content">
+                    <!-- 鍦ㄦ瘡鎺掑唴鏄剧ず鍒楋紙涓嶆樉绀哄垪鏍囩锛� -->
+                    <div class="location-column" v-for="column in sortedColumns(rowGroup.columns)" :key="column.column">
+                      <div class="locations-wrapper">
+                        <!-- 姣忓垪鏄剧ず娣卞害锛堟祬/娣憋級 -->
+                        <div class="location-item" v-for="depth in column.depths" :key="depth.depth"
+                          :class="getLocationStatusClass(depth)"
+                          @mouseenter="showTooltip(depth, column.column, layer.layer, $event)" 
+                          @mouseleave="hideTooltip"
+                          @click="handleLocationClick(depth)">
+                          <div class="location-code">
+                            {{ getLocationPositionForDisplay(depth, column.column, layer.layer) }}
+                          </div>
+                          <div class="location-status" v-if="depth.enableStatus !== 0">
+                            绂佺敤
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+
+        <!-- 鏃犳暟鎹彁绀� -->
+        <div v-else class="empty-container">
+          <el-empty description="鏆傛棤璐т綅鏁版嵁">
+            <template #description>
+              <p>璇烽�夋嫨浠撳簱鍜屽贩閬撴潵鏌ョ湅璐т綅淇℃伅</p>
+            </template>
+          </el-empty>
+        </div>
+
+        <!-- 鎮诞鎻愮ず妗� -->
+        <div v-if="showTooltipFlag" class="location-tooltip" :style="{
+          left: tooltipPosition.x + 'px',
+          top: tooltipPosition.y + 'px',
+        }">
+          <div class="tooltip-content">
+            <div class="tooltip-header">
+              <h4>璐т綅璇︽儏</h4>
+            </div>
+            <div class="tooltip-body">
+              <div class="tooltip-row">
+                <span class="tooltip-label">浠撳簱锛�</span>
+                <span class="tooltip-value">{{ getWarehouseName(selectedWarehouse) }}</span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">宸烽亾锛�</span>
+                <span class="tooltip-value">{{ selectedRoadwayNo }}</span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">璐т綅缂栧彿锛�</span>
+                <span class="tooltip-value">{{ currentLocation?.locationCode || '--' }}</span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">浣嶇疆锛�</span>
+                <span class="tooltip-value">{{ getLocationPosition(currentLocation) }}</span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">绫诲瀷锛�</span>
+                <span class="tooltip-value">{{ getLocationTypeText(currentLocation?.locationType) }}</span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">鐘舵�侊細</span>
+                <span class="tooltip-value" :class="getStatusClass(currentLocation?.locationStatus)">
+                  {{ getStatusText(currentLocation?.locationStatus) }}
+                </span>
+              </div>
+              <div class="tooltip-row">
+                <span class="tooltip-label">鍚敤鐘舵�侊細</span>
+                <span class="tooltip-value" :class="{ 'status-disabled': currentLocation?.enableStatus !== 0 }">
+                  {{ getEnableStatusText(currentLocation?.enableStatus) }}
+                </span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
-    <script>
-import extend from "@/extension/stock/stockView.js";
-import { ref, defineComponent } from "vue";
-export default defineComponent({
-  setup() {
-    const table = ref({
-      key: "stockId",
-      footer: "Foots",
-      cnName: "搴撳瓨瑙嗗浘",
-      name: "stockView",
-      url: "/stockView/",
-      sortName: "stockId",
-    });
-    const editFormFields = ref({
-      palletCode: "",
-      locationCode: "",
-      locationName: "",
-    });
-    const editFormOptions = ref([
-      
-    ]);
-    const searchFormFields = ref({
-      palletCode: "",
-      // locationCode: "",
-      materielCode:"",
-      batchNo:""
-    });
-    const searchFormOptions = ref([
-      [
-        { title: "鎵樼洏缂栧彿", field: "palletCode",type: "like" },
-        // { title: "璐т綅缂栧彿", field: "locationCode",type: "like" },
-        { title: "璐т綅鐘舵��", field: "locationStatus" ,type: "selectList",dataKey: "locationStatusEnum",data: [],},
-        { title: "搴撳瓨鐘舵��", field: "stockStatus",type: "selectList",dataKey: "stockStatusEmun",data: [],},
-      ],
-      [
-        { title: "鐗╂枡缂栧彿", field: "materielCode",type: "like"},
-        { title: "鎵规鍙�", field: "batchNo",type: "like"},
-        { title: "鎵�灞炰粨搴�", field: "warehouseId",type: "selectList",dataKey: "warehouses",data: [],},
-      ],
-    ]);
-    const columns = ref([
-      {
-        field: "stockId",
-        title: "Id",
-        type: "int",
-        width: 90,
-        hidden: true,
-        readonly: true,
-        require: true,
-        align: "left",
-      },
-      {
-        field: "palletCode",
-        title: "鎵樼洏缂栧彿",
-        type: "string",
-        width: 150,
-        link: true,
-        align: "left",
-      },
-      {
-        field: "locationCode",
-        title: "璐т綅缂栧彿",
-        type: "string",
-        width: 200,
-        align: "left",
-      },
-      {
-        field: "locationName",
-        title: "璐т綅鍚嶇О",
-        type: "string",
-        width: 270,
-        align: "left",
-      },
-      {
-        field: "warehouseId",
-        title: "鎵�灞炰粨搴�",
-        type: "string",
-        width: 80,
-        align: "left",
-        bind: { key: "warehouses", data: [] },
-      },
-      {
-        field: "roadwayNo",
-        title: "宸烽亾缂栧彿",
-        type: "decimal",
-        width: 100,
-        align: "left",
-        hidden:true
-      },
-      {
-        field: "materielCode",
-        title: "鎵�鍚墿鏂欑紪鍙�",
-        type: "string",
-        width: 120,
-        align: "left",
-      },
-      {
-        field: "batchNo",
-        title: "鎵�鍚墿鏂欐壒娆�",
-        type: "string",
-        width: 200,
-        align: "left"
-      },
-      {
-        field: "materielInfo",
-        title: "鎵�鍚墿鏂欐渶鏃╀复鏈�",
-        type: "string",
-        width: 140,
-        align: "left",
-      },
-      {
-        field: "sumStock",
-        title: "鎬诲簱瀛�",
-        type: "string",
-        width: 140,
-        align: "left",
-      },
-      {
-        field: "row",
-        title: "璐т綅琛�",
-        type: "string",
-        width: 90,
-        align: "left",
-        hidden: true,
-      },
-      {
-        field: "column",
-        title: "璐т綅鍒�",
-        type: "int",
-        width: 120,
-        align: "left",
-        hidden: true,
-      },
-      {
-        field: "layer",
-        title: "璐т綅灞�",
-        type: "string",
-        width: 200,
-        align: "left",
-        hidden: true,
-      },
-      {
-        field: "depth",
-        title: "璐т綅娣卞害",
-        type: "string",
-        width: 180,
-        align: "left",
-        hidden: true,
-      },
-      {
-        field: "stockStatus",
-        title: "搴撳瓨鐘舵��",
-        type: "string",
-        width: 200,
-        align: "left",
-        bind: { key: "stockStatusEmun", data: [] },
-      },
-      {
-        field: "locationType",
-        title: "璐т綅绫诲瀷",
-        type: "string",
-        width: 100,
-        align: "left",
-        bind:{key: "locationTypeEnum", data: []}
-      },
-      {
-        field: "locationStatus",
-        title: "璐т綅鐘舵��",
-        type: "string",
-        width: 120,
-        align: "left",
-        bind: { key: "locationStatusEnum", data: [] },
-      },
-      {
-        field: "enalbeStatus",
-        title: "绂佺敤鐘舵��",
-        type: "string",
-        width: 80,
-        align: "left",
-        bind: { key: "enableStatusEnum", data: [] },
-      },
-      {
-        field: "creater",
-        title: "鍒涘缓浜�",
-        type: "string",
-        width: 90,
-        align: "left",
-      },
-      {
-        field: "createDate",
-        title: "鍒涘缓鏃堕棿",
-        type: "datetime",
-        width: 160,
-        align: "left",
-      },
-      {
-        field: "modifier",
-        title: "淇敼浜�",
-        type: "string",
-        width: 100,
-        align: "left",
-      },
-      {
-        field: "modifyDate",
-        title: "淇敼鏃堕棿",
-        type: "datetime",
-        width: 160,
-        align: "left",
-      },
-      {
-        field: "remark",
-        title: "澶囨敞",
-        type: "string",
-        width: 100,
-        align: "left",
-        hidden:true
-      },
-    ]);
-    const detail = ref({
-      cnName: "搴撳瓨鏄庣粏淇℃伅",
-      table: "StockInfoDetail",
-      columns: [
-        {
-          field: "id",
-          title: "Id",
-          type: "int",
-          width: 90,
-          hidden: true,
-          readonly: true,
-          require: true,
-          align: "left",
-        },
-        {
-          field: "stockId",
-          title: "搴撳瓨淇℃伅涓婚敭",
-          type: "string",
-          width: 90,
-          align: "left",
-          hidden: true
-        },
-        {
-          field: "materielCode",
-          title: "鐗╂枡缂栧彿",
-          type: "string",
-          width: 110,
-          align: "left",
-        },
-        {
-          field: "materielName",
-          title: "鐗╂枡鍚嶇О",
-          type: "string",
-          width: 130,
-          align: "left",
-        },
-        {
-          field: "orderNo",
-          title: "鍗曟嵁缂栧彿",
-          type: "decimal",
-          width: 130,
-          align: "left",
-        },
-        {
-          field: "batchNo",
-          title: "鎵规鍙�",
-          type: "string",
-          width: 180,
-          align: "left",
-        },
-        {
-          field: "serialNumber",
-          title: "搴忓垪鍙�",
-          type: "int",
-          width: 120,
-          align: "left",
-          hidden: true,
-        },
-        {
-          field: "stockQuantity",
-          title: "搴撳瓨鏁伴噺",
-          type: "string",
-          width: 80,
-          align: "left",
-        },
-        {
-          field: "outboundQuantity",
-          title: "鍑哄簱鏁伴噺",
-          type: "string",
-          width: 80,
-          align: "left",
-        },
-        {
-          field: "unit",
-          title: "鍗曚綅",
-          type: "string",
-          width: 50,
-          align: "left",
-        },
-        {
-          field: "productionDate",
-          title: "鐢熶骇鏃ユ湡",
-          type: "string",
-          width: 80,
-          align: "left",
-        },
-        {
-          field: "effectiveDate",
-          title: "鏈夋晥鏃ユ湡",
-          type: "string",
-          width: 80,
-          align: "left",
-        },
-        {
-          field: "status",
-          title: "搴撳瓨鏄庣粏鐘舵��",
-          type: "string",
-          width: 120,
-          align: "left",
-          bind: { key: "stockStatusEmun", data: [] }
-        },
-        {
-          field: "creater",
-          title: "鍒涘缓浜�",
-          type: "string",
-          width: 90,
-          align: "left",
-          hidden: true
-        },
-        {
-          field: "createDate",
-          title: "鍒涘缓鏃堕棿",
-          type: "datetime",
-          width: 160,
-          align: "left",
-          hidden: true
-        },
-        {
-          field: "modifier",
-          title: "淇敼浜�",
-          type: "string",
-          width: 100,
-          align: "left",
-          hidden: true
-        },
-        {
-          field: "modifyDate",
-          title: "淇敼鏃堕棿",
-          type: "datetime",
-          width: 160,
-          align: "left",
-          hidden: true
-        },
-        {
-          field: "remark",
-          title: "澶囨敞",
-          type: "string",
-          width: 100,
-          align: "left",
-          hidden: true
-        },
-      ],
-      sortName: "id",
-      key: "id",
-    });
+
+<script>
+import { ElButton, ElMessage, ElSelect, ElOption, ElEmpty, ElSkeleton } from "element-plus";
+
+export default {
+  data() {
     return {
-      table,
-      extend,
-      editFormFields,
-      editFormOptions,
-      searchFormFields,
-      searchFormOptions,
-      columns,
-      detail,
+      warehouseList: [],
+      roadwayNoList: [],
+      selectedWarehouse: null,
+      selectedRoadwayNo: null,
+      selectedLocationCode: null,
+      infoMsg: [
+        { bgcolor: "#2BB3D5", msg: "绌鸿揣浣�" },
+        { bgcolor: "orange", msg: "鏈夎揣" },
+        { bgcolor: "lightgreen", msg: "閿佸畾" },
+        { bgcolor: "#ccc", msg: "绂佺敤" }
+      ],
+      locationData: [],
+      showTooltipFlag: false,
+      currentLocation: null,
+      tooltipPosition: { x: 0, y: 0 },
+      currentColumn: null,
+      currentLayer: null,
+      loading: false
     };
   },
-});
+  computed: {
+    sortedLayerData() {
+      const layerMap = {};
+
+      this.locationData.forEach(layer => {
+        if (!layerMap[layer.layer]) {
+          layerMap[layer.layer] = {
+            layer: layer.layer,
+            columns: []
+          };
+        }
+
+        layer.columns?.forEach(column => {
+          layerMap[layer.layer].columns.push({
+            column: column.column,
+            depths: column.depths || []
+          });
+        });
+      });
+
+      return Object.values(layerMap).sort((a, b) => a.layer - b.layer);
+    },
+
+    totalLocations() {
+      let count = 0;
+      this.locationData.forEach(layer => {
+        layer.columns?.forEach(column => {
+          count += column.depths?.length || 0;
+        });
+      });
+      return count;
+    }
+  },
+  methods: {
+    // 鎸夎鍒嗙粍鏁版嵁
+    getRowGroups(layer) {
+      const rowMap = {};
+      
+      // 閬嶅巻鎵�鏈夊垪鍜屾繁搴︼紝鎸夎鍒嗙粍
+      layer.columns?.forEach(column => {
+        column.depths?.forEach(depth => {
+          const row = depth.row || '?';
+          
+          if (!rowMap[row]) {
+            rowMap[row] = {
+              row: row,
+              locations: [],
+              columns: {}
+            };
+          }
+          
+          // 娣诲姞鍒拌琛岀殑浣嶇疆鍒楄〃
+          rowMap[row].locations.push({
+            ...depth,
+            column: column.column,
+            layer: layer.layer
+          });
+          
+          // 鎸夊垪缁勭粐鏁版嵁
+          if (!rowMap[row].columns[column.column]) {
+            rowMap[row].columns[column.column] = {
+              column: column.column,
+              depths: []
+            };
+          }
+          
+          rowMap[row].columns[column.column].depths.push(depth);
+        });
+      });
+      
+      // 杞崲涓烘暟缁勫苟鎸夎鎺掑簭
+      return Object.values(rowMap)
+        .sort((a, b) => this.compareRows(a.row, b.row));
+    },
+
+    sortedColumns(columnsObj) {
+      // 灏嗗璞¤浆鎹负鏁扮粍骞舵寜鍒楀彿鎺掑簭
+      const columns = Object.values(columnsObj || {});
+      return columns.sort((a, b) => a.column - b.column);
+    },
+
+    // 姣旇緝琛屽彿鐨勮緟鍔╂柟娉�
+    compareRows(rowA, rowB) {
+      // 濡傛灉閮芥槸鏁板瓧锛屾寜鏁板瓧姣旇緝
+      if (!isNaN(rowA) && !isNaN(rowB)) {
+        return Number(rowA) - Number(rowB);
+      }
+      // 鍚﹀垯鎸夊瓧绗︿覆姣旇緝
+      return String(rowA).localeCompare(String(rowB));
+    },
+
+    // 鑾峰彇浣嶇疆淇℃伅鐢ㄤ簬鏄剧ず
+    getLocationPositionForDisplay(location, column, layer) {
+      if (!location) return '';
+      const row = location.row || '?';
+      const depthText = location.depth === 1 ? '娴�' : '娣�';
+      return `${row}鎺�${column}鍒�${layer}灞�${depthText}`;
+    },
+
+    // 鑾峰彇浣嶇疆淇℃伅锛堢敤浜庢偓娴彁绀烘锛�
+    getLocationPosition(location) {
+      if (!location || !this.currentColumn || !this.currentLayer) return '--';
+      const row = location.row || '?';
+      const depthText = location.depth === 1 ? '娴�' : '娣�';
+      return `${row}鎺�-${this.currentColumn}鍒�-${this.currentLayer}灞�-${depthText}`;
+    },
+
+    async fetchWarehouseData() {
+      try {
+        this.loading = true;
+        const response = await this.http.get("/api/LocationInfo/GetArea");
+        this.warehouseList = response.data || [];
+
+        if (this.warehouseList.length > 0) {
+          this.selectedWarehouse = this.warehouseList[0].warehouseId;
+          this.roadwayNoList = this.warehouseList[0].roadwayNo || [];
+
+          if (this.roadwayNoList.length > 0) {
+            this.selectedRoadwayNo = this.roadwayNoList[0];
+            await this.fetchLocationStatus();
+          }
+        }
+      } catch (error) {
+        console.error("鑾峰彇浠撳簱鏁版嵁澶辫触:", error);
+        this.warehouseList = [];
+        this.roadwayNoList = [];
+        ElMessage.error("鑾峰彇浠撳簱鏁版嵁澶辫触锛岃绋嶅悗閲嶈瘯");
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    async fetchLocationStatus() {
+      if (!this.selectedWarehouse || !this.selectedRoadwayNo) {
+        ElMessage.warning("璇烽�夋嫨浠撳簱鍜屽贩閬�");
+        return;
+      }
+
+      try {
+        this.loading = true;
+        const response = await this.http.get(
+          `/api/LocationInfo/GetLocationStatus?WarehouseId=${this.selectedWarehouse}&RoadwayNo=${this.selectedRoadwayNo}`
+        );
+
+        if (response.data && response.status) {
+          this.locationData = response.data || [];
+
+          // 楠岃瘉鏁版嵁
+          console.log("璐т綅鏁版嵁:", this.locationData);
+          if (this.locationData.length > 0 && this.locationData[0].columns) {
+            console.log("绀轰緥璐т綅:", this.locationData[0].columns[0]?.depths?.[0]);
+          }
+
+          if (this.locationData.length === 0) {
+            ElMessage.info("璇ュ贩閬撴病鏈夎揣浣嶆暟鎹�");
+          }
+        } else {
+          this.locationData = [];
+          ElMessage.error(response.data?.message || "鑾峰彇璐т綅鐘舵�佸け璐�");
+        }
+      } catch (error) {
+        console.error("鑾峰彇璐т綅鐘舵�佸け璐�:", error);
+        this.locationData = [];
+        ElMessage.error("鑾峰彇璐т綅鐘舵�佸け璐ワ紝璇风◢鍚庨噸璇�");
+      } finally {
+        this.loading = false;
+      }
+    },
+
+    handleWarehouseChange() {
+      const selectedWarehouse = this.warehouseList.find(
+        w => w.warehouseId === this.selectedWarehouse
+      );
+      this.roadwayNoList = selectedWarehouse ? selectedWarehouse.roadwayNo : [];
+      this.selectedRoadwayNo = this.roadwayNoList.length > 0 ? this.roadwayNoList[0] : null;
+      this.fetchLocationStatus();
+    },
+
+    getWarehouseName(warehouseId) {
+      const warehouseMap = {
+        1: '鍘熸潗鏂欎粨',
+        2: '鎴愬搧浠�'
+      };
+      return warehouseMap[warehouseId] || `浠撳簱 ${warehouseId}`;
+    },
+
+    handleRoadwayNoChange() {
+      this.fetchLocationStatus();
+    },
+
+    getLocationStatusClass(depth) {
+      if (depth.enableStatus !== 0) {
+        return 'location-disabled';
+      }
+
+      switch (depth.locationStatus) {
+        case 0: return 'location-empty';     // 绌鸿揣浣�
+        case 1: return 'location-locked';    // 閿佸畾
+        case 100: return 'location-occupied'; // 鏈夎揣
+        default: return 'location-other';
+      }
+    },
+
+    getLayerLocations(layer) {
+      let count = 0;
+      layer.columns?.forEach(column => {
+        count += column.depths?.length || 0;
+      });
+      return count;
+    },
+
+    showTooltip(depth, column, layer, event) {
+      this.currentLocation = depth;
+      this.currentColumn = column;
+      this.currentLayer = layer;
+      this.showTooltipFlag = true;
+
+      const offsetX = 15;
+      const offsetY = 15;
+      this.tooltipPosition = {
+        x: event.clientX + offsetX,
+        y: event.clientY + offsetY,
+      };
+    },
+
+    hideTooltip() {
+      this.showTooltipFlag = false;
+      this.currentLocation = null;
+      this.currentColumn = null;
+      this.currentLayer = null;
+    },
+
+    handleLocationClick(depth) {
+      console.log('鐐瑰嚮璐т綅:', depth);
+      // 杩欓噷鍙互娣诲姞鐐瑰嚮璐т綅鐨勫鐞嗛�昏緫
+      ElMessage.info(`閫変腑璐т綅: ${depth.locationCode || '鏈煡璐т綅'}`);
+    },
+
+    getStatusText(status) {
+      const statusMap = {
+        0: "绌鸿揣浣�",
+        1: "閿佸畾",
+        100: "鏈夎揣",
+      };
+      return statusMap[status] || "鏈煡鐘舵��";
+    },
+
+    getStatusClass(status) {
+      const classMap = {
+        0: 'status-empty',
+        1: 'status-locked',
+        100: 'status-occupied'
+      };
+      return classMap[status] || '';
+    },
+
+    getLocationTypeText(type) {
+      const typeMap = {
+        1: "甯冨嵎",
+        2: "鏉惧竷鍗�",
+        3: "鎴愬搧璐т綅"
+      };
+      return typeMap[type] || "鏈煡绫诲瀷";
+    },
+
+    getEnableStatusText(status) {
+      return status === 0 ? '鍚敤' : '绂佺敤';
+    }
+  },
+  mounted() {
+    this.fetchWarehouseData();
+  },
+  components: {
+    ElButton,
+    ElSelect,
+    ElOption,
+    ElEmpty,
+    ElSkeleton
+  },
+};
 </script>
-    
\ No newline at end of file
+
+<style scoped>
+/* 鏍峰紡閮ㄥ垎 */
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  padding: 16px;
+  box-sizing: border-box;
+  background-color: #f0f2f5;
+}
+
+.content-wrapper {
+  display: flex;
+  flex: 1;
+  min-height: 0;
+  gap: 16px;
+}
+
+.control-panel {
+  width: 260px;
+  background-color: white;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  display: flex;
+  flex-direction: column;
+  flex-shrink: 0;
+  overflow: hidden;
+}
+
+.panel-header {
+  padding: 16px;
+  border-bottom: 1px solid #e8e8e8;
+  background-color: #fafafa;
+}
+
+.panel-header h3 {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.panel-body {
+  padding: 16px;
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+}
+
+.form-group {
+  margin-bottom: 0;
+}
+
+.form-label {
+  display: block;
+  margin-bottom: 6px;
+  font-size: 14px;
+  color: #666;
+  font-weight: 500;
+}
+
+.full-width {
+  width: 100%;
+}
+
+.refresh-btn {
+  margin-top: 8px;
+  width: 100%;
+  height: 32px;
+}
+
+.legend-section {
+  margin-top: 8px;
+  padding-top: 16px;
+  border-top: 1px solid #e8e8e8;
+}
+
+.legend-header h4 {
+  margin: 0 0 12px 0;
+  font-size: 15px;
+  font-weight: 600;
+  color: #333;
+}
+
+.legend-list {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.color-box {
+  width: 20px;
+  height: 20px;
+  border-radius: 4px;
+  border: 1px solid rgba(0, 0, 0, 0.1);
+  flex-shrink: 0;
+}
+
+.legend-label {
+  font-size: 13px;
+  color: #666;
+}
+
+.main-content {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  min-width: 0;
+}
+
+.loading-container {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: white;
+  border-radius: 8px;
+  padding: 24px;
+}
+
+.location-container {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  background: white;
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  overflow: hidden;
+  min-height: 0;
+}
+
+.location-header {
+  padding: 16px 20px;
+  background: #fafafa;
+  border-bottom: 1px solid #e8e8e8;
+  flex-shrink: 0;
+}
+
+.location-info {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 14px;
+}
+
+.total-count {
+  font-weight: 600;
+  color: #1890ff;
+}
+
+.layers-container {
+  width: 100%;
+  height: 100%;
+  flex: 1;
+  overflow-y: auto;
+  padding: 20px;
+  display: flex;
+  flex-direction: column;
+  gap: 24px;
+}
+
+.layer-row {
+  background: #f9f9f9;
+  border-radius: 8px;
+  border: 1px solid #e8e8e8;
+  display: flex;
+  flex-direction: column;
+  min-height: auto;
+}
+
+.layer-title-area {
+  padding: 12px 16px;
+  background: #f0f0f0;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.layer-title {
+  margin: 0;
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+}
+
+.layer-count {
+  font-size: 12px;
+  color: #666;
+  background: white;
+  padding: 4px 10px;
+  border-radius: 12px;
+  border: 1px solid #ddd;
+}
+
+.layer-content-wrap {
+  width: 100%;
+  overflow: hidden;
+  flex: 1;
+  padding: 16px;
+}
+
+/* 琛岀粍鏍峰紡 */
+.row-group {
+  margin-bottom: 10px;
+  padding: 12px;
+  background: white;
+  border-radius: 6px;
+  border: 1px solid #e8e8e8;
+  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
+}
+
+.row-group:last-child {
+  margin-bottom: 0;
+}
+
+.row-title {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 12px;
+  padding-bottom: 8px;
+  border-bottom: 1px dashed #e8e8e8;
+}
+
+.row-label {
+  font-size: 14px;
+  font-weight: 600;
+  color: #333;
+}
+
+.row-count {
+  font-size: 12px;
+  color: #666;
+  background: #f0f0f0;
+  padding: 2px 8px;
+  border-radius: 10px;
+}
+
+.row-content {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 8px; /* 鍑忓皬闂磋窛 */
+}
+
+/* 缂╁皬璐т綅妗嗗昂瀵� */
+.location-column {
+  flex: 0 0 auto;
+  width: 70px; /* 鍑忓皬瀹藉害 */
+  min-height: 30px; /* 鍑忓皬楂樺害 */
+  display: flex;
+  flex-direction: column;
+  box-sizing: border-box;
+}
+
+.locations-wrapper {
+  display: flex;
+  flex-direction: column;
+  gap: 4px; /* 鍑忓皬闂磋窛 */
+  flex: 1;
+  min-height: 0;
+}
+
+/* 缂╁皬璐т綅椤� */
+.location-item {
+  min-height: 32px; /* 鍑忓皬楂樺害 */
+  padding: 4px 2px; /* 鍑忓皬鍐呰竟璺� */
+  border-radius: 4px;
+  text-align: center;
+  cursor: pointer;
+  border: 1px solid rgba(0, 0, 0, 0.1);
+  transition: all 0.2s;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 1px;
+  flex: 1;
+}
+
+.location-item:hover {
+  transform: scale(1.05);
+  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+  z-index: 10;
+}
+
+/* 缂╁皬璐т綅缂栧彿瀛椾綋 */
+.location-code {
+  font-size: 9px; /* 鍑忓皬瀛椾綋 */
+  font-weight: 500;
+  line-height: 1.2;
+  word-break: break-all;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  max-width: 100%;
+}
+
+.location-status {
+  font-size: 8px; /* 鍑忓皬瀛椾綋 */
+  padding: 1px 3px;
+  border-radius: 2px;
+  background: rgba(0, 0, 0, 0.1);
+}
+
+/* 璐т綅鐘舵�侀鑹� */
+.location-empty {
+  background-color: #2BB3D5;
+  color: white;
+}
+
+.location-occupied {
+  background-color: orange;
+  color: white;
+}
+
+.location-locked {
+  background-color: lightgreen;
+  color: #333;
+}
+
+.location-disabled {
+  background-color: #ccc;
+  color: #666;
+  cursor: not-allowed;
+}
+
+.location-other {
+  background-color: #b7ba6b;
+  color: white;
+}
+
+.empty-container {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: white;
+  border-radius: 8px;
+}
+
+.location-tooltip {
+  position: fixed;
+  z-index: 9999;
+  background-color: white;
+  border: 1px solid #ddd;
+  border-radius: 6px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  pointer-events: none;
+  min-width: 220px;
+  max-width: 300px;
+}
+
+.tooltip-content {
+  overflow: hidden;
+}
+
+.tooltip-header {
+  padding: 12px 16px;
+  background-color: #1890ff;
+  color: white;
+}
+
+.tooltip-header h4 {
+  margin: 0;
+  font-size: 14px;
+  font-weight: 600;
+}
+
+.tooltip-body {
+  padding: 12px 16px;
+}
+
+.tooltip-row {
+  display: flex;
+  margin-bottom: 8px;
+  font-size: 13px;
+  line-height: 1.4;
+}
+
+.tooltip-row:last-child {
+  margin-bottom: 0;
+}
+
+.tooltip-label {
+  flex: 0 0 80px;
+  color: #666;
+  font-weight: 500;
+}
+
+.tooltip-value {
+  flex: 1;
+  color: #333;
+  word-break: break-all;
+}
+
+.status-disabled {
+  color: #f5222d;
+}
+
+/* 婊氬姩鏉℃牱寮� */
+.layers-container::-webkit-scrollbar {
+  width: 8px;
+}
+
+.layers-container::-webkit-scrollbar-track {
+  background: #f1f1f1;
+  border-radius: 4px;
+}
+
+.layers-container::-webkit-scrollbar-thumb {
+  background: #c1c1c1;
+  border-radius: 4px;
+}
+
+.layers-container::-webkit-scrollbar-thumb:hover {
+  background: #a8a8a8;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1200px) {
+  .location-column {
+    width: 95px;
+  }
+}
+
+@media (max-width: 768px) {
+  .content-wrapper {
+    flex-direction: column;
+  }
+
+  .control-panel {
+    width: 100%;
+  }
+
+  .location-column {
+    width: 90px;
+  }
+
+  .row-content {
+    gap: 6px;
+  }
+}
+
+@media (max-width: 480px) {
+  .location-column {
+    width: 80px;
+  }
+
+  .location-code {
+    font-size: 8px;
+  }
+
+  .row-content {
+    gap: 4px;
+  }
+
+  .row-group {
+    padding: 8px;
+  }
+}
+
+@media (max-width: 380px) {
+  .location-column {
+    width: 70px;
+  }
+  
+  .location-code {
+    font-size: 7px;
+  }
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3