ÏîÄ¿´úÂë/WMS/WMSClient/src/views/Home.vue
@@ -27,9 +27,9 @@
                class="full-width">
                <el-option v-for="item in warehouseList" :value="item" :label="item" :key="item"></el-option>
              </el-select>
              <h4>货位排</h4>
              <el-select size="mini" @change="SCChange" v-model="Area.row" placeholder="请选择排" class="full-width">
                <el-option v-for="item in scList" :value="item" :label="'第' + item + '排'" :key="item"></el-option>
              <h4>巷道</h4>
              <el-select size="mini" @change="SCChange" v-model="Area.roadwayNo" placeholder="请选择巷道" class="full-width">
                <el-option v-for="item in scList" :value="item" :label="item" :key="item"></el-option>
              </el-select>
              <el-button type="success" class="refresh-btn" @click="GetViewData">
                åˆ·æ–°
@@ -50,25 +50,37 @@
        <!-- è´§ä½å±•示区域 -->
        <div v-if="loading" class="loading-container">
          <el-icon class="is-loading">
            <Loading />
          </el-icon>
          <span>加载中...</span>
        </div>
        <div v-else-if="locationData.length === 0" class="empty-container">
        <div
          v-else-if="(!locationData.row1 || locationData.row1.length === 0) && (!locationData.row2 || locationData.row2.length === 0)"
          class="empty-container">
          <el-empty description="暂无数据" />
        </div>
        <div v-else>
          <div class="location-view">
            <div class="layer-container" v-for="(item, index) in locationData" :key="index">
              <h3 class="layer-title">第{{ item.layer }}层</h3>
              <div class="row">
            <!-- ç¬¬1排(东面) -->
            <div class="roadway-section">
              <h2 class="roadway-title">{{ Area.roadwayNo }} ç¬¬1巷道第1排(东面:北>南)</h2>
              <div class="row" v-for="(item, index) in locationData.row1" :key="'row1-' + index">
                <div class="location-cell" :style="{ 'background-color': GetBgColor(column) }"
                  v-for="(column, index) in item.locationObj" :key="index" @mouseenter="showTooltip(column, $event)"
                  @mouseleave="hideTooltip">
                  {{ column.row }}-{{ column.column }}-{{ column.layer }}
                  v-for="(column, colIndex) in item.locationObj" :key="'row1-' + item.layer + '-' + colIndex"
                  @mouseenter="showTooltip(column, $event)" @mouseleave="hideTooltip">
                  {{ getRoadwayNo(column) }}-{{ column.column }}-{{ column.layer }}
                </div>
              </div>
            </div>
            <!-- ç¬¬2排(西面) -->
            <div class="roadway-section">
              <h2 class="roadway-title">{{ Area.roadwayNo }} ç¬¬1巷道第2排(西面:北>南)</h2>
              <div class="row" v-for="(item, index) in locationData.row2" :key="'row2-' + index">
                <div class="location-cell" :style="{ 'background-color': GetBgColor(column) }"
                  v-for="(column, colIndex) in item.locationObj" :key="'row2-' + item.layer + '-' + colIndex"
                  @mouseenter="showTooltip(column, $event)" @mouseleave="hideTooltip">
                  {{ getRoadwayNo(column) }}-{{ column.column }}-{{ column.layer }}
                </div>
              </div>
            </div>
