You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现表格悬停时显示对应商品其他门店库存的Tooltip功能

我来帮你搞定这个悬停Tooltip显示错误的问题!核心问题就是之前的Tooltip没有和当前悬停的SKU做绑定,导致一触发就把所有商品的库存都掏出来了。下面是具体的实现思路和代码示例,完全贴合你的需求:

解决方案核心思路
  1. 数据按SKU分组存储:从数据库拉取库存时,把每个SKU对应的4个门店库存都存在一起(比如一个对象数组,每个元素对应一个SKU的全量库存)。
  2. 给库存单元格绑定SKU标识:主表格里每个门店的"In Stock"单元格,都用data-sku属性和当前行的SKU关联起来,确保悬停时能精准定位到对应商品。
  3. 动态生成Tooltip内容:每次悬停时,只根据当前SKU筛选出其他3个门店的库存,生成专属的小表格,而不是提前渲染所有商品的库存。
  4. 权限过滤:始终排除当前用户所属门店的库存,只展示其他门店的数据。
原生HTML+JS实现示例

主表格结构

<!-- 主库存表格(假设当前用户是伦敦门店) -->
<table id="inventory-table" border="1" cellpadding="8">
  <thead>
    <tr>
      <th>SKU</th>
      <th>商品名称</th>
      <th>In Stock (London)</th>
    </tr>
  </thead>
  <tbody>
    <!-- 动态渲染的商品行,每个行对应一个SKU -->
    <tr>
      <td>SKU-001</td>
      <td>无线耳机</td>
      <td class="stock-cell" data-sku="SKU-001">15</td>
    </tr>
    <tr>
      <td>SKU-002</td>
      <td>蓝牙音箱</td>
      <td class="stock-cell" data-sku="SKU-002">8</td>
    </tr>
    <tr>
      <td>SKU-003</td>
      <td>充电底座</td>
      <td class="stock-cell" data-sku="SKU-003">22</td>
    </tr>
  </tbody>
</table>

<!-- 全局Tooltip容器,初始隐藏 -->
<div id="stock-tooltip" style="display: none; position: absolute; background: #fff; border: 1px solid #ddd; border-radius: 4px; padding: 8px; z-index: 9999; box-shadow: 0 2px 8px rgba(0,0,0,0.15);"></div>

JS逻辑实现

// 模拟从数据库获取的全量库存数据(实际项目中从后端接口获取)
const fullInventory = [
  {
    sku: "SKU-001",
    london: 15,
    manchester: 22,
    birmingham: 10,
    liverpool: 5
  },
  {
    sku: "SKU-002",
    london: 8,
    manchester: 14,
    birmingham: 0,
    liverpool: 18
  },
  {
    sku: "SKU-003",
    london: 22,
    manchester: 7,
    birmingham: 19,
    liverpool: 11
  }
];

// 当前用户所属门店(实际从登录态/后端获取)
const currentUserStore = "london";

// 获取Tooltip容器
const tooltip = document.getElementById("stock-tooltip");

// 给所有库存单元格绑定悬停事件
document.querySelectorAll(".stock-cell").forEach(cell => {
  cell.addEventListener("mouseover", function(e) {
    const targetSku = this.getAttribute("data-sku");
    // 找到当前SKU的全量库存数据
    const targetInventory = fullInventory.find(item => item.sku === targetSku);
    if (!targetInventory) return;

    // 生成其他门店的库存表格HTML
    let tooltipContent = `
      <table border="1" cellpadding="4">
        <thead>
          <tr><th>门店</th><th>库存数量</th></tr>
        </thead>
        <tbody>
    `;
    // 遍历所有门店,排除当前用户的门店和SKU字段
    Object.entries(targetInventory).forEach(([store, stock]) => {
      if (store !== "sku" && store !== currentUserStore) {
        // 门店名称首字母大写,提升可读性
        const storeName = store.charAt(0).toUpperCase() + store.slice(1);
        tooltipContent += `<tr><td>${storeName}</td><td>${stock}</td></tr>`;
      }
    });
    tooltipContent += `</tbody></table>`;

    // 设置Tooltip内容和位置
    tooltip.innerHTML = tooltipContent;
    tooltip.style.display = "block";
    tooltip.style.left = `${e.pageX + 10}px`;
    tooltip.style.top = `${e.pageY + 10}px`;
  });

  cell.addEventListener("mouseout", function() {
    tooltip.style.display = "none";
  });
});
前端框架(Vue)简化示例

如果你的项目用了Vue这类框架,思路是一样的,只是写法更简洁:

<template>
  <table border="1" cellpadding="8">
    <thead>
      <tr>
        <th>SKU</th>
        <th>商品名称</th>
        <th>In Stock ({{ currentStore }})</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="item in inventoryList" :key="item.sku">
        <td>{{ item.sku }}</td>
        <td>{{ item.productName }}</td>
        <td 
          @mouseover="showTooltip(item.sku, $event)" 
          @mouseout="hideTooltip"
          style="cursor: pointer;"
        >
          {{ item[currentStore] }}
        </td>
      </tr>
    </tbody>
  </table>

  <!-- Tooltip组件 -->
  <div 
    v-if="isTooltipShow" 
    :style="{ left: tooltipX + 'px', top: tooltipY + 'px' }"
    class="custom-tooltip"
  >
    <table border="1" cellpadding="4">
      <tr><th>门店</th><th>库存</th></tr>
      <tr 
        v-for="(stock, store) in currentSkuStock" 
        :key="store"
        v-if="store !== currentStore && store !== 'sku' && store !== 'productName'"
      >
        <td>{{ store.charAt(0).toUpperCase() + store.slice(1) }}</td>
        <td>{{ stock }}</td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inventoryList: [],
      currentStore: "london",
      isTooltipShow: false,
      tooltipX: 0,
      tooltipY: 0,
      currentSkuStock: {}
    };
  },
  methods: {
    showTooltip(sku, event) {
      this.currentSkuStock = this.inventoryList.find(item => item.sku === sku);
      this.isTooltipShow = true;
      this.tooltipX = event.pageX + 10;
      this.tooltipY = event.pageY + 10;
    },
    hideTooltip() {
      this.isTooltipShow = false;
    }
  },
  mounted() {
    // 模拟从后端获取数据
    this.inventoryList = [
      { sku: "SKU-001", productName: "无线耳机", london:15, manchester:22, birmingham:10, liverpool:5 },
      { sku: "SKU-002", productName: "蓝牙音箱", london:8, manchester:14, birmingham:0, liverpool:18 },
      { sku: "SKU-003", productName: "充电底座", london:22, manchester:7, birmingham:19, liverpool:11 }
    ];
  }
};
</script>

<style scoped>
.custom-tooltip {
  position: absolute;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 8px;
  z-index: 9999;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
</style>

这样实现后,你悬停任意SKU的库存单元格时,只会弹出该SKU的其他3个门店库存,完美解决之前显示全部商品的问题,同时也满足了不同用户组只能查看自己门店库存的权限要求。

内容的提问来源于stack exchange,提问作者MailBlade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:16:04