# 库存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布局展示** - 全部货位均渲染,按状态着色 - 货架式排列,包含巷道 - 地面网格背景 2. **多仓库 Tab 切换** - Element Plus Tabs 组件 - 每个仓库独立加载数据 - Tab 切换时重置3D场景 3. **货位点击详情弹窗** - 全屏 Dialog 展示 - 显示:货位信息、库存状态、托盘编号、物料明细列表 - 支持查看批次、保质期预警 4. **3D场景交互** - 鼠标旋转(OrbitControls) - 滚轮缩放 - 中键平移 - 点击货位高亮 + 相机聚焦 5. **实时库存状态更新** - SignalR 监听库存变化 - 货位颜色动态更新 6. **筛选过滤** - 按物料类型/批次/库存状态过滤 - 高亮显示匹配货位 7. **状态图例** - 右上角/底部颜色图例 - 说明每种颜色代表的货位状态 ### 3.2 货位状态颜色编码(颜色优先级:locationStatus > stockStatus) **颜色判定规则(按优先级顺序):** 1. **`locationStatus = 3`(禁用)** → 深灰 `#2d2d2d`(最高优先级) 2. **`locationStatus = 2`(锁定)** → 红色 `#F56C6C` 3. **`locationStatus = 1`(占用)且 `stockStatus = 0`(无货)** → 暗灰 `#4a4a4a` 4. **`locationStatus = 1`(占用)且 `stockStatus = 1`(有货)** → 蓝色 `#409EFF` 5. **`locationStatus = 1`(占用)且 `stockStatus = 2`(库存紧张 <10%)** → 橙色 `#E6A23C` 6. **`locationStatus = 1`(占用)且 `stockStatus = 3`(已满 ≥90%)** → 绿色 `#67C23A` 7. **`locationStatus = 0`(空)** → 暗灰 `#4a4a4a` **阈值定义:** - 库存紧张:`stockQuantity / maxCapacity < 10%` - 已满:`stockQuantity / maxCapacity ≥ 90%` ## 4. 后端 API ### 4.1 新增接口 ``` GET /api/StockInfo/Get3DLayout?warehouseId={id} ``` **响应结构**: ```json { "status": true, "data": { "warehouseId": 1, "warehouseName": "主仓库", "maxRow": 10, "maxColumn": 20, "maxLayer": 5, "materielCodeList": ["M001", "M002", "M003"], "batchNoList": ["B20260301", "B20260302"], "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`: 货位最大容量(用于计算填充率) - `materielCodeList`: 当前仓库所有物料编号列表(用于筛选下拉) - `batchNoList`: 当前仓库所有批次号列表(用于筛选下拉) - **颜色判定在前端实现**:后端返回 `stockQuantity` 和 `maxCapacity`,前端按 3.2 规则计算颜色 ### 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) ```vue ``` ## 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 相机聚焦动画 - 使用简单线性插值(lerp)平滑移动相机 - 目标位置:货位坐标 + 偏移量 - 插值公式:`camera.position.lerp(target, 0.05)` 每帧执行 ## 8. 性能优化 | 策略 | 说明 | |------|------| | InstancedMesh | 单次 drawcall 渲染所有货位 | | 视锥体剔除 | 相机外的货位不渲染 | | 颜色缓存 | 材质复用,避免频繁创建 | | requestAnimationFrame | 渲染循环使用 RAF | | 数据分页 | 大仓库可考虑按区域分片加载 | ## 9. 路由注册 在 `viewGird.js` 中注册路由: ```javascript { path: '/stockChat', name: 'stockChat', component: () => import('@/views/stock/stockChat.vue') } ``` ## 10. 实现注意事项 ### 10.1 后端交付物 - `Get3DLayout` API 实现,返回结构见 4.1 - SignalR Hub 配置(`/stockHub`),推送 `stockUpdated` 事件 - 货位颜色判定逻辑按 3.2 规则在后端或前端实现均可 ### 10.2 前端筛选联动 - `filterStockStatus`、`filterMaterielCode`、`filterBatchNo` 三者联动 - 筛选结果高亮显示,非匹配货位变暗(opacity: 0.3) - 筛选为空时显示全部货位正常颜色