编辑 | blame | 历史 | 原始文档

库存3D查看器 (stockChat) 设计文档

1. 概述

  • 功能名称:库存3D仓库查看器 (stockChat)
  • 文件路径WIDESEA_WMSClient/src/views/stock/stockChat.vue
  • 核心功能:使用 Three.js + WebGL 实现仓库3D可视化,用户可在3D场景中巡视仓库、查看货位状态、点击货位查看库存详情
  • 目标用户:仓库管理员、调度人员、质检人员

2. 技术选型

技术 选型 说明
3D引擎 Three.js WebGL 主流库,Vue 3 友好
渲染策略 InstancedMesh 批量渲染大量货位,单次 drawcall
状态管理 Vue 3 Composition API ref/reactive
UI组件 Element Plus 与项目现有技术栈一致
实时通信 SignalR 与后端 WebSocket 配合实现库存动态更新

3. 功能需求

3.1 核心功能

  1. 仓库3D布局展示
  • 全部货位均渲染,按状态着色
  • 货架式排列,包含巷道
  • 地面网格背景
  1. 多仓库 Tab 切换
  • Element Plus Tabs 组件
  • 每个仓库独立加载数据
  • Tab 切换时重置3D场景
  1. 货位点击详情弹窗
  • 全屏 Dialog 展示
  • 显示:货位信息、库存状态、托盘编号、物料明细列表
  • 支持查看批次、保质期预警
  1. 3D场景交互
  • 鼠标旋转(OrbitControls)
  • 滚轮缩放
  • 中键平移
  • 点击货位高亮 + 相机聚焦
  1. 实时库存状态更新
  • SignalR 监听库存变化
  • 货位颜色动态更新
  1. 筛选过滤
  • 按物料类型/批次/库存状态过滤
  • 高亮显示匹配货位
  1. 状态图例
  • 右上角/底部颜色图例
  • 说明每种颜色代表的货位状态

3.2 货位状态颜色编码

状态 颜色 Hex
空货位 暗灰 #4a4a4a
有库存 蓝色 #409EFF
库存紧张 (<10%) 橙色 #E6A23C
已满 绿色 #67C23A
锁定/冻结 红色 #F56C6C
禁用 深灰 #2d2d2d

4. 后端 API

4.1 新增接口

GET /api/StockInfo/Get3DLayout?warehouseId={id}

响应结构
json { "status": true, "data": { "warehouseId": 1, "warehouseName": "主仓库", "maxRow": 10, "maxColumn": 20, "maxLayer": 5, "locations": [ { "locationId": 1, "locationCode": "A-01-02-03", "row": 1, "column": 2, "layer": 3, "locationStatus": 0, "stockStatus": 2, "stockQuantity": 50, "maxCapacity": 100, "palletCode": "PLT-001", "materielCode": "M001", "materielName": "物料A", "batchNo": "B20260301" } ] } }

说明
- locationStatus: 0=空, 1=占用, 2=锁定, 3=禁用
- stockStatus: 0=无货, 1=有货, 2=库存紧张, 3=已满
- maxCapacity: 货位最大容量(用于计算填充率)

4.2 SignalR 实时推送

Hub 路径/stockHub

推送事件
javascript // 库存变化事件 stockUpdated: { locationId, warehouseId, stockQuantity, stockStatus }

5. 前端文件结构

WIDESEA_WMSClient/src/
├── views/stock/
│   └── stockChat.vue              # 主页面组件
├── extension/stock/
│   └── stockChat.js               # ViewGrid 扩展配置
└── api/
    └── http.js                    # 复用现有 http 封装

6. 组件结构 (stockChat.vue)

<template>
  <div class="stock-chat-container">
    <!-- 仓库 Tabs -->
    <el-tabs v-model="activeWarehouse" @tab-change="onWarehouseChange">
      <el-tab-pane
        v-for="wh in warehouseList"
        :key="wh.warehouseId"
        :label="wh.warehouseName"
        :name="wh.warehouseId"
      />
    </el-tabs>

    <!-- 工具栏 -->
    <div class="toolbar">
      <el-select v-model="filterStatus" placeholder="库存状态筛选" clearable />
      <el-select v-model="filterMateriel" placeholder="物料筛选" clearable />
      <el-button @click="resetCamera">重置视角</el-button>
    </div>

    <!-- 3D Canvas -->
    <div ref="canvasContainer" class="canvas-container" />

    <!-- 状态图例 -->
    <div class="legend">
      <div v-for="item in legendItems" :key="item.status" class="legend-item">
        <span class="color-box" :style="{ background: item.color }" />
        <span>{{ item.label }}</span>
      </div>
    </div>

    <!-- 详情弹窗 -->
    <el-dialog v-model="detailDialogVisible" title="库存详情" fullscreen>
      <!-- 详情内容 -->
    </el-dialog>
  </div>
</template>

7. Three.js 场景设计

7.1 初始化流程

  1. 创建 WebGLRenderer,挂载到 canvasContainer
  2. 创建 PerspectiveCamera(透视相机)
  3. 创建 Scene 场景
  4. 添加光照(环境光 + 定向光)
  5. 创建地面(PlaneGeometry + 网格材质)
  6. 创建货架货位(InstancedMesh
  7. 添加 OrbitControls 控制器
  8. 启动渲染循环

7.2 货位定位算法

x = (column - maxColumn/2) * CELL_SIZE_X
y = layer * CELL_SIZE_Y
z = (row - maxRow/2) * CELL_SIZE_Z

7.3 点击拾取

  • 使用 Raycaster 进行射线检测
  • 通过 instanceId 识别被点击的货位实例
  • 高亮:临时替换材质颜色

7.4 相机聚焦动画

  • 使用 TWEEN 或手动插值平滑移动相机
  • 目标位置:货位坐标 + 偏移量

8. 性能优化

策略 说明
InstancedMesh 单次 drawcall 渲染所有货位
视锥体剔除 相机外的货位不渲染
颜色缓存 材质复用,避免频繁创建
requestAnimationFrame 渲染循环使用 RAF
数据分页 大仓库可考虑按区域分片加载

9. 路由注册

viewGird.js 中注册路由:
javascript { path: '/stockChat', name: 'stockChat', component: () => import('@/views/stock/stockChat.vue') }

10. 待补充

  • [ ] 后端 Get3DLayout API 实现
  • [ ] SignalR Hub 配置
  • [ ] 货位颜色与后端状态枚举对齐
  • [ ] 筛选功能具体字段确认