@@ -79,36 +91,30 @@
            top: tooltipPosition.y + 'px',
          }">
            <div v-if="currentLocation">
              <p><strong>仓库:</strong>{{ Area.warehouse || "未选择" }}</p>
              <p><strong>货位号:</strong>{{ currentLocation.locationCode }}</p>
              <!-- <p><strong>料箱号:</strong>{{ currentLocation.barCode ? currentLocation.barCode : "无料箱" }}</p> -->
              <p><strong>仓库:</strong><span>{{ Area.warehouse || "未选择" }}</span></p>
              <p><strong>货位号:</strong><span>{{ currentLocation.locationCode }}</span></p>
              <!-- æ ¹æ®ä»“库类型显示不同的标签和内容 -->
              <p v-if="Area.warehouse === '原料库'">
                <strong>RFID:</strong>{{ this.rfidData[currentLocation.locationCode] || "无" }}
              </p>
              <p v-else-if="Area.warehouse === '成品库'">
                <strong>托盘号:</strong>{{ this.rfidData[currentLocation.locationCode] || "无" }}
              </p>
              <p v-else>
                <strong>标识:</strong>{{ this.rfidData[currentLocation.locationCode] || "无" }}
              </p>
              <!-- åŽŸæ–™åº“æ˜¾ç¤ºå†…å®¹ -->
              <div v-if="Area.warehouse === '原料库'">
                <p><strong>纸卷:</strong><span>{{ currentLocation.paperRoll || "无" }}</span></p>
                <p><strong>门幅:</strong><span>{{ currentLocation.width ? currentLocation.width + "m" : "无" }}</span></p>
                <p><strong>条码:</strong><span>{{ currentLocation.barcode || "无" }}</span></p>
                <p><strong>RFID:</strong><span>{{ currentLocation.rfid || "无" }}</span></p>
              </div>
              <!-- æˆå“åº“显示内容 -->
              <div v-else-if="Area.warehouse === '成品库'">
                <p><strong>成品名称:</strong><span>{{ currentLocation.productName || currentLocation.paperRoll || "无" }}</span></p>
                <p><strong>成品数量:</strong><span>{{ currentLocation.quantity || currentLocation.width || "无" }}</span></p>
                <p><strong>托盘号:</strong><span>{{ currentLocation.rfid || currentLocation.rfidCode ||
                  this.rfidData[currentLocation.locationCode] || "无" }}</span></p>
              </div>
              <p>
                <strong>排列层:</strong> {{ currentLocation.row }}排{{
                  currentLocation.column
                }}列{{ currentLocation.layer }}层
                <strong>排列层:</strong> <span>{{ currentLocation.row }}排{{ currentLocation.column }}列{{ currentLocation.layer
                }}层</span>
              </p>
              <p><strong>状态:</strong> {{ getStatusText(currentLocation) }}</p>
              <!-- <p>
                <strong>禁用:</strong>
                {{ currentLocation.location_lock == 3 ? "是" : "否" }}
              </p> -->
              <!-- <p v-if="currentLocation.location_state > 0">
                <strong>物料编码:</strong>
                {{ currentLocation.material_code || "无" }}
              </p>
              <p v-if="currentLocation.location_state > 0">
                <strong>数量:</strong> {{ currentLocation.quantity || "无" }}
              </p> -->
              <p><strong>状态:</strong> <span>{{ getStatusText(currentLocation) }}</span></p>
              <p><strong>入库日期:</strong><span>{{ currentLocation.inDate ? new Date(currentLocation.inDate).toLocaleString() :
                "无" }}</span></p>
            </div>
          </div>
        </div>
@@ -116,53 +122,68 @@
    </template>
