# 库存3D查看器 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task.
**Goal:** 实现库存3D查看器,用户可在 Three.js 3D 场景中巡视仓库、点击货位查看库存详情
**Architecture:** 前端 Vue 3 + Element Plus + Three.js,后端 ASP.NET Core 6 Web API + SignalR 实时推送
**Tech Stack:** Three.js, @microsoft/signalr, Element Plus, Vue 3 Composition API
---
## 文件结构
```
后端 (WIDESEA_WMSServer)
├── WIDESEA_DTO/Stock/Stock3DLayoutDTO.cs # 3D布局响应DTO [新建]
├── WIDESEA_IStockService/IStockInfoService.cs # 添加Get3DLayoutAsync方法签名 [修改]
├── WIDESEA_StockService/StockInfoService.cs # 实现Get3DLayoutAsync [修改]
├── WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs # 添加Get3DLayout端点 [修改]
└── WIDESEA_WMSServer/Hubs/StockHub.cs # SignalR Hub [新建]
前端 (WIDESEA_WMSClient)
├── package.json # 添加three依赖 [修改]
├── src/router/viewGird.js # 注册路由 [修改]
├── src/views/stock/stockChat.vue # 主页面组件 [新建]
└── src/extension/stock/stockChat.js # 扩展配置 [新建]
```
---
## 实现任务
### Task 1: 后端 - 创建 Stock3DLayoutDTO
**Files:**
- Create: `WIDESEA_WMSServer/WIDESEA_DTO/Stock/Stock3DLayoutDTO.cs`
**详细规范:**
创建两个 DTO 类:
1. `Stock3DLayoutDTO` - 包含仓库基本信息、尺寸、筛选列表、货位数组
2. `Location3DItemDTO` - 包含单个货位的所有3D渲染所需数据
**验收标准:**
- DTO 包含所有 spec 中定义的字段
- 命名空间正确
- 可以被 Service 层正确引用
```csharp
namespace WIDESEA_DTO.Stock
{
///
/// 仓库3D布局响应DTO
///
public class Stock3DLayoutDTO
{
public int WarehouseId { get; set; }
public string WarehouseName { get; set; }
public int MaxRow { get; set; }
public int MaxColumn { get; set; }
public int MaxLayer { get; set; }
public List MaterielCodeList { get; set; } = new();
public List BatchNoList { get; set; } = new();
public List Locations { get; set; } = new();
}
///
/// 货位3D数据项
///
public class Location3DItemDTO
{
public int LocationId { get; set; }
public string LocationCode { get; set; }
public int Row { get; set; }
public int Column { get; set; }
public int Layer { get; set; }
public int LocationStatus { get; set; } // 0=空, 1=占用, 2=锁定, 3=禁用
public int StockStatus { get; set; } // 0=无货, 1=有货, 2=库存紧张, 3=已满
public float StockQuantity { get; set; }
public float MaxCapacity { get; set; }
public string? PalletCode { get; set; }
public string? MaterielCode { get; set; }
public string? MaterielName { get; set; }
public string? BatchNo { get; set; }
}
}
```
---
### Task 2: 后端 - 更新 IStockInfoService 接口
**Files:**
- Modify: `WIDESEA_WMSServer/WIDESEA_IStockService/IStockInfoService.cs`
**详细规范:**
在接口中添加方法签名:
```csharp
///
/// 获取仓库3D布局数据
///
/// 仓库ID
/// 3D布局DTO
Task Get3DLayoutAsync(int warehouseId);
```
**验收标准:**
- 方法签名正确
- 添加了文档注释
- 引用了 Stock3DLayoutDTO
---
### Task 3: 后端 - 实现 Get3DLayoutAsync
**Files:**
- Modify: `WIDESEA_WMSServer/WIDESEA_StockService/StockInfoService.cs`
**详细规范:**
实现 Get3DLayoutAsync 方法:
1. 查询仓库信息
2. 查询该仓库所有货位
3. 查询库存信息(包含明细)
4. 提取物料编号和批次号列表
5. 映射到 Location3DItemDTO
6. 计算仓库尺寸
**验收标准:**
- 方法能正确返回 Stock3DLayoutDTO
- 所有 locationStatus 和 stockStatus 值正确映射
- 性能适合中型仓库(1000-5000货位)
---
### Task 4: 后端 - 添加 API 端点
**Files:**
- Modify: `WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Stock/StockInfoController.cs`
**详细规范:**
添加端点:
```csharp
///
/// 获取仓库3D布局
///
/// 仓库ID
/// 3D布局数据
[HttpGet("Get3DLayout")]
public async Task Get3DLayout(int warehouseId)
{
var result = await Service.Get3DLayoutAsync(warehouseId);
return WebResponseContent.Instance.OK(result);
}
```
**验收标准:**
- 路由正确:GET /api/StockInfo/Get3DLayout?warehouseId={id}
- 返回格式符合 WebResponseContent 规范
---
### Task 5: 后端 - 创建 SignalR Hub
**Files:**
- Create: `WIDESEA_WMSServer/WIDESEA_WMSServer/Hubs/StockHub.cs`
- Modify: `WIDESEA_WMSServer/WIDESEA_WMSServer/Program.cs`
**详细规范:**
1. 创建 StockHub 类,继承 Microsoft.AspNetCore.SignalR.Hub
2. 添加 SendStockUpdate 方法供外部调用
3. 在 Program.cs 中注册 SignalR 服务并映射 Hub
**验收标准:**
- Hub 可被前端连接
- SendStockUpdate 方法存在且可被调用
---
### Task 6: 前端 - 安装 Three.js 依赖
**Files:**
- Modify: `WIDESEA_WMSClient/package.json`
**详细规范:**
添加 three 依赖到 package.json:
```json
"three": "^0.160.0"
```
**验收标准:**
- package.json 包含 three 依赖
- 版本号合理(^0.160.0 或更新稳定版)
---
### Task 7: 前端 - 注册路由
**Files:**
- Modify: `WIDESEA_WMSClient/src/router/viewGird.js`
**详细规范:**
在 stockView 路由后添加:
```javascript
{
path: '/stockChat',
name: 'stockChat',
component: () => import('@/views/stock/stockChat.vue')
}
```
**验收标准:**
- 路由注册正确
- 与其他路由格式一致
---
### Task 8: 前端 - 创建 stockChat.vue 主组件
**Files:**
- Create: `WIDESEA_WMSClient/src/views/stock/stockChat.vue`
**详细规范:**
组件必须包含:
1. 仓库 Tabs(el-tabs)
2. 工具栏(筛选 + 重置视角按钮)
3. 3D Canvas 容器
4. 状态图例
5. 详情弹窗(el-dialog fullscreen)
Three.js 场景:
1. 场景初始化(背景色 0x1a1a2e)
2. 透视相机
3. WebGLRenderer
4. OrbitControls(阻尼启用的轨道控制器)
5. 环境光 + 定向光
6. 地面(PlaneGeometry,网格)
7. InstancedMesh 批量渲染货位
8. Raycaster 点击拾取
9. 相机 lerp 聚焦动画
颜色编码(前端实现):
- DISABLED(3): 0x2d2d2d
- LOCKED(2): 0xF56C6C
- EMPTY(0/无货): 0x4a4a4a
- HAS_STOCK(1): 0x409EFF
- LOW_STOCK(2): 0xE6A23C
- FULL(3): 0x67C23A
**验收标准:**
- 页面可以正常加载
- Three.js 场景正确初始化
- 点击货位能显示详情弹窗
- 颜色编码正确
---
### Task 9: 前端 - 创建扩展配置文件
**Files:**
- Create: `WIDESEA_WMSClient/src/extension/stock/stockChat.js`
**详细规范:**
创建标准扩展文件格式:
```javascript
let extension = {
components: {
gridHeader: '',
gridBody: '',
gridFooter: '',
modelHeader: '',
modelBody: '',
modelFooter: ''
},
tableAction: '',
buttons: { view: [], box: [], detail: [] },
methods: {
onInit() {},
onInited() {}
}
};
export default extension;
```
**验收标准:**
- 符合项目现有扩展文件模式
---
### Task 10: 前端 - 集成 SignalR 实时更新
**Files:**
- Modify: `WIDESEA_WMSClient/src/views/stock/stockChat.vue`
**详细规范:**
1. 在 onMounted 中初始化 SignalR 连接
2. 连接 /stockHub
3. 监听 StockUpdated 事件
4. 更新对应货位的 stockQuantity 和 stockStatus
5. 动态更新货位颜色
6. 在 onUnmounted 中断开连接
**验收标准:**
- SignalR 连接正常建立
- 收到更新时货位颜色能动态变化