<script>
import { ElButton, Loading } from "element-plus";
import { ElButton } from "element-plus";
export default {
  data() {
      return {
        slectData: [],
        scList: [],
        warehouseList: ["原料库", "成品库"],
        warehouseMap: {
          "原料库": 1,
          "成品库": 2
        },
        Area: {
          warehouse: "原料库",
          row: "",
          shelf_code: ""
        },
        mian_height: "",
        loading: false,
        infoMsg: [
          { bgcolor: "lightgreen", msg: "空闲", state: 0 },
          { bgcolor: "orange", msg: "有货", state: 100 },
          { bgcolor: "#2BB3D5", msg: "锁定", state: 1 },
          { bgcolor: "yellow", msg: "空闲锁定", state: 20 },
          { bgcolor: "purple", msg: "有货锁定", state: 10 },
        ],
        locationData: [],
        showTooltipFlag: false,
        currentLocation: null,
        tooltipPosition: { x: 0, y: 0 },
        rfidData: {}, // å­˜å‚¨è´§ä½ç¼–号与RFID的映射关系
      };
    },
    return {
      slectData: [],
      scList: [],
      allRoadways: [], // ä¿å­˜æ‰€æœ‰å··é“列表
      warehouseList: ["原料库", "成品库"],
      warehouseMap: {
        "原料库": 1,
        "成品库": 2
      },
      // å··é“类型映射
      roadwayTypeMap: {
        "原料库": ["SC01_YL", "SC02_YL", "SC03_YLDual", "SC04_YLDual", "SC05_YLDual"],
        "成品库": ["SC01_CP", "SC02_CP", "SC03_CP", "SC04_CP", "SC05_CP"]
      },
      Area: {
        warehouse: "原料库",
        roadwayNo: "",
        shelf_code: ""
      },
      mian_height: "",
      loading: false,
      infoMsg: [
        { bgcolor: "#f0f0f0", msg: "空闲", state: 0 },
        { bgcolor: "#90ee90", msg: "有货", state: 100 },
        { bgcolor: "#a0a0a0", msg: "空闲锁定", state: 20 },
        { bgcolor: "#228b22", msg: "有货锁定", state: 10 },
        { bgcolor: "#2BB3D5", msg: "专用货位", state: 3 },
      ],
      locationData: [],
      showTooltipFlag: false,
      currentLocation: null,
      tooltipPosition: { x: 0, y: 0 },
      rfidData: {}, // å­˜å‚¨è´§ä½ç¼–号与RFID的映射关系
    };
  },
  computed: {
    GetBgColor() {
      return (col) => {
        var bgColor = "";
        //优先显示禁用状态
        if (col.location_lock > 0) {
          this.infoMsg.forEach((el) => {
            if (el.state === col.location_lock) {
              bgColor = el.bgcolor;
            }
          });
        }
        else {
          return "lightgreen";
        //根据状态设置颜色
        switch (col.location_lock) {
          case 0: //空闲
            bgColor = "#f0f0f0"; //很浅灰
            break;
          case 20: //空闲锁定
            bgColor = "#a0a0a0"; //深灰
            break;
          case 100: //有货
            bgColor = "#90ee90"; //浅绿
            break;
          case 10: //有货锁定
            bgColor = "#228b22"; //深绿
            break;
          case 3: //专用库位
            bgColor = "#2BB3D5"; //蓝色(不变)
            break;
          default:
            bgColor = "#f0f0f0"; //默认很浅灰
        }
        return bgColor;
      };
@@ -187,16 +208,25 @@
          console.log("RFID查询API返回结果:", response);
          if (response.status && response.data) {
            console.log(`成功获取${response.data.length}条RFID记录`);
            // æ›´æ–°rfidData映射
            // å°†RFID数据转换为以locationCode为键的映射
            const rfidDataMap = {};
            response.data.forEach((item, index) => {
              try {
                // æ£€æŸ¥å­—段名,支持大小写两种格式
                const locationCode = item.LocationCode || item.locationCode;
                const rfidCode = item.RfidCode || item.rfidCode;
                if (item && locationCode !== undefined) {
                  console.log(`更新RFID数据: ${locationCode} -> ${rfidCode}`);
                  this.rfidData[locationCode] = rfidCode;
                  rfidDataMap[locationCode] = {
                    paperRoll: item.PaperRoll || item.paperRoll || "",
                    productName: item.ProductName || item.productName || item.PaperRoll || item.paperRoll || "", // ä¼˜å…ˆä½¿ç”¨ProductName字段
                    width: item.Width || item.width || 0,
                    quantity: item.Quantity || item.quantity || item.Width || item.width || 0, // ä¼˜å…ˆä½¿ç”¨Quantity字段
                    barcode: item.Barcode || item.barcode || "",
                    rfid: item.RfidCode || item.rfidCode || "",
                    rfidCode: item.RfidCode || item.rfidCode || "", // ç¡®ä¿rfidCode字段存在
                    status: item.Status || item.status || 0,
                    inDate: item.InDate || item.inDate || null
                  };
                } else {
                  console.warn(`跳过无效的RFID数据项(${index}):`, item);
                }
@@ -204,7 +234,58 @@
                console.error(`处理RFID数据项(${index})时出错:`, error, item);
              }
            });
            console.log("更新后的rfidData:", this.rfidData);
            console.log("RFID数据映射:", rfidDataMap);
            // æ›´æ–°è´§ä½æ•°æ®ï¼Œå°†RFID信息合并到对应的货位对象中
            // å¤„理第1排数据
            if (this.locationData.row1) {
              this.locationData.row1.forEach(layer => {
                layer.locationObj.forEach(location => {
                  const rfidInfo = rfidDataMap[location.locationCode];
                  if (rfidInfo) {
                    // æ›´æ–°è´§ä½å¯¹è±¡çš„字段
                    location.paperRoll = rfidInfo.paperRoll;
                    location.productName = rfidInfo.productName; // æ–°å¢žæˆå“åç§°å­—段
                    location.width = rfidInfo.width;
                    location.quantity = rfidInfo.quantity; // æ–°å¢žæˆå“æ•°é‡å­—段
                    location.barcode = rfidInfo.barcode;
                    location.rfid = rfidInfo.rfid;
                    location.rfidCode = rfidInfo.rfidCode; // æ–°å¢žrfidCode字段
                    location.status = rfidInfo.status;
                    location.inDate = rfidInfo.inDate;
                    // æ›´æ–°rfidData映射(保持向后兼容)
                    this.rfidData[location.locationCode] = rfidInfo.rfid || rfidInfo.rfidCode; // ä½¿ç”¨rfid或rfidCode作为托盘号
                  }
                });
              });
            }
            // å¤„理第2排数据
            if (this.locationData.row2) {
              this.locationData.row2.forEach(layer => {
                layer.locationObj.forEach(location => {
                  const rfidInfo = rfidDataMap[location.locationCode];
                  if (rfidInfo) {
                    // æ›´æ–°è´§ä½å¯¹è±¡çš„字段
                    location.paperRoll = rfidInfo.paperRoll;
                    location.productName = rfidInfo.productName; // æ–°å¢žæˆå“åç§°å­—段
                    location.width = rfidInfo.width;
                    location.quantity = rfidInfo.quantity; // æ–°å¢žæˆå“æ•°é‡å­—段
                    location.barcode = rfidInfo.barcode;
                    location.rfid = rfidInfo.rfid;
                    location.rfidCode = rfidInfo.rfidCode; // æ–°å¢žrfidCode字段
                    location.status = rfidInfo.status;
                    location.inDate = rfidInfo.inDate;
                    // æ›´æ–°rfidData映射(保持向后兼容)
                    this.rfidData[location.locationCode] = rfidInfo.rfid || rfidInfo.rfidCode; // ä½¿ç”¨rfid或rfidCode作为托盘号
                  }
                });
              });
            }
            console.log("更新后的货位数据:", this.locationData);
          } else {
            console.log("RFID查询API返回状态失败或数据为空");
          }
@@ -219,6 +300,7 @@
      this.loading = true;
      this.rfidData = {}; // æ¸…空之前的RFID数据
      this.locationData = { row1: [], row2: [] }; // åˆå§‹åŒ–新的数据结构
      let warehouseId = 0;
      if (this.Area.warehouse) {
@@ -226,25 +308,90 @@
        console.log(`当前选择的仓库: ${this.Area.warehouse}, å¯¹åº”çš„warehouseId: ${warehouseId}`);
      }
      console.log(`调用GetLocationStatus API: row=${_this.Area.row}, warehouseId=${warehouseId}`);
      console.log(`调用GetLocationStatus API: roadwayNo=${_this.Area.roadwayNo}, warehouseId=${warehouseId}`);
      this.http
        .post(`/api/LocationInfo/GetLocationStatus?row=${_this.Area.row}&warehouseId=${warehouseId}`, {}, "查询中")
        .post(`/api/LocationInfo/GetLocationStatus?roadwayNo=${_this.Area.roadwayNo}&warehouseId=${warehouseId}`, {}, "查询中")
        .then((x) => {
          console.log("GetLocationStatus API返回结果:", x);
          this.locationData = x.data || [];
          if (x.data) {
            this.locationData = x.data;
            // å¯¹ç¬¬1排数据进行排序
            if (this.locationData.row1) {
              // æŒ‰å±‚号从高到低排序
              this.locationData.row1.sort((a, b) => parseInt(b.layer) - parseInt(a.layer));
              // å¯¹æ¯å±‚内的货位按列号从北到南排序(01-64)
              this.locationData.row1.forEach(layer => {
                layer.locationObj.sort((a, b) => {
                  // ç¡®ä¿åˆ—号按数字顺序排列
                  const colA = parseInt(a.column);
                  const colB = parseInt(b.column);
                  return colA - colB;
                });
              });
            }
            // å¯¹ç¬¬2排数据进行同样的排序
            if (this.locationData.row2) {
              // æŒ‰å±‚号从高到低排序
              this.locationData.row2.sort((a, b) => parseInt(b.layer) - parseInt(a.layer));
              // å¯¹æ¯å±‚内的货位按列号从北到南排序(01-64)
              this.locationData.row2.forEach(layer => {
                layer.locationObj.sort((a, b) => {
                  // ç¡®ä¿åˆ—号按数字顺序排列
                  const colA = parseInt(a.column);
                  const colB = parseInt(b.column);
                  return colA - colB;
                });
              });
            }
          }
          // æå–所有货位编号
          let locationCodes = [];
          this.locationData.forEach(layer => {
            layer.locationObj.forEach(location => {
              locationCodes.push(location.locationCode);
          // æå–第1排货位编号
          if (this.locationData.row1) {
            this.locationData.row1.forEach(layer => {
              layer.locationObj.forEach(location => {
                locationCodes.push(location.locationCode);
                // åˆå§‹åŒ–每个货位的RFID相关字段
                if (!location.paperRoll) location.paperRoll = "无";
                if (!location.productName) location.productName = "无";
                if (!location.width) location.width = 0;
                if (!location.quantity) location.quantity = 0;
                if (!location.barcode) location.barcode = "无";
                if (!location.rfid) location.rfid = "无";
                if (!location.rfidCode) location.rfidCode = "无";
                if (!location.inDate) location.inDate = null;
              });
            });
          });
          }
          // æå–第2排货位编号
          if (this.locationData.row2) {
            this.locationData.row2.forEach(layer => {
              layer.locationObj.forEach(location => {
                locationCodes.push(location.locationCode);
                // åˆå§‹åŒ–每个货位的RFID相关字段
                if (!location.paperRoll) location.paperRoll = "无";
                if (!location.productName) location.productName = "无";
                if (!location.width) location.width = 0;
                if (!location.quantity) location.quantity = 0;
                if (!location.barcode) location.barcode = "无";
                if (!location.rfid) location.rfid = "无";
                if (!location.rfidCode) location.rfidCode = "无";
                if (!location.inDate) location.inDate = null;
              });
            });
          }
          console.log(`从货位数据中提取到${locationCodes.length}个货位编号`);
          console.log("提取的货位编号:", locationCodes);
          // è°ƒç”¨API获取RFID信息
          this.getRfidInfo(locationCodes, warehouseId);
        })
@@ -261,9 +408,24 @@
    SCChange() {
      this.GetViewData();
    },
    // æ ¹æ®ä»“库类型过滤巷道列表
    filterRoadwaysByWarehouse(warehouse) {
      const allowedRoadways = this.roadwayTypeMap[warehouse] || [];
      this.scList = this.allRoadways.filter(roadway => allowedRoadways.includes(roadway));
      // å¦‚果当前选中的巷道不在过滤后的列表中,重置选择
      if (this.Area.roadwayNo && !this.scList.includes(this.Area.roadwayNo)) {
        this.Area.roadwayNo = this.scList[0] || "";
      } else if (!this.Area.roadwayNo && this.scList.length > 0) {
        this.Area.roadwayNo = this.scList[0];
      }
    },
    // åˆ‡æ¢ä»“库
    onWarehouseChange() {
      // åˆ‡æ¢ä»“库时重置排选择
      // æ ¹æ®ä»“库类型过滤巷道列表
      this.filterRoadwaysByWarehouse(this.Area.warehouse);
      // é‡ç½®æŽ’选择后获取数据
      this.GetViewData();
    },
    showTooltip(location, event) {
@@ -283,21 +445,127 @@
    },
    getStatusText(location) {
      // if (location.location_lock === 3) return "禁用";
      if (location.location_lock === 0) return "空闲";
      if (location.location_lock === 1) return "锁定";
      if (location.location_lock === 100) return "有货";
      if (location.location_lock === 20) return "空闲锁定";
      if (location.location_lock === 10) return "有货锁定";
      // if (location.location_state > 0 && location.location_state < 100)
      //   return "锁定";
      return "其他";
    },
    getRoadwayNo(column) {
      // æ ¹æ®ç”¨æˆ·è¦æ±‚的规则生成标准化巷道号
      // å··é“/排:从东到西 11、12、21、22、31、32、41、42、51、52
      // åˆ—:从北到南 01—64
      // å±‚:01—10
      if (column && column.locationCode && column.row) {
        // æå–原始巷道号,如SC01_YL
        const locationCode = column.locationCode;
        const row = column.row;
        const originalRoadwayNo = locationCode.split('-')[0];
        // æ ¹æ®åŽŸå§‹å··é“å·å’Œè¡Œå·æ˜ å°„åˆ°æ ‡å‡†åŒ–å··é“å·
        const standardizedRoadwayMap = {
          // åŽŸæ–™åº“å··é“æ˜ å°„
          // SC01_YL, ç¬¬1排 -> 11,第2排 -> 12
          'SC01_YL': {
            '01': '11',
            '1': '11',
            '02': '12',
            '2': '12'
          },
          // SC02_YL, ç¬¬1排 -> 21,第2排 -> 22
          'SC02_YL': {
            '01': '21',
            '1': '21',
            '02': '22',
            '2': '22'
          },
          // SC03_YLDual, ç¬¬1排 -> 31,第2排 -> 32
          'SC03_YLDual': {
            '01': '31',
            '1': '31',
            '02': '32',
            '2': '32'
          },
          // SC04_YLDual, ç¬¬1排 -> 41,第2排 -> 42
          'SC04_YLDual': {
            '01': '41',
            '1': '41',
            '02': '42',
            '2': '42'
          },
          // SC05_YLDual, ç¬¬1排 -> 51,第2排 -> 52
          'SC05_YLDual': {
            '01': '51',
            '1': '51',
            '02': '52',
            '2': '52'
          },
          // æˆå“åº“巷道映射
          // SC01_CP, ç¬¬1排 -> 11,第2排 -> 12
          'SC01_CP': {
            '01': '11',
            '1': '11',
            '02': '12',
            '2': '12'
          },
          // SC02_CP, ç¬¬1排 -> 21,第2排 -> 22
          'SC02_CP': {
            '01': '21',
            '1': '21',
            '02': '22',
            '2': '22'
          },
          // SC03_CP, ç¬¬1排 -> 31,第2排 -> 32
          'SC03_CP': {
            '01': '31',
            '1': '31',
            '02': '32',
            '2': '32'
          },
          // SC04_CP, ç¬¬1排 -> 41,第2排 -> 42
          'SC04_CP': {
            '01': '41',
            '1': '41',
            '02': '42',
            '2': '42'
          },
          // SC05_CP, ç¬¬1排 -> 51,第2排 -> 52
          'SC05_CP': {
            '01': '51',
            '1': '51',
            '02': '52',
            '2': '52'
          }
        };
        // ä»Žcolumn.row获取行号,注意column.row是带前导零的字符串
        const rowStr = row;
        // æŸ¥æ‰¾æ˜ å°„
        if (standardizedRoadwayMap[originalRoadwayNo]) {
          const rowMap = standardizedRoadwayMap[originalRoadwayNo];
          if (rowMap[rowStr]) {
            return rowMap[rowStr];
          }
          // å°è¯•不带前导零的情况
          const rowStrWithoutZero = rowStr.replace(/^0/, '');
          if (rowMap[rowStrWithoutZero]) {
            return rowMap[rowStrWithoutZero];
          }
        }
        // å¦‚果没有匹配的映射,返回原始巷道号
        return originalRoadwayNo;
      }
      return '';
    },
    getWarehouseName(location) {
      if (location.warehouseId === 1) return "原料库";
      if (location.warehouseId === 2) return "成品库";
      return "未知仓库";
    },
    }
  },
  mounted() {
    var mainHeight = document.getElementById("vol-main");
@@ -307,27 +575,28 @@
    var _this = this;
    //加载下拉选项
    this.http.post("/api/LocationInfo/GetRow", {}, "查询中").then((x) => {
      //加载第一个区域,第一排
      // _this.Area.shelf_code = _this.slectData[0].shelf_code;
      _this.scList = x.data;
      //保存所有巷道
      _this.allRoadways = x.data;
      //根据当前仓库类型过滤巷道
      _this.filterRoadwaysByWarehouse(_this.Area.warehouse);
      if (_this.scList.length > 0) {
        _this.Area.row = _this.scList[0];
        _this.Area.roadwayNo = _this.scList[0];
      }
      _this.GetViewData();
    });
  },
  components: { ElButton, Loading },
  components: { ElButton }
};
</script>
<style scoped>
.container {
      display: flex;
      flex-direction: column;
      height: 100%;
      width: 100%;
      padding: 10px;
    }
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  padding: 10px;
}
.header {
  text-align: center;
@@ -384,41 +653,53 @@
}
.location-view {
      flex: 1;
      width: 100%;
      max-width: 100%;
      overflow: auto;
      padding: 10px;
      background-color: white;
      border-radius: 4px;
    }
.layer-container {
  margin-bottom: 25px;
}
.layer-title {
  margin: 0 0 10px 0;
  font-size: 16px;
  color: #333;
  flex: 1;
  width: 470%;
  max-width: 470%;
  overflow: auto;
  padding: 20px;
  background-color: #f5f7fa;
  border-radius: 8px;
}
.row {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 8px;
  cursor: pointer;
  flex-wrap: nowrap;
}
.location-cell {
  width: 85px;
  height: 38px;
  margin: 3px;
  width: 120px;
  height: 50px;
  margin: 5px;
  text-align: center;
  font-size: 14px;
  border-radius: 3px;
  line-height: 38px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  font-size: 16px;
  border-radius: 4px;
  line-height: 50px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
  border: 1px solid #ccc;
  background-color: #f9f9f9;
}
/* å··é“区域样式 */
.roadway-section {
  margin-bottom: 40px;
  padding: 20px;
  background-color: white;
  border-radius: 6px;
  border: 1px solid #eaeaea;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.roadway-title {
  margin: 0 0 20px 0;
  font-size: 24px;
  font-weight: bold;
  color: #2c3e50;
  text-align: left;
  padding-bottom: 15px;
  border-bottom: 3px solid #409EFF;
}
.location-tooltip {
@@ -427,22 +708,37 @@
  background-color: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px;
  padding: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  pointer-events: none;
  max-width: 250px;
  min-width: 280px;
  max-width: 320px;
}
.location-tooltip p {
  margin: 5px 0;
  font-size: 13px;
  line-height: 1.4;
  margin: 6px 0;
  font-size: 14px;
  line-height: 1.5;
  display: flex;
  align-items: center;
}
.location-tooltip strong {
  display: inline-block;
  width: 70px;
  color: #666;
  width: 80px;
  color: #555;
  font-weight: 600;
  text-align: right;
  margin-right: 12px;
  flex-shrink: 0;
}
.location-tooltip span {
  display: inline-block;
  color: #333;
  font-weight: 500;
  flex: 1;
  text-align: left;
}
.form-group {