From ad9ee935006188c413f60118842cdeb868cf7aa5 Mon Sep 17 00:00:00 2001 From: btobab Date: Fri, 25 Jul 2025 12:35:54 +0800 Subject: [PATCH] =?UTF-8?q?1.0=E7=89=88=E6=9C=AC=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + .idea/.gitignore | 5 - .idea/202504-Wms-MengYang.iml | 9 - .idea/misc.xml | 6 - .idea/modules.xml | 8 - .idea/vcs.xml | 8 - 202504-Wms-MengYang-box/.idea/.gitignore | 5 - .../.idea/202504-Wms-MengYang-box.iml | 9 - 202504-Wms-MengYang-box/.idea/misc.xml | 6 - 202504-Wms-MengYang-box/.idea/modules.xml | 8 - 202504-Wms-MengYang-box/.idea/vcs.xml | 7 - .../wms_serve_mengyang/.idea/.gitignore | 8 - .../.idea/CommonStatePersistent.xml | 6 - .../CoolRequestCommonStatePersistent.xml | 6 - .../.idea/CoolRequestSetting.xml | 40 --- .../wms_serve_mengyang/.idea/compiler.xml | 19 -- .../wms_serve_mengyang/.idea/encodings.xml | 7 - .../.idea/jarRepositories.xml | 25 -- .../wms_serve_mengyang/.idea/misc.xml | 12 - .../wms_serve_mengyang/.idea/vcs.xml | 7 - .../wms_serve_mengyang/CLAUDE.md | 210 +++++++++++++- .../wms_serve_mengyang/README.md | 2 +- .../api-tests/MyWmsController.http | 69 +++++ .../api-tests/TaskController.http | 60 ++++ .../wms_serve_mengyang/pom.xml | 15 +- .../constant/enums/mywms/OrderInCBEnums.java | 18 ++ .../constant/enums/mywms/OrderOutCBEnums.java | 18 ++ .../constant/enums/wms/AppConfigKeyEnums.java | 5 +- .../constant/enums/wms/WmsAgvLockEnums.java | 13 + .../controller/mywms/MyWmsController.java | 15 + .../com/wms_main/dao/ITAppAgvLockService.java | 27 ++ .../dao/impl/TAppAgvLockServiceImpl.java | 46 +++ .../com/wms_main/mapper/AppAgvLockMapper.java | 12 + .../model/dto/request/mywms/OrderInCBReq.java | 19 +- .../model/dto/request/mywms/OrderInReq.java | 32 +-- .../dto/request/mywms/OrderOutCBReq.java | 17 +- .../request/mywms/OrderOutGoodsDetail.java | 4 +- .../model/dto/request/mywms/OrderOutReq.java | 24 +- .../model/dto/request/mywms/StockReq.java | 17 +- .../request/mywms/StockReqGoodsDetail.java | 6 +- .../dto/request/wcs/WcsCanFeedRequest.java | 13 + .../dto/response/mes/MesApiResponse.java | 23 ++ .../dto/response/mes/MesCanFeedResponse.java | 47 ++++ .../dto/response/wcs/WcsApiResponse.java | 2 +- .../dto/response/wcs/WcsCanFeedResponse.java | 27 ++ .../com/wms_main/model/po/TAppAgvLock.java | 87 ++++++ .../com/wms_main/model/po/TAppOrderOut.java | 4 +- .../service/api/IExternalApiService.java | 8 +- .../wms_main/service/api/IWcsApiService.java | 9 + .../serviceImpl/ExternalApiServiceImpl.java | 88 +----- .../api/serviceImpl/WcsApiServiceImpl.java | 32 +++ .../service/business/IAgvLockService.java | 52 ++++ .../business/IDepthStrategyService.java | 6 +- .../serviceImpl/AgvLockServiceImpl.java | 232 +++++++++++++++ .../serviceImpl/DepthStrategyServiceImpl.java | 22 +- .../serviceImpl/StackerTaskServiceImpl.java | 104 +++---- .../controller/IMyWmsControllerService.java | 4 + .../MyWmsControllerServiceImpl.java | 113 ++++++-- .../TaskControllerServiceImpl.java | 28 ++ .../job_executor/MyOutExecutor.java | 12 +- .../wms_web_mengyang/CLAUDE.md | 209 ++++++++++++++ .../wms_serve_mengyang/CLAUDE.md | 203 +++++++++----- .../api-tests/MyWmsController.http | 66 +++++ .../api-tests/TaskController.http | 60 ++++ .../wms_serve_mengyang/pom.xml | 15 +- .../serviceImpl/StackerTaskServiceImpl.java | 76 +++-- .../wms_web_mengyang/CLAUDE.md | 263 ++++++++++++++++++ 67 files changed, 2039 insertions(+), 601 deletions(-) create mode 100644 .gitignore delete mode 100644 .idea/.gitignore delete mode 100644 .idea/202504-Wms-MengYang.iml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 202504-Wms-MengYang-box/.idea/.gitignore delete mode 100644 202504-Wms-MengYang-box/.idea/202504-Wms-MengYang-box.iml delete mode 100644 202504-Wms-MengYang-box/.idea/misc.xml delete mode 100644 202504-Wms-MengYang-box/.idea/modules.xml delete mode 100644 202504-Wms-MengYang-box/.idea/vcs.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/.gitignore delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CommonStatePersistent.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestCommonStatePersistent.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestSetting.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/compiler.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/encodings.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/jarRepositories.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/misc.xml delete mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/.idea/vcs.xml create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/MyWmsController.http create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/TaskController.http create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderInCBEnums.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderOutCBEnums.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/WmsAgvLockEnums.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/ITAppAgvLockService.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/impl/TAppAgvLockServiceImpl.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/mapper/AppAgvLockMapper.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/wcs/WcsCanFeedRequest.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesApiResponse.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesCanFeedResponse.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsCanFeedResponse.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppAgvLock.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IAgvLockService.java create mode 100644 202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/AgvLockServiceImpl.java create mode 100644 202504-Wms-MengYang-box/wms_web_mengyang/CLAUDE.md create mode 100644 202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/MyWmsController.http create mode 100644 202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/TaskController.http create mode 100644 202504-Wms-MengYang-tp/wms_web_mengyang/CLAUDE.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52d77d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ +**/.idea/ +*.iml +.vscode/ +wms_log/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index a0ccf77..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Environment-dependent path to Maven home directory -/mavenHomeManager.xml diff --git a/.idea/202504-Wms-MengYang.iml b/.idea/202504-Wms-MengYang.iml deleted file mode 100644 index d6ebd48..0000000 --- a/.idea/202504-Wms-MengYang.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 639900d..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index f180dc5..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 0e6ac68..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/.idea/.gitignore b/202504-Wms-MengYang-box/.idea/.gitignore deleted file mode 100644 index a0ccf77..0000000 --- a/202504-Wms-MengYang-box/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Environment-dependent path to Maven home directory -/mavenHomeManager.xml diff --git a/202504-Wms-MengYang-box/.idea/202504-Wms-MengYang-box.iml b/202504-Wms-MengYang-box/.idea/202504-Wms-MengYang-box.iml deleted file mode 100644 index d6ebd48..0000000 --- a/202504-Wms-MengYang-box/.idea/202504-Wms-MengYang-box.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/.idea/misc.xml b/202504-Wms-MengYang-box/.idea/misc.xml deleted file mode 100644 index 639900d..0000000 --- a/202504-Wms-MengYang-box/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/.idea/modules.xml b/202504-Wms-MengYang-box/.idea/modules.xml deleted file mode 100644 index d290ac9..0000000 --- a/202504-Wms-MengYang-box/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/.idea/vcs.xml b/202504-Wms-MengYang-box/.idea/vcs.xml deleted file mode 100644 index 288b36b..0000000 --- a/202504-Wms-MengYang-box/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/.gitignore b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/.gitignore deleted file mode 100644 index 35410ca..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# 默认忽略的文件 -/shelf/ -/workspace.xml -# 基于编辑器的 HTTP 客户端请求 -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CommonStatePersistent.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CommonStatePersistent.xml deleted file mode 100644 index cce905e..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CommonStatePersistent.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestCommonStatePersistent.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestCommonStatePersistent.xml deleted file mode 100644 index b081340..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestCommonStatePersistent.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestSetting.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestSetting.xml deleted file mode 100644 index fc5a9d5..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/CoolRequestSetting.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/compiler.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/compiler.xml deleted file mode 100644 index 269757b..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/compiler.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/encodings.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/encodings.xml deleted file mode 100644 index eebab54..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/encodings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/jarRepositories.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/jarRepositories.xml deleted file mode 100644 index c7ea920..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/jarRepositories.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/misc.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/misc.xml deleted file mode 100644 index 9dc782b..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/misc.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/vcs.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/vcs.xml deleted file mode 100644 index 62bd7a0..0000000 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/CLAUDE.md b/202504-Wms-MengYang-box/wms_serve_mengyang/CLAUDE.md index 9221728..5f05f3c 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/CLAUDE.md +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/CLAUDE.md @@ -4,12 +4,29 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## 项目概述 -这是一个宝应梦阳WMS(仓库管理系统)后端项目,基于Spring Boot 3.3.5和Java 21开发,使用Maven构建。系统管理仓库的入库、出库、库存和任务调度等核心业务。 +这是一个宝应梦阳WMS(仓库管理系统)项目,包含前后端分离的完整解决方案: +- **后端项目**:基于Spring Boot 3.3.5和Java 21开发,使用Maven构建 +- **前端项目**:基于Vue 3和Element Plus开发,提供Web管理界面 +- **业务场景**:支持托盘库(TP)和料箱库(BOX)两种存储类型,管理仓库的入库、出库、库存和任务调度等核心业务 + +## 项目结构 + +本项目包含两个子项目,位于不同目录: +- `202504-Wms-MengYang-box/` - 料箱库(BOX)版本 +- `202504-Wms-MengYang-tp/` - 托盘库(TP)版本 + +每个子项目都包含: +- `wms_serve_mengyang/` - Spring Boot后端服务 +- `wms_web_mengyang/` - Vue.js前端应用 +- `db/` - 数据库SQL文件 ## 开发环境设置 -### 构建和运行命令 +### 后端项目命令(Maven) ```bash +# 进入后端目录(以BOX版本为例) +cd 202504-Wms-MengYang-box/wms_serve_mengyang + # 编译项目 mvn clean compile @@ -19,28 +36,66 @@ mvn clean package # 运行项目 mvn spring-boot:run -# 跳过测试运行(默认配置) +# 跳过测试运行(项目配置默认跳过测试) mvn clean package -Dmaven.test.skip=true ``` -### 数据库配置 +### 前端项目命令(Vue.js) +```bash +# 进入前端目录(以BOX版本为例) +cd 202504-Wms-MengYang-box/wms_web_mengyang + +# 安装依赖 +npm install + +# 启动开发服务器 +npm run serve + +# 构建生产版本 +npm run build + +# 代码检查和修复 +npm run lint +``` + +### 运行环境配置 + +**数据库配置** - 本地开发:MySQL `localhost:3306/wms_mengyang_box` - 生产环境:MySQL `10.18.58.21:3306/wms_yachi_nantong` -- 用户名/密码:本地使用root/root,生产使用user/user +- 认证信息:本地使用root/root,生产使用user/user -### 应用配置 +**后端服务 (Spring Boot)** - 服务端口:12315 - 应用名称:wms_main - 文件上传限制:单文件100MB,总计1000MB +- 当前配置:`spring.profiles.active=online` + +**前端应用 (Vue.js)** +- 开发端口:12306 +- 后端API地址:`http://10.18.58.21:12315` +- 路由模式:Hash路由 ## 核心架构 ### 分层架构 + +**后端架构(Spring Boot)** 系统采用标准的MVC三层架构: - **Controller层**:REST API接口,包含mywms和wms两个模块 - **Service层**:业务逻辑层,分为controller、business、api三个子模块 - **DAO层**:数据访问层,使用MyBatis-Plus +**前端架构(Vue.js)** +采用现代化的Vue 3组件化架构: +- **Views层**:页面视图组件(login、HomeView、SystemCenter) +- **Layout层**:业务布局组件(库存、入库、出库等功能页面) +- **Components层**:可复用组件(sideMenu、appTag) +- **API层**:HTTP请求封装和接口定义 +- **Store层**:Vuex状态管理(用户信息、菜单权限、标签页) +- **Router层**:Vue Router路由管理 +- **Utils层**:工具函数(日期处理、格式化、加密等) + ### 核心业务模块 #### 1. MyWMS模块 (`controller/mywms/`) @@ -72,35 +127,79 @@ mvn clean package -Dmaven.test.skip=true - `vo/` - 视图对象(View Object) ### 常用枚举类 (`constant/enums/`) + +**WMS业务枚举** (`enums/wms/`) - `StorageTypeEnums` - 存储类型(托盘库TP/料箱库BOX) - `WmsDepthStrategyEnums` - 深度策略枚举 - `WmsTaskTypeEnums` - 任务类型枚举 - `OrderStatusEnum` - 订单状态枚举 +- `WmsLocationTypeEnums` - 货位类型枚举 +- `WmsGoodsStatusEnums` - 货物状态枚举 +- `WmsVehicleStatusEnums` - 载具状态枚举 + +**WCS集成枚举** (`enums/wcs/`) +- `WcsApiResponseCodeEnums` - WCS API响应码 +- `WcsStackerTaskTypeEnums` - 堆垛机任务类型 +- `WcsStackerTaskStatusEnums` - 堆垛机任务状态 + +**任务调度枚举** (`enums/jobs/`) +- `JobStatusEnums` - 任务状态枚举 +- `JobTimerTypeEnums` - 定时器类型枚举 ## 技术栈 -### 核心依赖 +### 后端技术栈(Spring Boot) + +**核心依赖** - Spring Boot Web 3.3.5 - REST API框架 - Spring Boot Quartz - 定时任务调度 - MyBatis-Plus 3.5.7 - ORM框架 - MySQL Connector - 数据库连接 - Lombok - 代码简化 -### 工具库 +**工具库** - Hutool 5.8.33 - Java工具类库 - FastJSON 2.0.21 - JSON处理 - EasyExcel 4.0.3 & EasyPOI 4.5.0 - Excel处理 - Apache HttpClient 4.5.13 - HTTP客户端 - Google Guava 33.3.1 - 集合工具 +### 前端技术栈(Vue.js) + +**核心框架** +- Vue 3.2.13 - 前端框架 +- Vue Router 4.0.3 - 路由管理 +- Vuex 4.0.0 - 状态管理 +- Element Plus 2.4.0 - UI组件库 + +**主要依赖** +- Axios 1.3.3 - HTTP请求库 +- Moment 2.29.4 - 日期处理 +- XLSX 0.18.5 - Excel文件处理 +- QRCode.vue 3.4.1 - 二维码生成 +- Vue3-print-nb 0.1.4 - 打印功能 +- File-saver 2.0.5 - 文件下载 + +**开发工具** +- Sass 1.83.4 - CSS预处理器 +- ESLint - 代码质量检查 +- Babel - JavaScript编译器 + ## 开发注意事项 -### 代码规范 +### 后端代码规范 - 使用Lombok注解减少样板代码 - 统一的API响应格式(WmsApiResponse) - 枚举类管理常量值 - 接口-实现分离的服务层设计 +### 前端代码规范 +- Vue 3 Composition API优先 +- Element Plus组件库统一UI风格 +- Vuex模块化状态管理 +- ESLint代码质量检查(关闭未使用变量警告) +- 响应式设计,支持不同屏幕尺寸 + ### 数据库操作 - 使用MyBatis-Plus进行ORM操作 - 支持批量操作和事务处理 @@ -113,11 +212,15 @@ mvn clean package -Dmaven.test.skip=true - 请求日志过滤器:`RequestLogFilter` ### Excel处理 -系统支持完整的Excel导入导出功能: +**后端**:使用EasyExcel和EasyPOI双重支持 - 货物信息、产品信息、库存信息等业务数据 -- 使用EasyExcel和EasyPOI双重支持 - 模板位置:`excel/easypoi/excelTemplate/` +**前端**:使用XLSX和Element Plus支持 +- 文件上传组件:`excel/` 目录下的各类Excel上传组件 +- 支持在线预览和数据导出 +- 集成二维码生成和打印功能 + ## 外部系统集成 ### WCS系统集成 @@ -131,8 +234,91 @@ mvn clean package -Dmaven.test.skip=true ## 测试说明 +**后端测试** 项目配置中跳过了单元测试执行(`maven-surefire-plugin.skip=true`),在开发新功能时建议: 1. 先实现功能代码 2. 使用Postman等工具进行API测试 3. 检查数据库数据状态 -4. 验证定时任务执行情况 \ No newline at end of file +4. 验证定时任务执行情况 + +**前端测试** +- 使用浏览器开发者工具调试 +- 通过Vue DevTools检查组件状态 +- 使用Element Plus组件库确保UI一致性 +- 在不同浏览器(Chrome、Firefox、Edge)中测试兼容性 + +## 开发注意事项 + +### 特殊的Maven配置 +- 项目默认跳过单元测试:`maven-surefire-plugin.skip=true` +- 最终构建文件名:`wms-box-server` +- Java版本:21 (source和target都是21) +- Maven Wrapper可用:使用`./mvnw`替代`mvn`命令 + +### 重要的文件路径 +- 主要工作目录:`202504-Wms-MengYang-box/wms_serve_mengyang/` +- 日志存储:`wms_log/` (按日期和级别分类) +- 数据库脚本:`db/wms_mengyang_box.sql` +- MyBatis映射:`src/main/resources/mapper/` + +### 常见开发任务 + +**启动后端服务** +```bash +cd 202504-Wms-MengYang-box/wms_serve_mengyang +mvn spring-boot:run +# 或使用Maven Wrapper +./mvnw spring-boot:run +``` + +**启动前端开发服务器** +```bash +cd 202504-Wms-MengYang-box/wms_web_mengyang +npm run serve +``` + +**查看日志** +```bash +# 查看今天的info日志 +tail -f wms_log/info/$(date +%Y-%m-%d)/$(date +%Y-%m-%d).0.log + +# 查看今天的error日志 +tail -f wms_log/error/$(date +%Y-%m-%d)/$(date +%Y-%m-%d).0.log +``` + +**数据库操作** +- 使用MyBatis-Plus进行ORM操作 +- 支持批量操作和事务处理 +- 驼峰命名自动映射(`map-underscore-to-camel-case: true`) +- ID生成策略:`assign_id` + +### 系统集成要点 + +**WCS系统集成** +- TCP和HTTP双协议支持 +- 堆垛机任务调度和状态同步 +- 载具管理(托盘和料箱) + +**任务调度系统** +- 基于Quartz的定时任务框架 +- 关键执行器:`WmsTaskExecutor`、`MyOutExecutor`、`WcsStackerTaskSender` +- 任务状态实时监控 + +**Excel处理** +- 后端:EasyExcel 4.0.3 + EasyPOI 4.5.0 +- 前端:XLSX 0.18.5 + Element Plus上传组件 +- 模板位置:`excel/easypoi/excelTemplate/` + +## 故障排除 + +### 常见问题 +1. **端口冲突**:确认12315端口未被占用 +2. **数据库连接**:检查MySQL服务状态和配置 +3. **前端代理**:确认后端API地址配置正确 +4. **日志分析**:按级别查看对应日志目录 + +### 调试技巧 +- 使用`RequestLogFilter`查看API请求日志 +- 通过`WmsControllerExceptionHandler`统一异常处理 +- 检查定时任务执行状态:查看`TAppJobs`表 +- Vue DevTools调试前端状态管理 \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/README.md b/202504-Wms-MengYang-box/wms_serve_mengyang/README.md index aa7a8fb..4871cdb 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/README.md +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/README.md @@ -1,3 +1,3 @@ # wms_serve_mengyang -宝应梦阳料箱库WMS后端 \ No newline at end of file +宝应梦阳托盘库WMS后端 \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/MyWmsController.http b/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/MyWmsController.http new file mode 100644 index 0000000..1522ad3 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/MyWmsController.http @@ -0,0 +1,69 @@ +### MyWMS接口测试 +### 基础配置 +@baseUrl = http://localhost:12315 + +### 1. 入库订单接口 +POST {{baseUrl}}/mywms/orderIn +Content-Type: application/json + +{ + "taskId": "testOrderId6", + "vehicleNo": "1006" +} + +### 2. 出库订单接口 +POST {{baseUrl}}/mywms/orderOut +Content-Type: application/json + +{ + "taskId": "testOrderId1", + "vehicleNo": "1004" +} + +### 3. 库存查询接口 - 仅按载具查询 +POST {{baseUrl}}/mywms/stock +Content-Type: application/json + +{ + "requestId": "testOrderId1", + "details": [ + { + "vehicleNo": "1001" + } + ] +} + +### 4. 库存查询接口 - 仅按库位查询 +POST {{baseUrl}}/mywms/stock +Content-Type: application/json + +{ + "requestId": "testOrderId2", + "details": [ + { + "locationId": "A02-01-02-02" + } + ] +} + +### 5. 检查是否允许投料 +GET {{baseUrl}}/mywms/allowFeed + +### 6. 允许出库 +GET {{baseUrl}}/mywms/allowOut + +### 测试数据说明 +# 1. orderIn: 入库订单接口,需要taskId和vehicleNo +# 2. orderOut: 出库订单接口,需要taskId和vehicleNo +# 3. stock: 库存查询接口,需要requestId和details数组 +# - details中可以包含vehicleNo和/或locationId +# 4. allowFeed: 查询当前系统是否允许投料操作(GET请求) + +### 响应格式说明 +# 所有接口都返回MyWmsResponse格式: +# { +# "code": 200, // 响应码 +# "message": "操作成功", // 响应消息 +# "data": {}, // 具体数据 +# "success": true // 是否成功 +# } \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/TaskController.http b/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/TaskController.http new file mode 100644 index 0000000..602428f --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/api-tests/TaskController.http @@ -0,0 +1,60 @@ +### TaskController接口测试 - WMS任务控制接口 +### 基础配置 +@baseUrl = http://localhost:12315 + +### 1. WCS请求载具入库 +POST {{baseUrl}}/wms/task/wcsRequestVehicleIn +Content-Type: application/json + +{ + "origin": "R1", + "vehicleNo": "1006", + "codeMessage": "test", + "remark": "载具入库测试" +} + +### 2. 发送任务结果 - 任务完成 +POST {{baseUrl}}/wms/task/sendTaskResult +Content-Type: application/json + +{ + "taskId": "1753403954324010001", + "taskStatus": 100, + "vehicleNo": "1004", + "destination": "C1", + "message": "任务执行成功" +} + +### 测试数据说明 +# 1. wcsRequestVehicleIn: WCS请求载具入库 +# - origin: 点位(必填) +# - vehicleNo: 载具信息(必填) +# - codeMessage: 条码信息(可选) +# - remark: 备注(可选) + +# 2. sendTaskResult: WCS反馈任务执行结果 +# - taskId: 任务ID(必填) +# - taskStatus: 任务状态(必填) +# * 0: 等待执行 +# * 1: 执行中 +# * 2: 执行完成 +# * 3: 执行失败 +# - vehicleNo: 载具号(必填) +# - destination: 终点(可选) +# - message: 信息(可选) + +### 响应格式说明 +# wcsRequestVehicleIn返回WcsVehicleInResponse: +# { +# "success": true, +# "code": "SUCCESS", +# "message": "请求成功", +# "data": {} +# } + +# sendTaskResult返回BaseWcsApiResponse: +# { +# "success": true, +# "code": "SUCCESS", +# "message": "任务结果接收成功" +# } \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/pom.xml b/202504-Wms-MengYang-box/wms_serve_mengyang/pom.xml index 57aea11..be078b0 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/pom.xml +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/pom.xml @@ -9,10 +9,10 @@ com - dev_wms_serve + wms_serve_mengyang_box 3.2 - dev_wms_serve - dev_wms_serve + wms_serve_mengyang_box + wms_serve_mengyang_box @@ -162,6 +162,15 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + UTF-8 + + diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderInCBEnums.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderInCBEnums.java new file mode 100644 index 0000000..8fd58ba --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderInCBEnums.java @@ -0,0 +1,18 @@ +package com.wms_main.constant.enums.mywms; + +import lombok.Getter; + +@Getter +public enum OrderInCBEnums { + COMPLETE(1, "入库完成"), + CANCEL(2, "入库取消"), + EXCEPTION(3, "入库异常"); + + private final Integer code; + private final String desc; + + OrderInCBEnums(Integer code, String desc) { + this.code = code; + this.desc = desc; + } +} diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderOutCBEnums.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderOutCBEnums.java new file mode 100644 index 0000000..6aaa784 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/mywms/OrderOutCBEnums.java @@ -0,0 +1,18 @@ +package com.wms_main.constant.enums.mywms; + +import lombok.Getter; + +@Getter +public enum OrderOutCBEnums { + COMPLETE(1, "出库完成"), + CANCEL(2, "出库取消"), + EXCEPTION(3, "出库异常"); + + private final Integer code; + private final String desc; + + OrderOutCBEnums(Integer code, String desc) { + this.code = code; + this.desc = desc; + } +} diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/AppConfigKeyEnums.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/AppConfigKeyEnums.java index 98311ff..ee409c5 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/AppConfigKeyEnums.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/AppConfigKeyEnums.java @@ -12,6 +12,7 @@ public enum AppConfigKeyEnums { WCS_STACKER_TASK_URL("WcsStackerTaskUrl", "发送堆垛机任务地址"), WCS_PICK_TASK_URL("WcsPickTaskUrl", "发送拣选任务地址"), WCS_CANCEL_PICK_TASK_URL("WcsCancelPickTaskUrl", "发送取消拣选任务地址"), + WCS_CAN_FEED_URL("wcsCanFeedUrl", "查询wcs是否可上料"), WCS_RELEASE_BOX_URL("WcsReleaseBoxUrl", "发送释放站台箱子地址"), STAND_CAPACITY("StandCapacity", "站台容量"), IMAGE_IP("ImageIp", "图片存放ip"), @@ -19,7 +20,9 @@ public enum AppConfigKeyEnums { STOCK_WARNING_QTY("StockWarningQty", "库存预警数量"), MES_GET_GOODS_URL("MesGetGoodsUrl", "获取物料信息地址"), ERP_GET_VEHICLENO_DATA("ErpGetVehicleNoData", "根据托盘号查询简单生产入库单"), - WMS_MANAGE_CALLBACK("WmsManageCallback", "场内WMS接受的入库出库执行后回调地址"); + WMS_ORDER_IN_CALLBACK("WmsOrderInCallback", "WMS接受的入库执行后回调地址"), + WMS_ORDER_OUT_CALLBACK("WmsOrderOutCallback", "WMS接受的出库执行后回调地址"); + private final String key; private final String desc; diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/WmsAgvLockEnums.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/WmsAgvLockEnums.java new file mode 100644 index 0000000..4d6673f --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/constant/enums/wms/WmsAgvLockEnums.java @@ -0,0 +1,13 @@ +package com.wms_main.constant.enums.wms; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum WmsAgvLockEnums { + AVAILABLE(0, "可用"), + LOCK(1, "锁定"); + private final Integer code; + private final String desc; +} diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/controller/mywms/MyWmsController.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/controller/mywms/MyWmsController.java index ba4fd05..29a8249 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/controller/mywms/MyWmsController.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/controller/mywms/MyWmsController.java @@ -7,15 +7,20 @@ import com.wms_main.model.dto.request.mywms.StockRespGoodsDetail; import com.wms_main.model.dto.response.mywms.MyWmsResponse; import com.wms_main.service.controller.IMyWmsControllerService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + @RestController @ResponseBody @CrossOrigin @RequiredArgsConstructor @RequestMapping("/mywms") +@Slf4j public class MyWmsController { private final IMyWmsControllerService myWmsControllerService; @@ -34,4 +39,14 @@ public class MyWmsController { public MyWmsResponse> stock(@RequestBody StockReq request) { return myWmsControllerService.stock(request); } + + @GetMapping("/allowFeed") + public MyWmsResponse canFeed() { + return myWmsControllerService.queryCanFeed(); + } + + @GetMapping("/allowOut") + public MyWmsResponse canOut() { + return myWmsControllerService.queryCanOut(); + } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/ITAppAgvLockService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/ITAppAgvLockService.java new file mode 100644 index 0000000..2b0d98e --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/ITAppAgvLockService.java @@ -0,0 +1,27 @@ +package com.wms_main.dao; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.wms_main.model.po.TAppAgvLock; + +import java.util.List; + +/** + * AGV互锁表数据访问接口 + */ +public interface ITAppAgvLockService extends IService { + + /** + * 根据AGV和站点查询锁定记录 + */ + List getByAgvAndStation(String agvId, String feedStation); + + /** + * 根据站点查询所有锁定记录 + */ + List getByStation(String feedStation); + + /** + * 查询超时的锁定记录 + */ + List getTimeoutLocks(); +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/impl/TAppAgvLockServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/impl/TAppAgvLockServiceImpl.java new file mode 100644 index 0000000..74d556c --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/dao/impl/TAppAgvLockServiceImpl.java @@ -0,0 +1,46 @@ +package com.wms_main.dao.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms_main.dao.ITAppAgvLockService; +import com.wms_main.mapper.AppAgvLockMapper; +import com.wms_main.model.po.TAppAgvLock; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * AGV互锁表数据访问实现 + */ +@Service +public class TAppAgvLockServiceImpl extends ServiceImpl implements ITAppAgvLockService { + + @Override + public List getByAgvAndStation(String agvId, String feedStation) { + return list(new LambdaQueryWrapper() + .eq(TAppAgvLock::getAgvId, agvId) + .eq(TAppAgvLock::getFeedStation, feedStation) + .eq(TAppAgvLock::getLockStatus, 1) + .orderByAsc(TAppAgvLock::getCreateTime) + ); + } + + @Override + public List getByStation(String feedStation) { + return list(new LambdaQueryWrapper() + .eq(TAppAgvLock::getFeedStation, feedStation) + .eq(TAppAgvLock::getLockStatus, 1) + .orderByAsc(TAppAgvLock::getPriority) + .orderByAsc(TAppAgvLock::getCreateTime) + ); + } + + @Override + public List getTimeoutLocks() { + return list(new LambdaQueryWrapper() + .eq(TAppAgvLock::getLockStatus, 1) + .lt(TAppAgvLock::getLockTime, LocalDateTime.now().minusSeconds(300)) // 超过5分钟的锁定 + ); + } +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/mapper/AppAgvLockMapper.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/mapper/AppAgvLockMapper.java new file mode 100644 index 0000000..660381f --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/mapper/AppAgvLockMapper.java @@ -0,0 +1,12 @@ +package com.wms_main.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.wms_main.model.po.TAppAgvLock; +import org.apache.ibatis.annotations.Mapper; + +/** + * AGV互锁表映射器 + */ +@Mapper +public interface AppAgvLockMapper extends BaseMapper { +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInCBReq.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInCBReq.java index 16ecec0..f48aaca 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInCBReq.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInCBReq.java @@ -1,5 +1,6 @@ package com.wms_main.model.dto.request.mywms; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -8,8 +9,18 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class OrderInCBReq { - String orderId; - String vehicleNo; - Integer orderStatus; - String message; + @JsonProperty("taskId") + private String taskId; + + @JsonProperty("vehicleNo") + private String vehicleNo; + + @JsonProperty("locationId") + private String locationId; + + @JsonProperty("result") + private Integer result; + + @JsonProperty("resultMessage") + private String resultMessage; } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInReq.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInReq.java index f511e4f..0bcda6b 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInReq.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderInReq.java @@ -1,15 +1,10 @@ package com.wms_main.model.dto.request.mywms; -import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; -import com.wms_main.constant.enums.wms.WmsTaskTypeEnums; import com.wms_main.repository.utils.StringUtils; import lombok.Getter; import lombok.Setter; -import org.springframework.format.annotation.DateTimeFormat; -import java.time.LocalDateTime; -import java.util.Objects; @Getter @Setter @@ -18,34 +13,11 @@ public class OrderInReq { @JsonProperty("taskId") private String taskId; - @JsonProperty("storageId") - private Integer storageId; - - @JsonProperty("taskType") - private Integer taskType; - @JsonProperty("vehicleNo") private String vehicleNo; - @JsonProperty("standId") - private String standId; - - @JsonProperty("requestTime") - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private LocalDateTime requestTime; - - @JsonProperty("requestUser") - private String requestUser; - public boolean isValid() { - if (StringUtils.isEmpty(this.getTaskId()) - || StringUtils.isEmpty(this.getVehicleNo()) - || StringUtils.isEmpty(this.getStandId()) - || !Objects.equals(this.getTaskType(), WmsTaskTypeEnums.IN.getCode())) { - return false; - } else { - return true; - } + return !StringUtils.isEmpty(this.getTaskId()) + && !StringUtils.isEmpty(this.getVehicleNo()); } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutCBReq.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutCBReq.java index 401efee..ef1ca96 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutCBReq.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutCBReq.java @@ -1,5 +1,6 @@ package com.wms_main.model.dto.request.mywms; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -8,9 +9,15 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class OrderOutCBReq { - String orderId; - String vehicleNo; - Integer orderStatus; - String outStand; - String message; + @JsonProperty("taskId") + private String taskId; + + @JsonProperty("result") + private Integer result; + + @JsonProperty("resultMessage") + private String resultMessage; + + @JsonProperty("vehicleNo") + private String vehicleNo; } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutGoodsDetail.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutGoodsDetail.java index 8986b8f..5d5e0d1 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutGoodsDetail.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutGoodsDetail.java @@ -7,6 +7,6 @@ import lombok.Setter; @Getter @Setter public class OrderOutGoodsDetail { - @JsonProperty("inTaskId") - private String inTaskId; + @JsonProperty("vehicleNo") + private String vehicleNo; } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutReq.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutReq.java index 67be9d2..d30251c 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutReq.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/OrderOutReq.java @@ -1,14 +1,8 @@ package com.wms_main.model.dto.request.mywms; - -import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.Setter; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; -import java.util.List; @Getter @Setter @@ -17,20 +11,6 @@ public class OrderOutReq { @JsonProperty("taskId") private String taskId; - @JsonProperty("storageId") - private Integer storageId; - - @JsonProperty("taskType") - private Integer taskType; - - @JsonProperty("details") - private List details; - - @JsonProperty("requestTime") - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private LocalDateTime requestTime; - - @JsonProperty("requestUser") - private String requestUser; + @JsonProperty("vehicleNo") + private String vehicleNo; } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReq.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReq.java index 7b4ff63..5b60ae9 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReq.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReq.java @@ -16,25 +16,10 @@ public class StockReq { @JsonProperty("requestId") private String requestId; - @JsonProperty("storageId") - private Integer storageId; - - @JsonProperty("requestTime") - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String requestTime; - - @JsonProperty("requestUser") - private String requestUser; - @JsonProperty("details") private List details; public boolean empty() { - return StringUtils.isEmpty(requestId) - && StringUtils.isEmpty(requestTime) - && StringUtils.isEmpty(requestUser) - && Objects.isNull(storageId); + return StringUtils.isEmpty(requestId); } - } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReqGoodsDetail.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReqGoodsDetail.java index 190a319..d80b9d9 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReqGoodsDetail.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/mywms/StockReqGoodsDetail.java @@ -12,12 +12,8 @@ public class StockReqGoodsDetail { @JsonProperty("locationId") private String locationId; - @JsonProperty("inTaskId") - private String inTaskId; - public boolean empty() { return StringUtils.isEmpty(vehicleNo) - && StringUtils.isEmpty(locationId) - && StringUtils.isEmpty(inTaskId); + && StringUtils.isEmpty(locationId); } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/wcs/WcsCanFeedRequest.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/wcs/WcsCanFeedRequest.java new file mode 100644 index 0000000..6aef3a3 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/request/wcs/WcsCanFeedRequest.java @@ -0,0 +1,13 @@ +package com.wms_main.model.dto.request.wcs; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class WcsCanFeedRequest { + /** + * 入库口编号(默认为单一入库口) + */ + private String inboundPort; +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesApiResponse.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesApiResponse.java new file mode 100644 index 0000000..d8b7703 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesApiResponse.java @@ -0,0 +1,23 @@ +package com.wms_main.model.dto.response.mes; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class MesApiResponse { + @JsonProperty("code") + private Integer code; + + @JsonProperty("message") + private String message; + + public static MesApiResponse error(String msg) { + return new MesApiResponse(999, msg); + } +} diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesCanFeedResponse.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesCanFeedResponse.java new file mode 100644 index 0000000..b8aa371 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/mes/MesCanFeedResponse.java @@ -0,0 +1,47 @@ +package com.wms_main.model.dto.response.mes; + +import lombok.Getter; +import lombok.Setter; + +/** + * MES系统查询是否可上料响应 + */ +@Getter +@Setter +public class MesCanFeedResponse { + + /** + * 是否可以上料 + */ + private Boolean canFeed; + + /** + * 入库口状态(空闲/占用) + */ + private String inboundPortStatus; + + /** + * 当前处理中的任务数量 + */ + private Integer processingTaskCount; + + /** + * 响应消息 + */ + private String message; + + /** + * 预留字段1 + */ + private String reserved1; + + /** + * 预留字段2 + */ + private String reserved2; + + /** + * 预留字段3 + */ + private String reserved3; +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsApiResponse.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsApiResponse.java index a995dc0..78b7a0b 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsApiResponse.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsApiResponse.java @@ -17,7 +17,7 @@ public class WcsApiResponse extends BaseWcsApiResponse { /** * 返回数据 */ - @JsonProperty("data") + @JsonProperty("returnData") private T data; /** diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsCanFeedResponse.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsCanFeedResponse.java new file mode 100644 index 0000000..331659c --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/dto/response/wcs/WcsCanFeedResponse.java @@ -0,0 +1,27 @@ +package com.wms_main.model.dto.response.wcs; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +/** + * 立库查询是否可上料响应 + */ +@Getter +@Setter +public class WcsCanFeedResponse { + @JsonProperty("responseTime") + @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss") + private LocalDateTime responseTime; + + @JsonProperty("allowAction") + boolean allowAction; + + @JsonProperty("msg") + String msg; +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppAgvLock.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppAgvLock.java new file mode 100644 index 0000000..04d6077 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppAgvLock.java @@ -0,0 +1,87 @@ +package com.wms_main.model.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +/** + * AGV互锁表 + */ +@Getter +@Setter +@TableName(value = "t_app_agv_lock", autoResultMap = true) +public class TAppAgvLock { + + @TableId(value = "lock_id") + private String lockId; + + /** + * AGV设备ID + */ + @TableField(value = "agv_id") + private String agvId; + + /** + * 上料站点 + */ + @TableField(value = "feed_station") + private String feedStation; + + /** + * 锁定状态: 1-锁定中, 0-已释放 + */ + @TableField(value = "lock_status") + private Integer lockStatus; + + /** + * 锁定类型: FEED-上料锁定, WAIT-等待锁定 + */ + @TableField(value = "lock_type") + private String lockType; + + /** + * 优先级: 数字越小优先级越高 + */ + @TableField(value = "priority") + private Integer priority; + + /** + * 队列位置 + */ + @TableField(value = "queue_position") + private Integer queuePosition; + + /** + * 锁定时间 + */ + @TableField(value = "lock_time") + private LocalDateTime lockTime; + + /** + * 释放时间 + */ + @TableField(value = "unlock_time") + private LocalDateTime unlockTime; + + /** + * 超时时间(秒) + */ + @TableField(value = "timeout_seconds") + private Integer timeoutSeconds; + + /** + * 备注 + */ + @TableField(value = "remark") + private String remark; + + @TableField(value = "create_time") + private LocalDateTime createTime; + + @TableField(value = "update_time") + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppOrderOut.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppOrderOut.java index d3eb020..1951ae6 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppOrderOut.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/model/po/TAppOrderOut.java @@ -19,8 +19,8 @@ public class TAppOrderOut { @TableField(value = "order_id") private String orderId; - @TableField(value = "in_task_id") - private String inTaskId; + @TableField(value = "vehicle_no") + private String vehicleNo; @TableField(value = "order_status") private Integer orderStatus; diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IExternalApiService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IExternalApiService.java index 70876d3..2ab1415 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IExternalApiService.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IExternalApiService.java @@ -1,14 +1,12 @@ package com.wms_main.service.api; -import com.wms_main.model.bo.ycwms.YCWmsApiResponse; import com.wms_main.model.dto.request.mywms.OrderInCBReq; import com.wms_main.model.dto.request.mywms.OrderOutCBReq; -import com.wms_main.model.dto.response.mywms.MyWmsResponse; +import com.wms_main.model.dto.response.mes.MesApiResponse; public interface IExternalApiService { -// MyWmsResponse getVehicleNoData(String vehicleNo); - MyWmsResponse invokeOrderInCB(OrderInCBReq request); + MesApiResponse invokeOrderInCB(OrderInCBReq request); - MyWmsResponse invokeOrderOutCB(OrderOutCBReq request); + MesApiResponse invokeOrderOutCB(OrderOutCBReq request); } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IWcsApiService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IWcsApiService.java index 5e959e2..9849085 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IWcsApiService.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/IWcsApiService.java @@ -2,11 +2,13 @@ package com.wms_main.service.api; import com.wms_main.model.bo.wcs.WcsPickTask; import com.wms_main.model.bo.wcs.WcsStackerTask; +import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest; import com.wms_main.model.dto.request.wcs.WcsPickTaskRequest; import com.wms_main.model.dto.request.wcs.WcsReleaseBoxRequest; import com.wms_main.model.dto.request.wcs.WcsStackerTaskRequest; import com.wms_main.model.dto.response.wcs.BaseWcsApiResponse; import com.wms_main.model.dto.response.wcs.WcsApiResponse; +import com.wms_main.model.dto.response.wcs.WcsCanFeedResponse; /** * wcs接口服务 @@ -39,4 +41,11 @@ public interface IWcsApiService { * @return 发送结果 */ WcsApiResponse cancelPickTask(WcsPickTaskRequest request); + + /** + * 查询是否可上料 + * @param request 查询请求信息 + * @return 查询结果 + */ + WcsApiResponse canFeed(WcsCanFeedRequest request); } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/ExternalApiServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/ExternalApiServiceImpl.java index 3d5eb7c..cfa878f 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/ExternalApiServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/ExternalApiServiceImpl.java @@ -4,7 +4,7 @@ import com.wms_main.app.AppCommon; import com.wms_main.constant.enums.wms.AppConfigKeyEnums; import com.wms_main.model.dto.request.mywms.OrderInCBReq; import com.wms_main.model.dto.request.mywms.OrderOutCBReq; -import com.wms_main.model.dto.response.mywms.MyWmsResponse; +import com.wms_main.model.dto.response.mes.MesApiResponse; import com.wms_main.repository.http.HttpClient; import com.wms_main.repository.http.entity.HttpRequest; import com.wms_main.repository.http.entity.HttpResponse; @@ -12,12 +12,6 @@ import com.wms_main.service.api.IExternalApiService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import com.alibaba.fastjson.JSON; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; @Service @RequiredArgsConstructor @@ -26,87 +20,27 @@ public class ExternalApiServiceImpl implements IExternalApiService { private final HttpClient httpClient;// http客户端 private final AppCommon appCommon;// 应用共通 -// @Override -// public YcwmsResponse getVehicleNoData(String vehicleNo) { -// Map request = new HashMap<>(); -// request.put("vehicleNo", vehicleNo); -// HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.ERP_GET_VEHICLENO_DATA.getKey()), request); -// HttpResponse httpResponse = httpClient.httpPost(httpRequest); -// if (httpResponse != null && httpResponse.isSuccess()) { -// try { -// String responseMessage = httpResponse.getResponseMessage(); -// // 使用Map接收基本响应,避免泛型问题 -// Map baseResponseMap = JSON.parseObject(responseMessage, Map.class); -// -// // 创建最终返回的对象 -// YcwmsResponse finalResponse = new YcwmsResponse<>(); -// finalResponse.setCode((Integer) baseResponseMap.get("code")); -// finalResponse.setMessage((String) baseResponseMap.get("message")); -// -// // 处理returnData部分 -// if (baseResponseMap.containsKey("returnData") && baseResponseMap.get("returnData") != null) { -// // 转换returnData部分 -// Map returnDataMap = (Map) baseResponseMap.get("returnData"); -// -// // 创建ErpVehicleNoResp对象 -// ErpVehicleNoResp vehicleData = new ErpVehicleNoResp(); -// vehicleData.setVehicleNo((String) returnDataMap.get("vehicleNo")); -// -// // 处理goodsDetail数组 -// List> goodsDetailList = (List>) returnDataMap.get("goodsDetail"); -// List erpsGoodsDetails = new ArrayList<>(); -// -// if (goodsDetailList != null) { -// for (Map detail : goodsDetailList) { -// ErpGoodsDetail goodsDetail = new ErpGoodsDetail(); -// goodsDetail.setGoodsId((String) detail.get("goodsId")); -// goodsDetail.setGoodsName((String) detail.get("goodsName")); -// goodsDetail.setBatch((String) detail.get("batch")); -// goodsDetail.setGoodsType((String) detail.get("goodsType")); -// goodsDetail.setSpecification((String) (detail.get("specification"))); -// goodsDetail.setQuantity(Double.parseDouble(detail.get("quantity").toString())); -// goodsDetail.setGoodsDesc((String) detail.get("goodsDesc")); -// goodsDetail.setXsfbillno((String) detail.get("xsfbillno")); -// goodsDetail.setXsfseq(Integer.parseInt(detail.get("xsfseq").toString())); -// goodsDetail.setNeibubianhao((String) detail.get("neibubianhao")); -// goodsDetail.setGoodsBarcode((String) detail.get("goodsBarcode")); -// erpsGoodsDetails.add(goodsDetail); -// } -// } -// -// vehicleData.setGoodsDetail(erpsGoodsDetails); -// finalResponse.setReturnData(vehicleData); -// } -// -// return finalResponse; -// } catch (Exception e) { -// return YcwmsResponse.error("解析响应数据失败: " + e.getMessage(), null); -// } -// } -// return YcwmsResponse.error("请求未获得响应信息。", null); -// } - @Override - public MyWmsResponse invokeOrderInCB(OrderInCBReq request) { - HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_MANAGE_CALLBACK.getKey()), request); + public MesApiResponse invokeOrderInCB(OrderInCBReq request) { + HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_ORDER_IN_CALLBACK.getKey()), request); HttpResponse httpResponse = httpClient.httpPost(httpRequest); if (httpResponse != null && httpResponse.isSuccess()) { - MyWmsResponse response = new MyWmsResponse(); - response = httpResponse.getData(response.getClass().asSubclass(MyWmsResponse.class)); + MesApiResponse response = new MesApiResponse(); + response = httpResponse.getData(response.getClass().asSubclass(MesApiResponse.class)); return response; } - return MyWmsResponse.error("操作失败!", null); + return MesApiResponse.error("操作失败!"); } @Override - public MyWmsResponse invokeOrderOutCB(OrderOutCBReq request) { - HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_MANAGE_CALLBACK.getKey()), request); + public MesApiResponse invokeOrderOutCB(OrderOutCBReq request) { + HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_ORDER_OUT_CALLBACK.getKey()), request); HttpResponse httpResponse = httpClient.httpPost(httpRequest); if (httpResponse != null && httpResponse.isSuccess()) { - MyWmsResponse response = new MyWmsResponse(); - response = httpResponse.getData(response.getClass().asSubclass(MyWmsResponse.class)); + MesApiResponse response = new MesApiResponse(); + response = httpResponse.getData(response.getClass().asSubclass(MesApiResponse.class)); return response; } - return MyWmsResponse.error("操作失败!", null); + return MesApiResponse.error("操作失败!"); } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/WcsApiServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/WcsApiServiceImpl.java index 1490142..b54b13d 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/WcsApiServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/api/serviceImpl/WcsApiServiceImpl.java @@ -4,19 +4,26 @@ import com.wms_main.app.AppCommon; import com.wms_main.constant.enums.wms.AppConfigKeyEnums; import com.wms_main.model.bo.wcs.WcsPickTask; import com.wms_main.model.bo.wcs.WcsStackerTask; +import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest; import com.wms_main.model.dto.request.wcs.WcsPickTaskRequest; import com.wms_main.model.dto.request.wcs.WcsReleaseBoxRequest; import com.wms_main.model.dto.request.wcs.WcsStackerTaskRequest; import com.wms_main.model.dto.response.wcs.BaseWcsApiResponse; import com.wms_main.model.dto.response.wcs.WcsApiResponse; +import com.wms_main.model.dto.response.wcs.WcsCanFeedResponse; +import com.wms_main.model.po.TAppAgvLock; import com.wms_main.repository.http.HttpClient; import com.wms_main.repository.http.entity.HttpRequest; import com.wms_main.repository.http.entity.HttpResponse; import com.wms_main.service.api.IWcsApiService; +import com.wms_main.service.business.IAgvLockService; +import com.wms_main.service.business.IStackerTaskService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; + /** * Wcs接口服务实现 */ @@ -26,6 +33,8 @@ import org.springframework.stereotype.Service; public class WcsApiServiceImpl implements IWcsApiService { private final HttpClient httpClient;// http客户端 private final AppCommon appCommon;// 应用共通 + private final IAgvLockService agvLockService;// AGV互锁服务 + private final IStackerTaskService stackerTaskService;// 库位分配服务 /** * 发送堆垛机任务 @@ -97,4 +106,27 @@ public class WcsApiServiceImpl implements IWcsApiService { } return WcsApiResponse.error("请求未获得响应信息。", null); } + + /** + * 查询WCS系统是否可上料 + * @param request 查询请求信息 + * @return 查询结果 + */ + @Override + public WcsApiResponse canFeed(WcsCanFeedRequest request) { + HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WCS_CAN_FEED_URL.getKey()), request); +// HttpResponse httpResponse = httpClient.httpPost(httpRequest); +// if (httpResponse != null && httpResponse.isSuccess()) { +// WcsApiResponse response = new WcsApiResponse<>(); +// response = httpResponse.getData(response.getClass().asSubclass(WcsApiResponse.class)); +// return response; +// } + // TODO error -> success +// return WcsApiResponse.error("请求未获得响应信息。", null); + WcsCanFeedResponse wcsCanFeedResponse = new WcsCanFeedResponse(); + wcsCanFeedResponse.setResponseTime(LocalDateTime.now()); + wcsCanFeedResponse.setMsg("success"); + wcsCanFeedResponse.setAllowAction(true); + return WcsApiResponse.success("成功", wcsCanFeedResponse); + } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IAgvLockService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IAgvLockService.java new file mode 100644 index 0000000..d45dba5 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IAgvLockService.java @@ -0,0 +1,52 @@ +package com.wms_main.service.business; + +import com.wms_main.model.po.TAppAgvLock; + +/** + * 入库口互锁服务接口 + * 管理单一入库口的AGV上料互锁机制 + */ +public interface IAgvLockService { + + /** + * AGV就位并放货后,锁定入库口 + * @param agvId AGV设备ID + * @param inboundPort 入库口编号 + * @return 锁定结果:成功返回锁定记录,失败返回null + */ + TAppAgvLock lockInboundPort(String agvId, String inboundPort); + + /** + * 检查入库口是否可以上料(MES系统调用) + * @param inboundPort 入库口编号 + * @return 是否可以上料 + */ + boolean canFeedToInboundPort(String inboundPort); + + /** + * 获取当前入库口处理中的任务数量 + * @param inboundPort 入库口编号 + * @return 处理中的任务数量 + */ + int getProcessingTaskCount(String inboundPort); + + /** + * 获取入库口状态描述 + * @param inboundPort 入库口编号 + * @return 状态描述(空闲/占用) + */ + String getInboundPortStatus(String inboundPort); + + /** + * 清理超时锁定 + * @return 清理的记录数 + */ + int cleanTimeoutLocks(); + + /** + * 释放指定入库口的所有活动锁定 + * @param inboundPort 入库口编号 + * @return 释放的锁定数量 + */ + int releaseAllInboundPortLocks(String inboundPort); +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IDepthStrategyService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IDepthStrategyService.java index a53afc2..cd0a1dd 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IDepthStrategyService.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/IDepthStrategyService.java @@ -13,11 +13,11 @@ import java.util.List; public interface IDepthStrategyService { /** - * 分析出库订单的深度策略 - * @param orderOut 出库订单 + * 基于载具号分析深度策略 + * @param vehicleNo 载具号 * @return 深度策略分析结果 */ - DepthStrategyResult analyzeDepthStrategy(TAppOrderOut orderOut); + DepthStrategyResult analyzeDepthStrategyByVehicle(String vehicleNo); /** * 获取指定库位的深度信息 diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/AgvLockServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/AgvLockServiceImpl.java new file mode 100644 index 0000000..51187c5 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/AgvLockServiceImpl.java @@ -0,0 +1,232 @@ +package com.wms_main.service.business.serviceImpl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.wms_main.constant.enums.wms.WmsAgvLockEnums; +import com.wms_main.dao.ITAppAgvLockService; +import com.wms_main.dao.ITAppTaskService; +import com.wms_main.model.po.TAppAgvLock; +import com.wms_main.model.po.TAppTask; +import com.wms_main.constant.enums.wms.WmsTaskTypeEnums; +import com.wms_main.constant.enums.wms.WmsStackerTaskStatusEnums; +import com.wms_main.repository.utils.StringUtils; +import com.wms_main.repository.utils.UUIDUtils; +import com.wms_main.service.business.IAgvLockService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 入库口互锁服务实现 + * 管理单一入库口的AGV上料互锁机制 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class AgvLockServiceImpl implements IAgvLockService { + + private final ITAppAgvLockService agvLockService; + private final ITAppTaskService appTaskService; + + private static final String DEFAULT_INBOUND_PORT = "R1"; // 默认入库口 + private static final int DEFAULT_TIMEOUT_SECONDS = 600; // 默认超时时间10分钟 + + @Override + @Transactional + public TAppAgvLock lockInboundPort(String agvId, String inboundPort) { + if (StringUtils.isEmpty(agvId)) { + log.warn("AGV ID为空"); + return null; + } + + // 使用默认入库口如果未指定 + if (StringUtils.isEmpty(inboundPort)) { + inboundPort = DEFAULT_INBOUND_PORT; + } + + // 清理超时锁定 + cleanTimeoutLocks(); + + // 检查入库口是否已被占用 + List existingLocks = agvLockService.list(new LambdaQueryWrapper().eq(TAppAgvLock::getFeedStation, inboundPort)); + if (existingLocks == null || existingLocks.isEmpty()) { + return createInboundPortLock(agvId, inboundPort); + } else { + agvLockService.update( + new LambdaUpdateWrapper() + .eq(TAppAgvLock::getFeedStation, inboundPort) + .eq(TAppAgvLock::getLockStatus, WmsAgvLockEnums.AVAILABLE.getCode()) + .set(TAppAgvLock::getLockStatus, WmsAgvLockEnums.LOCK.getCode()) + .set(TAppAgvLock::getLockTime, LocalDateTime.now()) + .set(TAppAgvLock::getRemark, "AGV就位并放货,锁定入库口") + ); + return null; + } + } + + @Override + public boolean canFeedToInboundPort(String inboundPort) { + // 使用默认入库口如果未指定 + if (StringUtils.isEmpty(inboundPort)) { + inboundPort = DEFAULT_INBOUND_PORT; + } + + // 清理超时锁定 + cleanTimeoutLocks(); + + // 检查入库口是否有活动的锁定 + List activeLocks = agvLockService.getByStation(inboundPort); + boolean hasActiveLock = activeLocks.stream() + .anyMatch(lock -> lock.getLockStatus() == 1); + + if (hasActiveLock) { + log.debug("入库口 {} 当前被占用,无法上料", inboundPort); + return false; + } + + // 检查是否有正在处理的入库任务 + int processingTasks = getProcessingTaskCount(inboundPort); + boolean canFeed = processingTasks == 0; + + log.debug("入库口 {} 可上料状态: {}, 处理中任务数: {}", inboundPort, canFeed, processingTasks); + return canFeed; + } + + @Override + public int getProcessingTaskCount(String inboundPort) { + // 使用默认入库口如果未指定 + if (StringUtils.isEmpty(inboundPort)) { + inboundPort = DEFAULT_INBOUND_PORT; + } + + // 统计正在处理的入库任务数量(包括等待、运行状态的任务) + List processingTasks = appTaskService.list( + new LambdaQueryWrapper() + .eq(TAppTask::getTaskType, WmsTaskTypeEnums.IN.getCode()) + .in(TAppTask::getTaskStatus, + WmsStackerTaskStatusEnums.WAIT.getCode(), + WmsStackerTaskStatusEnums.RUN.getCode()) + .like(TAppTask::getOrigin, inboundPort) // 假设任务来源包含入库口信息 + ); + + return processingTasks.size(); + } + + @Override + public String getInboundPortStatus(String inboundPort) { + // 使用默认入库口如果未指定 + if (StringUtils.isEmpty(inboundPort)) { + inboundPort = DEFAULT_INBOUND_PORT; + } + + // 检查是否有活动锁定 + List activeLocks = agvLockService.getByStation(inboundPort); + boolean hasActiveLock = activeLocks.stream() + .anyMatch(lock -> lock.getLockStatus() == 1); + + if (hasActiveLock) { + return "占用"; + } + + // 检查是否有处理中的任务 + int processingTasks = getProcessingTaskCount(inboundPort); + if (processingTasks > 0) { + return "占用"; + } + + return "空闲"; + } + + @Override + @Transactional + public int cleanTimeoutLocks() { + List timeoutLocks = agvLockService.getTimeoutLocks(); + if (timeoutLocks.isEmpty()) { + return 0; + } + + try { + for (TAppAgvLock lock : timeoutLocks) { + agvLockService.update( + new LambdaUpdateWrapper() + .eq(TAppAgvLock::getLockId, lock.getLockId()) + .set(TAppAgvLock::getLockStatus, 0) + .set(TAppAgvLock::getUnlockTime, LocalDateTime.now()) + .set(TAppAgvLock::getRemark, "超时自动释放") + ); + + log.info("释放超时锁定: AGV {} 在入库口 {}", lock.getAgvId(), lock.getFeedStation()); + } + + log.info("清理了 {} 个超时锁定", timeoutLocks.size()); + return timeoutLocks.size(); + } catch (Exception e) { + log.error("清理超时锁定失败", e); + return 0; + } + } + + @Override + @Transactional + public int releaseAllInboundPortLocks(String inboundPort) { + // 使用默认入库口如果未指定 + if (StringUtils.isEmpty(inboundPort)) { + inboundPort = DEFAULT_INBOUND_PORT; + } + + try { + // 释放指定入库口的所有活动锁定 + agvLockService.update( + new LambdaUpdateWrapper() + .eq(TAppAgvLock::getFeedStation, inboundPort) + .eq(TAppAgvLock::getLockStatus, WmsAgvLockEnums.LOCK.getCode()) + .set(TAppAgvLock::getLockStatus, WmsAgvLockEnums.AVAILABLE.getCode()) + .set(TAppAgvLock::getUnlockTime, LocalDateTime.now()) + .set(TAppAgvLock::getRemark, "入库任务完成,批量释放锁定") + ); + + // 查询实际释放的锁定数量 + List activeLocks = agvLockService.getByStation(inboundPort); + int releasedCount = (int) activeLocks.stream() + .filter(lock -> lock.getLockStatus() == 0) + .count(); + + log.info("释放入库口 {} 的所有锁定,共释放 {} 个锁定", inboundPort, releasedCount); + return releasedCount; + } catch (Exception e) { + log.error("释放入库口 {} 的所有锁定失败", inboundPort, e); + return 0; + } + } + + /** + * 创建入库口锁定记录 + */ + private TAppAgvLock createInboundPortLock(String agvId, String inboundPort) { + TAppAgvLock lock = new TAppAgvLock(); + lock.setLockId(UUIDUtils.getNewUUID()); + lock.setAgvId(agvId); + lock.setFeedStation(inboundPort); + lock.setLockStatus(1); + lock.setLockType("INBOUND_PORT_LOCK"); + lock.setPriority(1); + lock.setQueuePosition(1); + lock.setLockTime(LocalDateTime.now()); + lock.setTimeoutSeconds(DEFAULT_TIMEOUT_SECONDS); + lock.setCreateTime(LocalDateTime.now()); + lock.setUpdateTime(LocalDateTime.now()); + lock.setRemark("AGV就位并放货,锁定入库口"); + + if (agvLockService.save(lock)) { + log.info("AGV {} 成功锁定入库口 {}", agvId, inboundPort); + return lock; + } + + log.error("AGV {} 锁定入库口 {} 失败", agvId, inboundPort); + return null; + } +} \ No newline at end of file diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/DepthStrategyServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/DepthStrategyServiceImpl.java index 3429599..caa073d 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/DepthStrategyServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/DepthStrategyServiceImpl.java @@ -19,7 +19,7 @@ import java.util.List; /** * 简化后的深度策略服务实现 - * 核心逻辑:根据inTaskId查询库存,检测深度策略 + * 核心逻辑:基于载具号查询库存,检测深度策略 */ @Service @RequiredArgsConstructor @@ -31,36 +31,32 @@ public class DepthStrategyServiceImpl implements IDepthStrategyService { private final IStackerTaskService stackerTaskService; /** - * 分析出库订单的深度策略(核心方法) + * 基于载具号分析深度策略(新核心方法) */ @Override - public DepthStrategyResult analyzeDepthStrategy(TAppOrderOut orderOut) { - // 1. 参数验证 - if (orderOut == null || StringUtils.isEmpty(orderOut.getInTaskId())) { - log.warn("出库订单为空或入库任务ID为空"); - return DepthStrategyResult.createError("订单信息不完整"); + public DepthStrategyResult analyzeDepthStrategyByVehicle(String vehicleNo) { + if (StringUtils.isEmpty(vehicleNo)) { + log.warn("载具号为空"); + return DepthStrategyResult.createError("载具号不能为空"); } - // 2. 根据inTaskId查询唯一库存 TAppStock stock = appStockService.getOne( new LambdaQueryWrapper() - .eq(TAppStock::getInTaskId, orderOut.getInTaskId()) + .eq(TAppStock::getVehicleId, vehicleNo) .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()) ); if (stock == null) { - log.warn("入库任务ID{}对应的库存不存在", orderOut.getInTaskId()); - return DepthStrategyResult.createError("库存不存在"); + log.warn("载具号{}对应的库存不存在", vehicleNo); + return DepthStrategyResult.createError("载具库存不存在"); } - // 3. 获取库存深度 Integer depth = getLocationDepth(stock.getLocationId()); if (depth == null) { log.warn("无法解析库存位置深度: {}", stock.getLocationId()); return DepthStrategyResult.createError("库位深度解析失败"); } - // 4. 深度策略判断 if (depth == 1) { return DepthStrategyResult.createDirectOut("深度1,直接出库"); } else if (depth == 2) { diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java index 0d78c52..e8ff980 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java @@ -3,10 +3,13 @@ package com.wms_main.service.business.serviceImpl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.wms_main.app.AppCommon; +import com.wms_main.constant.enums.mywms.OrderInCBEnums; +import com.wms_main.constant.enums.mywms.OrderOutCBEnums; import com.wms_main.constant.enums.wms.*; import com.wms_main.dao.*; +import com.wms_main.model.dto.request.mywms.OrderInCBReq; import com.wms_main.model.dto.request.mywms.OrderOutCBReq; -import com.wms_main.model.dto.response.mywms.MyWmsResponse; +import com.wms_main.model.dto.response.mes.MesApiResponse; import com.wms_main.model.po.*; import com.wms_main.repository.utils.ConvertUtils; import com.wms_main.repository.utils.StringUtils; @@ -22,7 +25,6 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import static com.wms_main.repository.utils.ConvertUtils.convertDestinationToPoint; /** * 服务实现 @@ -391,27 +393,28 @@ public class StackerTaskServiceImpl implements IStackerTaskService { .eq(TAppStock::getVehicleId, orderIn.getVehicleNo())); } -// OrderInCBReq orderInCBReq = new OrderInCBReq(); -// orderInCBReq.setOrderId(orderIn.getOrderId()); -// orderInCBReq.setVehicleNo(wmsTask.getVehicleId()); -// orderInCBReq.setOrderStatus(OrderStatusEnum.COMPLETE.getCode()); -// orderInCBReq.setMessage("入库完成"); -// -// int times = 0; -// MyWmsResponse response = null; -// do { -// Thread.sleep(15000L * times); -// response = externalApiService.invokeOrderInCB(orderInCBReq); -// times++; -// } while (!response.getMessage().equals("success") && times <= 10); -// if (response.getMessage().equals("error")) { -// log.error("[wms]上报失败"); -// } else { -// log.info("[wms]上报成功"); -// } - if (!appOrderInService.removeById(orderIn.getRecordId())) { - log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId()); - } + OrderInCBReq orderInCBReq = new OrderInCBReq(); + orderInCBReq.setTaskId(orderIn.getOrderId()); + orderInCBReq.setVehicleNo(wmsTask.getVehicleId()); + orderInCBReq.setLocationId(wmsTask.getDestination()); + orderInCBReq.setResult(OrderInCBEnums.COMPLETE.getCode()); + orderInCBReq.setResultMessage("入库完成"); + + // int times = 0; + // MesApiResponse response = null; + // do { + // Thread.sleep(15000L * times); + // response = externalApiService.invokeOrderInCB(orderInCBReq); + // times++; + // } while (response.getCode() != 0 && times <= 10); + // if (response.getCode() != 0) { + // log.error("[wms]上报失败"); + // } else { + // log.info("[wms]上报成功"); + // } + // if (!appOrderInService.removeById(orderIn.getRecordId())) { + // log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId()); + // } TAppVehicle vehicle = new TAppVehicle(); vehicle.setVehicleId(wmsTask.getVehicleId()); vehicle.setVehicleStatus(WmsVehicleStatusEnums.ON.getCode()); @@ -508,6 +511,12 @@ public class StackerTaskServiceImpl implements IStackerTaskService { .eq(TAppStock::getVehicleId, vehicleId)); // 当前载具的任务列表 List thisVehicleOutTasks = vehicleIdToTaskMap.get(vehicleId); + if (thisVehicleOutTasks.isEmpty()) { + continue; + } + List orderIds = thisVehicleOutTasks.stream().map(TAppTask::getTaskGroup).distinct().toList(); + List orderOuts = appOrderOutService.list(new LambdaQueryWrapper() + .in(TAppOrderOut::getOrderId, orderIds)); if (!thisVehicleOutTasks.isEmpty()) { // 存储出库记录 List stockOutRecordList = thisVehicleOutTasks.stream() @@ -519,39 +528,30 @@ public class StackerTaskServiceImpl implements IStackerTaskService { .eq(TAppTask::getTaskType, WmsTaskTypeEnums.OUT.getCode()) .in(TAppTask::getTaskId, thisVehicleOutTasks.stream().map(TAppTask::getTaskId).toList())); // 使用流删除关联的出库订单实体(新增的核心部分) - List orderIds = thisVehicleOutTasks.stream().map(TAppTask::getTaskGroup).distinct().toList(); - List orderOuts = appOrderOutService.list(new LambdaQueryWrapper() - .in(TAppOrderOut::getOrderId, orderIds)); if (!orderOuts.isEmpty()) { appOrderOutService.removeBatchByIds(orderOuts); } } -// List orderOutsId = thisVehicleOutTasks.stream().map(TAppTask::getTaskGroup).distinct().toList(); -// for (String orderId : orderOutsId) { -// if (orderId.contains("baokai")) { -// continue; -// } -// List appTasks = vehicleIdToTaskMap.get(vehicleId); -// OrderOutCBReq orderOutCBReq = new OrderOutCBReq(); -// orderOutCBReq.setOrderId(orderId); -// orderOutCBReq.setVehicleNo(vehicleId); -// orderOutCBReq.setOrderStatus(OrderStatusEnum.COMPLETE.getCode()); -// orderOutCBReq.setOutStand(convertDestinationToPoint(appTasks.getFirst().getDestination())); -// orderOutCBReq.setMessage("出库完成"); -// -// int times = 0; -// MyWmsResponse response = null; -// do { -// response = externalApiService.invokeOrderOutCB(orderOutCBReq); -// times++; -// Thread.sleep(15000L * times); -// } while (!response.getMessage().equals("success") && times <= 10); -// if (response.getMessage().equals("error")) { -// log.error("[WMS]上报失败"); -// } else { -// log.info("[WMS]上报成功"); -// } -// } + // for (TAppOrderOut orderOut : orderOuts) { + // OrderOutCBReq orderOutCBReq = new OrderOutCBReq(); + // orderOutCBReq.setTaskId(orderOut.getOrderId()); + // orderOutCBReq.setVehicleNo(vehicleId); + // orderOutCBReq.setResult(OrderOutCBEnums.COMPLETE.getCode()); + // orderOutCBReq.setResultMessage("出库完成"); + + // int times = 0; + // MesApiResponse response = null; + // do { + // response = externalApiService.invokeOrderOutCB(orderOutCBReq); + // times++; + // Thread.sleep(15000L * times); + // } while (response.getCode() != 0 && times <= 10); + // if (response.getCode() != 0) { + // log.error("[WMS]上报失败"); + // } else { + // log.info("[WMS]上报成功"); + // } + // } } } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/IMyWmsControllerService.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/IMyWmsControllerService.java index 7d216d2..d3cf1a8 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/IMyWmsControllerService.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/IMyWmsControllerService.java @@ -14,4 +14,8 @@ public interface IMyWmsControllerService { MyWmsResponse orderOut(OrderOutReq request); MyWmsResponse> stock(StockReq request); + + MyWmsResponse queryCanFeed(); + + MyWmsResponse queryCanOut(); } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/MyWmsControllerServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/MyWmsControllerServiceImpl.java index c393810..c188c0f 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/MyWmsControllerServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/MyWmsControllerServiceImpl.java @@ -1,23 +1,32 @@ package com.wms_main.service.controller.serviceImpl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.fasterxml.jackson.databind.ObjectMapper; import com.wms_main.constant.enums.wms.OrderStatusEnum; -import com.wms_main.constant.enums.wms.StorageTypeEnums; import com.wms_main.constant.enums.wms.WmsDepthStrategyEnums; -import com.wms_main.constant.enums.wms.WmsTaskTypeEnums; +import com.wms_main.constant.enums.wms.WmsStockStatusEnums; +import com.wms_main.dao.ITAppAgvLockService; +import com.wms_main.dao.ITAppLocationService; import com.wms_main.dao.ITAppOrderInService; import com.wms_main.dao.ITAppOrderOutService; import com.wms_main.dao.ITAppStockService; import com.wms_main.model.bo.wms.DepthStrategyResult; import com.wms_main.model.dto.request.mywms.*; +import com.wms_main.model.dto.request.wcs.WcsCanFeedRequest; import com.wms_main.model.dto.response.mywms.MyWmsResponse; +import com.wms_main.model.dto.response.wcs.WcsApiResponse; +import com.wms_main.model.dto.response.wcs.WcsCanFeedResponse; +import com.wms_main.model.po.TAppLocation; import com.wms_main.model.po.TAppOrderIn; import com.wms_main.model.po.TAppOrderOut; import com.wms_main.model.po.TAppStock; import com.wms_main.repository.utils.StringUtils; import com.wms_main.repository.utils.UUIDUtils; +import com.wms_main.service.api.IWcsApiService; +import com.wms_main.service.business.IAgvLockService; import com.wms_main.service.business.IDepthStrategyService; +import com.wms_main.service.business.IStackerTaskService; import com.wms_main.service.controller.IMyWmsControllerService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -35,8 +44,14 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { private final ITAppOrderOutService appOrderOutService; private final ITAppStockService appStockService; private final IDepthStrategyService depthStrategyService; + private final ITAppLocationService appLocationService; + private final IStackerTaskService stackerTaskService; + private final IAgvLockService agvLockService; + private final IWcsApiService wcsApiService; private final ObjectMapper objectMapper = new ObjectMapper(); + private static final String L_TEMP_FLAG = "temp"; + @Override public MyWmsResponse orderIn(OrderInReq request) { try { @@ -44,9 +59,6 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { if (!request.isValid()) { return MyWmsResponse.error("参数错误", null); } - if (!Objects.equals(request.getStorageId(), StorageTypeEnums.BOX.getCode())) { - return MyWmsResponse.error("仓库号错误", null); - } // 校验是否存在相同的入库单 List withTaskId = appOrderInService.getWithTaskId(request.getTaskId()); if (withTaskId == null) { @@ -59,8 +71,8 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { orderIn.setRecordId(UUIDUtils.getNewUUID()); orderIn.setOrderId(request.getTaskId()); orderIn.setVehicleNo(request.getVehicleNo()); - orderIn.setInStand(request.getStandId()); - orderIn.setRequestUser(request.getRequestUser()); + orderIn.setInStand("R1"); + orderIn.setRequestUser("wms"); orderIn.setOrderStatus(OrderStatusEnum.CREATE.getCode()); orderIn.setCreateTime(LocalDateTime.now()); orderIn.setUpdateTime(LocalDateTime.now()); @@ -76,13 +88,10 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { @Override public MyWmsResponse orderOut(OrderOutReq request) { try { - if (request == null) return MyWmsResponse.error("参数错误", null); - if (StringUtils.isEmpty(request.getTaskId()) - || request.getDetails() == null - || request.getStorageId() == null - || !Objects.equals(request.getTaskType(), WmsTaskTypeEnums.OUT.getCode())) { + if (request == null || StringUtils.isEmpty(request.getTaskId()) || StringUtils.isEmpty(request.getVehicleNo())) { return MyWmsResponse.error("参数错误", null); } + List orderOutCheckList = appOrderOutService.getWithTaskId(request.getTaskId()); if (orderOutCheckList == null) { return MyWmsResponse.error("数据服务异常,请稍后重试", null); @@ -90,29 +99,39 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { if (!orderOutCheckList.isEmpty()) { return MyWmsResponse.error("出库单已存在,请勿重复推送", null); } - List orderOutList = new ArrayList<>(); - for (OrderOutGoodsDetail orderOutGoodsDetail : request.getDetails()) { - TAppOrderOut orderOut = new TAppOrderOut(); - orderOut.setRecordId(UUIDUtils.getNewUUID()); - orderOut.setOrderId(request.getTaskId()); - orderOut.setInTaskId(orderOutGoodsDetail.getInTaskId()); - orderOut.setOrderStatus(OrderStatusEnum.CREATE.getCode()); - orderOut.setCreateTime(LocalDateTime.now()); - orderOut.setUpdateTime(LocalDateTime.now()); - DepthStrategyResult depthStrategy = depthStrategyService.analyzeDepthStrategy(orderOut); - orderOut.setDepthStrategy(depthStrategy.getStrategy().getCode()); - orderOut.setDepthStrategyDetail(objectMapper.writeValueAsString(depthStrategy)); - if (orderOut.getDepthStrategy().equals(WmsDepthStrategyEnums.NO_ACTION.getCode())) { - return MyWmsResponse.error("载具出库任务添加失败:" + orderOut.getInTaskId(), null); - } - orderOutList.add(orderOut); + List vehicleStocks = appStockService.list( + new LambdaQueryWrapper() + .eq(TAppStock::getVehicleId, request.getVehicleNo()) + .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()) + ); + + if (vehicleStocks == null || vehicleStocks.isEmpty()) { + return MyWmsResponse.error("载具号" + request.getVehicleNo() + "无库存记录", null); } - if (!appOrderOutService.saveBatch(orderOutList)) { + + TAppOrderOut orderOut = new TAppOrderOut(); + orderOut.setRecordId(UUIDUtils.getNewUUID()); + orderOut.setOrderId(request.getTaskId()); + orderOut.setVehicleNo(request.getVehicleNo()); + orderOut.setOrderStatus(OrderStatusEnum.CREATE.getCode()); + orderOut.setCreateTime(LocalDateTime.now()); + orderOut.setUpdateTime(LocalDateTime.now()); + + DepthStrategyResult depthStrategy = depthStrategyService.analyzeDepthStrategyByVehicle(request.getVehicleNo()); + orderOut.setDepthStrategy(depthStrategy.getStrategy().getCode()); + orderOut.setDepthStrategyDetail(objectMapper.writeValueAsString(depthStrategy)); + + if (orderOut.getDepthStrategy().equals(WmsDepthStrategyEnums.NO_ACTION.getCode())) { + return MyWmsResponse.error("载具出库任务添加失败:" + request.getVehicleNo(), null); + } + + if (!appOrderOutService.save(orderOut)) { return MyWmsResponse.error("出库单保存失败,请稍后再试", null); } return MyWmsResponse.success(); } catch (Exception e) { + log.error("出库任务添加失败", e); return MyWmsResponse.error("出库任务添加失败,请稍后再试", null); } } @@ -130,7 +149,6 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { new LambdaQueryWrapper() .eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getVehicleNo()), TAppStock::getVehicleId, stockReqGoodsDetail.getVehicleNo()) .eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getLocationId()), TAppStock::getLocationId, stockReqGoodsDetail.getLocationId()) - .eq(StringUtils.isNotEmpty(stockReqGoodsDetail.getInTaskId()), TAppStock::getInTaskId, stockReqGoodsDetail.getInTaskId()) ); if (stockList != null && !stockList.isEmpty()) { for (TAppStock stock : stockList) { @@ -156,4 +174,39 @@ public class MyWmsControllerServiceImpl implements IMyWmsControllerService { } return MyWmsResponse.success(respList); } + + @Override + public MyWmsResponse queryCanFeed() { + TAppLocation location = stackerTaskService.requestOneLocation(null, L_TEMP_FLAG); + if (location != null && StringUtils.isNotEmpty(location.getLocationId())) { + appLocationService.update(new LambdaUpdateWrapper() + .eq(TAppLocation::getLocationId, location.getLocationId()) + .set(TAppLocation::getIsOccupy, 0) + .set(TAppLocation::getVehicleId, "")); + return MyWmsResponse.success(true); + } + return MyWmsResponse.error("无剩余可用库位", false); + } + + @Override + public MyWmsResponse queryCanOut() { + try { + WcsApiResponse wcsResponse = wcsApiService.canFeed(new WcsCanFeedRequest("R1")); + + if (wcsResponse != null && wcsResponse.getData() != null) { + Boolean wcsAllow = wcsResponse.getData().isAllowAction(); + Boolean wmsAllow = agvLockService.canFeedToInboundPort("R1"); + + if (wcsAllow && wmsAllow) { + return MyWmsResponse.success(true); + } else { + return MyWmsResponse.error("出库口锁定中", null); + } + } else { + return MyWmsResponse.error("WCS系统查询失败", null); + } + } catch (Exception e) { + return MyWmsResponse.error("系统异常,请稍后重试", null); + } + } } diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/TaskControllerServiceImpl.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/TaskControllerServiceImpl.java index eabbd18..cf6bf60 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/TaskControllerServiceImpl.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/controller/serviceImpl/TaskControllerServiceImpl.java @@ -18,6 +18,7 @@ import com.wms_main.model.po.*; import com.wms_main.repository.utils.ConvertUtils; import com.wms_main.repository.utils.StringUtils; import com.wms_main.repository.utils.UUIDUtils; +import com.wms_main.service.business.IAgvLockService; import com.wms_main.service.business.IStackerTaskService; import com.wms_main.service.controller.ITaskControllerService; import lombok.RequiredArgsConstructor; @@ -41,11 +42,18 @@ public class TaskControllerServiceImpl implements ITaskControllerService { private final IStackerTaskService stackerTaskService;// 堆垛机任务服务 private final ITAppOrderInService orderInService; private final ITAppWcsTaskBakService appWcsTaskBakService; + private final IAgvLockService agvLockService;// AGV互锁服务 @Override @Transactional public WcsVehicleInResponse requireInTask(WcsVehicleInRequest request) { String vehicleNo = request.getVehicleNo(); + String origin = request.getOrigin(); + String inboundPort = "R1"; // 默认入库口 + + log.info("收到入库请求 - 载具号: {}, 来源: {}, 入库口: {}", + vehicleNo, origin, inboundPort); + TAppOrderIn orderIn = orderInService.getOne( new LambdaQueryWrapper() .eq(StringUtils.isNotEmpty(vehicleNo), TAppOrderIn::getVehicleNo, vehicleNo) @@ -55,6 +63,12 @@ public class TaskControllerServiceImpl implements ITaskControllerService { return WcsVehicleInResponse.error(String.format("条码:%s 不存在待入库的订单", vehicleNo)); } + // 检查入库口是否可用(不关心具体是哪台AGV) + boolean canFeed = agvLockService.canFeedToInboundPort(inboundPort); + if (!canFeed) { + return WcsVehicleInResponse.error("入库口被占用,请等待其他任务完成后再试"); + } + /* 查找可用库位 */ TAppLocation useLocation = stackerTaskService.requestOneLocation(null, vehicleNo); if (useLocation == null) { @@ -93,6 +107,7 @@ public class TaskControllerServiceImpl implements ITaskControllerService { .set(TAppOrderIn::getOrderStatus, OrderStatusEnum.RUNNING.getCode()) .set(TAppOrderIn::getUpdateTime, LocalDateTime.now()) ); + agvLockService.lockInboundPort("AGV", ""); WcsVehicleInResponse success = new WcsVehicleInResponse(); success.setCode("200"); @@ -144,6 +159,19 @@ public class TaskControllerServiceImpl implements ITaskControllerService { .eq(TAppOrderIn::getOrderId, wmsTask.getTaskGroup()) .set(TAppOrderIn::getOrderStatus, OrderStatusEnum.COMPLETE.getCode()) .set(TAppOrderIn::getCompleteTime, LocalDateTime.now())); + + // 如果是入库任务完成,释放入库口锁定 + if (wmsTask != null && WmsTaskTypeEnums.IN.getCode().equals(wmsTask.getTaskType())) { + try { + String inboundPort = "R1"; // 默认入库口 + + // 释放该入库口的所有活动锁定,不关心具体是哪台AGV + int releasedCount = agvLockService.releaseAllInboundPortLocks(inboundPort); + log.info("入库任务完成,释放入库口 {} 的锁定,共释放 {} 个锁定", inboundPort, releasedCount); + } catch (Exception e) { + log.error("释放入库口锁定时发生异常", e); + } + } // 移除wcs任务,并向wcs备份表添加记录 TAppWcsTaskBak wcsTaskBak = new TAppWcsTaskBak( wcsTask.getWcsTaskId(), diff --git a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/quartz_job/job_executor/MyOutExecutor.java b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/quartz_job/job_executor/MyOutExecutor.java index 9876c52..b61f50d 100644 --- a/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/quartz_job/job_executor/MyOutExecutor.java +++ b/202504-Wms-MengYang-box/wms_serve_mengyang/src/main/java/com/wms_main/service/quartz_job/job_executor/MyOutExecutor.java @@ -63,10 +63,10 @@ public class MyOutExecutor implements Job { */ private void processSingleOrder(TAppOrderOut order) { try { - // 1. 根据inTaskId获取关联库存 - TAppStock stock = getStockByInTaskId(order.getInTaskId()); + // 1. 根据载具号获取关联库存 + TAppStock stock = getStockByVehicleNo(order.getVehicleNo()); if (stock == null) { - log.error("未找到inTaskId关联的库存: {}", order.getInTaskId()); + log.error("未找到载具号关联的库存: {}", order.getVehicleNo()); return; } @@ -107,12 +107,12 @@ public class MyOutExecutor implements Job { } /** - * 根据inTaskId获取唯一库存 + * 根据载具号获取唯一库存 */ - private TAppStock getStockByInTaskId(String inTaskId) { + private TAppStock getStockByVehicleNo(String vehicleNo) { return appStockService.getOne( new LambdaQueryWrapper() - .eq(TAppStock::getInTaskId, inTaskId) + .eq(TAppStock::getVehicleId, vehicleNo) .eq(TAppStock::getStockStatus, WmsStockStatusEnums.OK.getCode()) ); } diff --git a/202504-Wms-MengYang-box/wms_web_mengyang/CLAUDE.md b/202504-Wms-MengYang-box/wms_web_mengyang/CLAUDE.md new file mode 100644 index 0000000..1af79f3 --- /dev/null +++ b/202504-Wms-MengYang-box/wms_web_mengyang/CLAUDE.md @@ -0,0 +1,209 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 项目概述 + +这是宝应梦阳WMS前端项目(BOX料箱库版本),基于Vue 3和Element Plus开发的现代化Web管理界面,用于仓库管理系统的操作和监控。 + +## 开发环境设置 + +### 基本命令 +```bash +# 进入项目目录 +cd 202504-Wms-MengYang-box/wms_web_mengyang + +# 安装依赖 +npm install + +# 启动开发服务器 +npm run serve + +# 构建生产版本 +npm run build + +# 代码检查和修复 +npm run lint +``` + +### 开发配置 +- **开发端口**:12306 +- **路由模式**:Hash路由 (`createWebHashHistory`) +- **默认路由**:登录页面 (`/`) -> 主页 (`/home`) -> 库存页面 (`/stock`) +- **代理配置**:Microsoft OAuth认证代理 + +## 技术栈 + +### 核心框架 +- **Vue 3.2.13** - 前端框架(Composition API) +- **Vue Router 4.0.3** - 路由管理 +- **Vuex 4.0.0** - 状态管理 +- **Element Plus 2.4.0** - UI组件库 + +### 主要依赖 +- **Axios 1.3.3** - HTTP请求库 +- **Moment 2.29.4** - 日期处理 +- **XLSX 0.18.5** - Excel文件处理 +- **QRCode.vue 3.4.1** - 二维码生成 +- **Vue3-print-nb 0.1.4** - 打印功能 +- **File-saver 2.0.5** - 文件下载 + +### 开发工具 +- **Sass 1.83.4** - CSS预处理器 +- **Vue CLI 5.0** - 构建工具 +- **ESLint** - 代码质量检查(已关闭未使用变量警告) + +## 项目架构 + +### 目录结构 +``` +src/ +├── api/ # API接口封装 +├── assets/ # 静态资源 +├── components/ # 可复用组件 +├── constant/ # 常量配置 +├── excel/ # Excel上传组件 +├── http/ # HTTP请求配置 +├── layout/ # 业务页面组件 +├── print/ # 打印相关组件 +├── router/ # 路由配置 +├── store/ # Vuex状态管理 +├── styles/ # 全局样式 +├── utils/ # 工具函数 +└── views/ # 主要视图组件 +``` + +### 核心业务模块 + +#### 1. 仓库作业 (`layout/`) +**库存管理** +- `stock.vue` - 库存查询和管理 +- `inventory.vue` - 库存盘点 +- `inventoryRecord.vue` - 盘点记录 + +**入出库作业** +- `goodsIn.vue` - 入库作业界面 +- `goodsOut.vue` - 出库作业界面 +- `orderIn.vue` - 入库单管理 +- `orderOut.vue` - 出库单管理 + +**任务监控** +- `taskMonitor.vue` - 任务执行监控 +- `pickTaskMonitor.vue` - 拣选任务监控 +- `inTaskRecord.vue` - 入库任务记录 +- `outTaskRecord.vue` - 出库任务记录 + +#### 2. 基础数据管理 +- `goods.vue` - 物料信息管理 +- `locationsTable.vue` - 库位信息管理 +- `standSettings.vue` - 站台(库口)设置 +- `vehicle.vue` - 料箱监控 + +#### 3. 配料系统 +- `kitting.vue` - 配料作业 +- `kittingList.vue` - 配料单管理 +- `kittingRelation.vue` - 配料关系配置 +- `clcKanban.vue` - 需求看板 + +#### 4. 系统管理 +- `wmsConfigNew.vue` - 系统配置 +- `role_user.vue` - 用户角色管理 +- `role_permission.vue` - 权限管理 +- `wmsLog.vue` - 系统日志 + +### API接口模块 (`api/`) + +**核心业务接口** +- `goods.js` - 物料信息API +- `stock.js` - 库存相关API +- `task.js` - 任务管理API +- `location.js` - 库位管理API + +**作业流程接口** +- `orderIn.js` - 入库订单API +- `orderOut.js` - 出库订单API +- `kateWork.js` - 配料作业API + +**系统功能接口** +- `login.js` - 登录认证API +- `user.js` - 用户管理API +- `config.js` - 系统配置API +- `excel.js` - Excel处理API + +### 公共组件 (`components/`) +- `sideMenu.vue` - 侧边菜单导航 +- `appTag.vue` - 标签页管理 + +### 工具模块 (`utils/`) +- `dateUtils.js` - 日期处理工具 +- `formatter.js` - 数据格式化 +- `hashUtils.js` - 哈希计算 +- `stringUtils.js` - 字符串处理 +- `loading.js` - 加载状态管理 +- `myMessageBox.js` - 消息提示封装 + +## 开发注意事项 + +### 路由配置 +- 使用Hash路由模式,兼容性更好 +- 实现了路由守卫,未登录用户自动跳转登录页 +- 登录状态通过`sessionStorage`中的`user`字段判断 + +### 状态管理 +- 使用Vuex进行全局状态管理 +- 主要管理用户信息、菜单权限、标签页状态 + +### HTTP请求 +- 统一使用Axios进行API调用 +- 请求封装在`/http/request.js`中 +- API接口按业务模块分类组织 + +### Excel处理 +- 支持Excel文件上传和解析 +- 专门的Excel上传组件位于`excel/`目录 +- 支持多种业务数据的Excel导入导出 + +### 打印功能 +- 使用`vue3-print-nb`实现打印功能 +- 打印组件位于`print/`目录 + +### 样式规范 +- 使用Sass预处理器 +- 全局样式文件:`styles/index.scss` +- 响应式设计,支持不同屏幕尺寸 + +## 常见开发任务 + +### 添加新页面 +1. 在`layout/`目录创建Vue组件 +2. 在`router/index.js`中配置路由 +3. 如需API调用,在`api/`目录创建对应接口文件 +4. 更新侧边菜单配置 + +### Excel上传功能 +1. 参考`excel/`目录下的现有组件 +2. 使用Element Plus的上传组件 +3. 后端API处理Excel数据解析 + +### 新增API接口 +1. 在`api/`目录按模块创建文件 +2. 使用`@/http/request`进行请求封装 +3. 导出接口函数供组件使用 + +### 调试和测试 +- 使用Vue DevTools检查组件状态 +- 浏览器开发者工具调试网络请求 +- ESLint检查代码质量 +- 在不同浏览器中测试兼容性 + +## 后端API集成 + +### 默认后端地址 +根据当前配置,后端API地址需要在`http/request.js`中配置,通常为: +- 开发环境:`http://localhost:12315` +- 生产环境:`http://10.18.58.21:12315` + +### 认证机制 +- 支持Microsoft OAuth认证代理 +- 登录状态存储在`sessionStorage`中 +- 路由守卫自动验证用户登录状态 \ No newline at end of file diff --git a/202504-Wms-MengYang-tp/wms_serve_mengyang/CLAUDE.md b/202504-Wms-MengYang-tp/wms_serve_mengyang/CLAUDE.md index 4ff4417..0e3fe7c 100644 --- a/202504-Wms-MengYang-tp/wms_serve_mengyang/CLAUDE.md +++ b/202504-Wms-MengYang-tp/wms_serve_mengyang/CLAUDE.md @@ -4,12 +4,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## 项目概述 -这是一个宝应梦阳WMS(仓库管理系统)后端项目,基于Spring Boot 3.3.5和Java 21开发,使用Maven构建。系统管理仓库的入库、出库、库存和任务调度等核心业务。 +这是宝应梦阳WMS(仓库管理系统)后端项目(TP托盘库版本),基于Spring Boot 3.3.5和Java 21开发,使用Maven构建。专门针对托盘库存储场景,管理仓库的入库、出库、库存和任务调度等核心业务。 + +## 项目特点 + +**TP托盘库版本特性** +- 专为托盘存储优化的算法策略 +- 支持大型货物的托盘化存储管理 +- 与BOX料箱库版本在业务逻辑上有所差异 +- 数据库schema针对托盘库场景设计 ## 开发环境设置 -### 构建和运行命令 +### 基本构建命令 ```bash +# 进入项目目录 +cd 202504-Wms-MengYang-tp/wms_serve_mengyang + # 编译项目 mvn clean compile @@ -19,19 +30,30 @@ mvn clean package # 运行项目 mvn spring-boot:run -# 跳过测试运行(默认配置) +# 使用Maven Wrapper +./mvnw spring-boot:run + +# 跳过测试运行(项目配置默认跳过测试) mvn clean package -Dmaven.test.skip=true ``` -### 数据库配置 -- 本地开发:MySQL `localhost:3306/wms_mengyang_box` -- 生产环境:MySQL `10.18.58.21:3306/wms_yachi_nantong` -- 用户名/密码:本地使用root/root,生产使用user/user +### 运行环境配置 -### 应用配置 +**数据库配置** +- 本地开发:MySQL `localhost:3306/wms_mengyang_tp`(注意:使用tp数据库) +- 生产环境:MySQL `10.18.58.21:3306/wms_yachi_nantong` +- 认证信息:本地使用root/root,生产使用user/user + +**应用配置** - 服务端口:12315 - 应用名称:wms_main - 文件上传限制:单文件100MB,总计1000MB +- 当前配置:`spring.profiles.active=online` + +**Maven特殊配置** +- 项目默认跳过单元测试:`maven-surefire-plugin.skip=true` +- 最终构建文件名:`wms-box-server`(注意:名称还是box-server但实际是tp版本) +- Java版本:21 (source和target都是21) ## 核心架构 @@ -50,50 +72,134 @@ mvn clean package -Dmaven.test.skip=true - `POST /stock` - 库存查询接口 #### 2. 深度策略服务 (`service/business/DepthStrategyService`) -核心算法模块,实现智能仓储策略: -- 支持托盘库(TP)和料箱库(BOX)两种存储类型 -- 动态深度分析和出库优化策略 +核心算法模块,针对托盘库优化: +- **托盘库(TP)专属存储策略** +- 大型货物的存储位置优化算法 +- 托盘堆叠和存取路径优化 #### 3. 任务调度系统 (`service/quartz_job/`) -基于Quartz的定时任务: +基于Quartz的定时任务框架: - `WmsTaskExecutor` - WMS任务执行器 - `MyOutExecutor` - 出库任务执行器 -- `WcsStackerTaskSender` - WCS任务发送器 +- `WcsStackerTaskSender` - WCS堆垛机任务发送器 #### 4. 设备集成 (`service/api/`) -- `WcsApiService` - WCS系统集成 +- `WcsApiService` - WCS系统集成(托盘库设备) - `ExternalApiService` - 外部系统API调用 ### 数据模型结构 -- `po/` - 数据库实体对象(Persistent Object) +- `po/` - 数据库实体对象(针对托盘库schema) - `dto/request/` - 请求数据传输对象 - `dto/response/` - 响应数据传输对象 - `bo/` - 业务对象(Business Object) - `vo/` - 视图对象(View Object) ### 常用枚举类 (`constant/enums/`) -- `StorageTypeEnums` - 存储类型(托盘库TP/料箱库BOX) -- `WmsDepthStrategyEnums` - 深度策略枚举 + +**WMS业务枚举** (`enums/wms/`) +- `StorageTypeEnums` - 存储类型(重点关注TP托盘库类型) +- `WmsDepthStrategyEnums` - 深度策略枚举(托盘库专用策略) - `WmsTaskTypeEnums` - 任务类型枚举 - `OrderStatusEnum` - 订单状态枚举 +- `WmsLocationTypeEnums` - 货位类型枚举(托盘货位) +- `WmsVehicleStatusEnums` - 载具状态枚举(托盘载具) + +**WCS集成枚举** (`enums/wcs/`) +- `WcsApiResponseCodeEnums` - WCS API响应码 +- `WcsStackerTaskTypeEnums` - 堆垛机任务类型(托盘堆垛机) +- `WcsStackerTaskStatusEnums` - 堆垛机任务状态 ## 技术栈 ### 核心依赖 -- Spring Boot Web 3.3.5 - REST API框架 -- Spring Boot Quartz - 定时任务调度 -- MyBatis-Plus 3.5.7 - ORM框架 -- MySQL Connector - 数据库连接 -- Lombok - 代码简化 +- **Spring Boot Web 3.3.5** - REST API框架 +- **Spring Boot Quartz** - 定时任务调度 +- **MyBatis-Plus 3.5.7** - ORM框架 +- **MySQL Connector** - 数据库连接 +- **Lombok** - 代码简化 ### 工具库 -- Hutool 5.8.33 - Java工具类库 -- FastJSON 2.0.21 - JSON处理 -- EasyExcel 4.0.3 & EasyPOI 4.5.0 - Excel处理 -- Apache HttpClient 4.5.13 - HTTP客户端 -- Google Guava 33.3.1 - 集合工具 +- **Hutool 5.8.33** - Java工具类库 +- **FastJSON 2.0.21** - JSON处理 +- **EasyExcel 4.0.3 & EasyPOI 4.5.0** - Excel处理 +- **Apache HttpClient 4.5.13** - HTTP客户端 +- **Google Guava 33.3.1** - 集合工具 -## 开发注意事项 +## 重要的文件路径 + +- **主要工作目录**:`202504-Wms-MengYang-tp/wms_serve_mengyang/` +- **日志存储**:`wms_log/` (按日期和级别分类) +- **数据库脚本**:`db/wms_mengyang_tp.sql` +- **MyBatis映射**:`src/main/resources/mapper/` + +## 常见开发任务 + +### 启动应用 +```bash +cd 202504-Wms-MengYang-tp/wms_serve_mengyang +mvn spring-boot:run +``` + +### 查看日志 +```bash +# 查看今天的info日志 +tail -f wms_log/info/$(date +%Y-%m-%d)/$(date +%Y-%m-%d).0.log + +# 查看今天的error日志 +tail -f wms_log/error/$(date +%Y-%m-%d)/$(date +%Y-%m-%d).0.log +``` + +### 数据库操作 +- 使用MyBatis-Plus进行ORM操作 +- 支持批量操作和事务处理 +- 驼峰命名自动映射(`map-underscore-to-camel-case: true`) +- ID生成策略:`assign_id` + +## 系统集成要点 + +### WCS系统集成(托盘库专用) +- TCP和HTTP双协议支持 +- **托盘堆垛机**任务调度和状态同步 +- **托盘载具**管理和追踪 + +### 任务调度系统 +- 基于Quartz的定时任务框架 +- 关键执行器针对托盘库场景优化 +- 任务状态实时监控 + +### Excel处理 +- 后端:EasyExcel 4.0.3 + EasyPOI 4.5.0 +- 支持托盘库相关的业务数据导入导出 +- 模板位置:`excel/easypoi/excelTemplate/` + +## TP与BOX版本的差异 + +### 主要区别 +1. **数据库schema**:使用`wms_mengyang_tp`数据库 +2. **存储策略算法**:针对托盘存储特点优化 +3. **设备集成**:对接托盘库专用设备 +4. **业务规则**:托盘的尺寸、重量、堆叠规则不同 + +### 开发注意事项 +- 在开发新功能时,注意区分TP和BOX版本的业务差异 +- 深度策略算法需要考虑托盘的物理特性 +- WCS集成需要适配托盘库的设备类型 + +## 故障排除 + +### 常见问题 +1. **端口冲突**:确认12315端口未被占用 +2. **数据库连接**:检查MySQL服务状态和TP数据库配置 +3. **版本混淆**:确认操作的是TP版本而非BOX版本 +4. **日志分析**:按级别查看对应日志目录 + +### 调试技巧 +- 使用`RequestLogFilter`查看API请求日志 +- 通过`WmsControllerExceptionHandler`统一异常处理 +- 检查定时任务执行状态:查看`TAppJobs`表 +- 注意区分TP和BOX版本的业务逻辑差异 + +## 开发规范 ### 代码规范 - 使用Lombok注解减少样板代码 @@ -101,43 +207,10 @@ mvn clean package -Dmaven.test.skip=true - 枚举类管理常量值 - 接口-实现分离的服务层设计 -### 数据库操作 -- 使用MyBatis-Plus进行ORM操作 -- 支持批量操作和事务处理 -- 驼峰命名自动映射 -- ID生成策略:assign_id - -### 错误处理 -- 统一异常处理器:`WmsControllerExceptionHandler` -- 标准化错误码:`WmsApiResponseCodeEnums` -- 请求日志过滤器:`RequestLogFilter` - -### Excel处理 -系统支持完整的Excel导入导出功能: -- 货物信息、产品信息、库存信息等业务数据 -- 使用EasyExcel和EasyPOI双重支持 -- 模板位置:`excel/easypoi/excelTemplate/` - -## 外部系统集成 - -### WCS系统集成 -- 堆垛机任务调度 -- 载具管理(托盘和料箱) -- TCP/HTTP通信协议 - -### MES系统对接 -- 制造执行系统数据交换 -- 生产任务状态同步 - -## 测试说明 - -项目配置中跳过了单元测试执行(`maven-surefire-plugin.skip=true`),在开发新功能时建议: +### 测试建议 +项目配置跳过单元测试,建议: 1. 先实现功能代码 2. 使用Postman等工具进行API测试 -3. 检查数据库数据状态 +3. 检查托盘库相关的数据库数据状态 4. 验证定时任务执行情况 - -## Claude交互指南 - -### AI助手通用记录 -- 说中文,think hard \ No newline at end of file +5. 测试WCS设备集成功能 \ No newline at end of file diff --git a/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/MyWmsController.http b/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/MyWmsController.http new file mode 100644 index 0000000..18721bd --- /dev/null +++ b/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/MyWmsController.http @@ -0,0 +1,66 @@ +### MyWMS接口测试 +### 基础配置 +@baseUrl = http://localhost:12315 + +### 1. 入库订单接口 +POST {{baseUrl}}/mywms/orderIn +Content-Type: application/json + +{ + "taskId": "testOrderId1", + "vehicleNo": "1001" +} + +### 2. 出库订单接口 +POST {{baseUrl}}/mywms/orderOut +Content-Type: application/json + +{ + "taskId": "testOrderId1", + "vehicleNo": "1001" +} + +### 3. 库存查询接口 - 仅按载具查询 +POST {{baseUrl}}/mywms/stock +Content-Type: application/json + +{ + "requestId": "testOrderId1", + "details": [ + { + "vehicleNo": "1001" + } + ] +} + +### 4. 库存查询接口 - 仅按库位查询 +POST {{baseUrl}}/mywms/stock +Content-Type: application/json + +{ + "requestId": "testOrderId2", + "details": [ + { + "locationId": "A01-01-01-02" + } + ] +} + +### 5. 检查是否允许投料 +GET {{baseUrl}}/mywms/allowFeed + +### 测试数据说明 +# 1. orderIn: 入库订单接口,需要taskId和vehicleNo +# 2. orderOut: 出库订单接口,需要taskId和vehicleNo +# 3. stock: 库存查询接口,需要requestId和details数组 +# - details中可以包含vehicleNo和/或locationId +# 4. allowFeed: 查询当前系统是否允许投料操作(GET请求) + +### 响应格式说明 +# 所有接口都返回MyWmsResponse格式: +# { +# "code": 200, // 响应码 +# "message": "操作成功", // 响应消息 +# "data": {}, // 具体数据 +# "success": true // 是否成功 +# } \ No newline at end of file diff --git a/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/TaskController.http b/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/TaskController.http new file mode 100644 index 0000000..15dd20c --- /dev/null +++ b/202504-Wms-MengYang-tp/wms_serve_mengyang/api-tests/TaskController.http @@ -0,0 +1,60 @@ +### TaskController接口测试 - WMS任务控制接口 +### 基础配置 +@baseUrl = http://localhost:12315 + +### 1. WCS请求载具入库 +POST {{baseUrl}}/wms/task/wcsRequestVehicleIn +Content-Type: application/json + +{ + "origin": "R1", + "vehicleNo": "1001", + "codeMessage": "test", + "remark": "载具入库测试" +} + +### 2. 发送任务结果 - 任务完成 +POST {{baseUrl}}/wms/task/sendTaskResult +Content-Type: application/json + +{ + "taskId": "TASK202507240001", + "taskStatus": 100, + "vehicleNo": "1001", + "destination": "A01-01-01-02", + "message": "任务执行成功" +} + +### 测试数据说明 +# 1. wcsRequestVehicleIn: WCS请求载具入库 +# - origin: 点位(必填) +# - vehicleNo: 载具信息(必填) +# - codeMessage: 条码信息(可选) +# - remark: 备注(可选) + +# 2. sendTaskResult: WCS反馈任务执行结果 +# - taskId: 任务ID(必填) +# - taskStatus: 任务状态(必填) +# * 0: 等待执行 +# * 1: 执行中 +# * 2: 执行完成 +# * 3: 执行失败 +# - vehicleNo: 载具号(必填) +# - destination: 终点(可选) +# - message: 信息(可选) + +### 响应格式说明 +# wcsRequestVehicleIn返回WcsVehicleInResponse: +# { +# "success": true, +# "code": "SUCCESS", +# "message": "请求成功", +# "data": {} +# } + +# sendTaskResult返回BaseWcsApiResponse: +# { +# "success": true, +# "code": "SUCCESS", +# "message": "任务结果接收成功" +# } \ No newline at end of file diff --git a/202504-Wms-MengYang-tp/wms_serve_mengyang/pom.xml b/202504-Wms-MengYang-tp/wms_serve_mengyang/pom.xml index 57aea11..a999ade 100644 --- a/202504-Wms-MengYang-tp/wms_serve_mengyang/pom.xml +++ b/202504-Wms-MengYang-tp/wms_serve_mengyang/pom.xml @@ -9,10 +9,10 @@ com - dev_wms_serve + wms_serve_mengyang_tp 3.2 - dev_wms_serve - dev_wms_serve + wms_serve_mengyang_tp + wms_serve_mengyang_tp @@ -162,6 +162,15 @@ true + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + UTF-8 + + diff --git a/202504-Wms-MengYang-tp/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java b/202504-Wms-MengYang-tp/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java index c83e09a..24ac327 100644 --- a/202504-Wms-MengYang-tp/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java +++ b/202504-Wms-MengYang-tp/wms_serve_mengyang/src/main/java/com/wms_main/service/business/serviceImpl/StackerTaskServiceImpl.java @@ -10,7 +10,6 @@ import com.wms_main.dao.*; import com.wms_main.model.dto.request.mywms.OrderInCBReq; import com.wms_main.model.dto.request.mywms.OrderOutCBReq; import com.wms_main.model.dto.response.mes.MesApiResponse; -import com.wms_main.model.dto.response.mywms.MyWmsResponse; import com.wms_main.model.po.*; import com.wms_main.repository.utils.ConvertUtils; import com.wms_main.repository.utils.StringUtils; @@ -26,7 +25,6 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import static com.wms_main.repository.utils.ConvertUtils.convertDestinationToPoint; /** * 服务实现 @@ -60,11 +58,6 @@ public class StackerTaskServiceImpl implements IStackerTaskService { */ private final ITAppTaskBakService appTaskBakService; - private final ITAppWcsTaskBakService appWcsTaskBakService; - /** - * 拣选任务服务 - */ - private final ITAppPickTaskService appPickTaskService; /** * 设备服务 */ @@ -402,21 +395,21 @@ public class StackerTaskServiceImpl implements IStackerTaskService { orderInCBReq.setResult(OrderInCBEnums.COMPLETE.getCode()); orderInCBReq.setResultMessage("入库完成"); - int times = 0; - MesApiResponse response = null; - do { - Thread.sleep(15000L * times); - response = externalApiService.invokeOrderInCB(orderInCBReq); - times++; - } while (response.getCode() != 0 && times <= 10); - if (response.getCode() != 0) { - log.error("[wms]上报失败"); - } else { - log.info("[wms]上报成功"); - } - if (!appOrderInService.removeById(orderIn.getRecordId())) { - log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId()); - } + // int times = 0; + // MesApiResponse response = null; + // do { + // Thread.sleep(15000L * times); + // response = externalApiService.invokeOrderInCB(orderInCBReq); + // times++; + // } while (response.getCode() != 0 && times <= 10); + // if (response.getCode() != 0) { + // log.error("[wms]上报失败"); + // } else { + // log.info("[wms]上报成功"); + // } + // if (!appOrderInService.removeById(orderIn.getRecordId())) { + // log.info("整箱入库完成删除入库单失败,任务:{},原因:删除入库单失败", wmsTask.getTaskId()); + // } TAppVehicle vehicle = new TAppVehicle(); vehicle.setVehicleId(wmsTask.getVehicleId()); vehicle.setVehicleStatus(WmsVehicleStatusEnums.ON.getCode()); @@ -534,27 +527,26 @@ public class StackerTaskServiceImpl implements IStackerTaskService { appOrderOutService.removeBatchByIds(orderOuts); } } - for (TAppOrderOut orderOut : orderOuts) { - List appTasks = vehicleIdToTaskMap.get(vehicleId); - OrderOutCBReq orderOutCBReq = new OrderOutCBReq(); - orderOutCBReq.setTaskId(orderOut.getOrderId()); - orderOutCBReq.setVehicleNo(vehicleId); - orderOutCBReq.setResult(OrderOutCBEnums.COMPLETE.getCode()); - orderOutCBReq.setResultMessage("出库完成"); + // for (TAppOrderOut orderOut : orderOuts) { + // OrderOutCBReq orderOutCBReq = new OrderOutCBReq(); + // orderOutCBReq.setTaskId(orderOut.getOrderId()); + // orderOutCBReq.setVehicleNo(vehicleId); + // orderOutCBReq.setResult(OrderOutCBEnums.COMPLETE.getCode()); + // orderOutCBReq.setResultMessage("出库完成"); - int times = 0; - MesApiResponse response = null; - do { - response = externalApiService.invokeOrderOutCB(orderOutCBReq); - times++; - Thread.sleep(15000L * times); - } while (response.getCode() != 0 && times <= 10); - if (response.getCode() != 0) { - log.error("[WMS]上报失败"); - } else { - log.info("[WMS]上报成功"); - } - } + // int times = 0; + // MesApiResponse response = null; + // do { + // response = externalApiService.invokeOrderOutCB(orderOutCBReq); + // times++; + // Thread.sleep(15000L * times); + // } while (response.getCode() != 0 && times <= 10); + // if (response.getCode() != 0) { + // log.error("[WMS]上报失败"); + // } else { + // log.info("[WMS]上报成功"); + // } + // } } } } diff --git a/202504-Wms-MengYang-tp/wms_web_mengyang/CLAUDE.md b/202504-Wms-MengYang-tp/wms_web_mengyang/CLAUDE.md new file mode 100644 index 0000000..7cc1559 --- /dev/null +++ b/202504-Wms-MengYang-tp/wms_web_mengyang/CLAUDE.md @@ -0,0 +1,263 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## 项目概述 + +这是宝应梦阳WMS前端项目(TP托盘库版本),基于Vue 3和Element Plus开发的现代化Web管理界面,专门用于托盘库存储场景的仓库管理系统操作和监控。 + +## 项目特点 + +**TP托盘库版本特性** +- 专为托盘存储场景设计的UI界面 +- 支持大型货物的托盘化存储管理操作 +- 与BOX料箱库版本在业务功能上有所差异 +- 针对托盘库的专用业务流程和界面优化 + +## 开发环境设置 + +### 基本命令 +```bash +# 进入项目目录 +cd 202504-Wms-MengYang-tp/wms_web_mengyang + +# 安装依赖 +npm install + +# 启动开发服务器 +npm run serve + +# 构建生产版本 +npm run build + +# 代码检查和修复 +npm run lint +``` + +### 开发配置 +- **开发端口**:12306 +- **路由模式**:Hash路由 (`createWebHashHistory`) +- **默认路由**:登录页面 (`/`) -> 主页 (`/home`) -> 库存页面 (`/stock`) +- **代理配置**:Microsoft OAuth认证代理 + +### 与BOX版本的区别 +- 项目结构和技术栈基本相同 +- **主要差异在业务逻辑**:托盘存储相关的界面和交互 +- **后端API对接**:调用TP版本后端的专用接口 +- **数据展示**:针对托盘库的数据字段和格式 + +## 技术栈 + +### 核心框架 +- **Vue 3.2.13** - 前端框架(Composition API) +- **Vue Router 4.0.3** - 路由管理 +- **Vuex 4.0.0** - 状态管理 +- **Element Plus 2.4.0** - UI组件库 + +### 主要依赖 +- **Axios 1.3.3** - HTTP请求库 +- **Moment 2.29.4** - 日期处理 +- **XLSX 0.18.5** - Excel文件处理 +- **QRCode.vue 3.4.1** - 二维码生成 +- **Vue3-print-nb 0.1.4** - 打印功能 +- **File-saver 2.0.5** - 文件下载 + +### 开发工具 +- **Sass 1.83.4** - CSS预处理器 +- **Vue CLI 5.0** - 构建工具 +- **ESLint** - 代码质量检查(已关闭未使用变量警告) + +## 项目架构 + +### 目录结构 +``` +src/ +├── api/ # API接口封装(托盘库专用接口) +├── assets/ # 静态资源 +├── components/ # 可复用组件 +├── constant/ # 常量配置(托盘库相关常量) +├── excel/ # Excel上传组件(托盘库数据) +├── http/ # HTTP请求配置 +├── layout/ # 业务页面组件(托盘库业务界面) +├── print/ # 打印相关组件 +├── router/ # 路由配置 +├── store/ # Vuex状态管理 +├── styles/ # 全局样式 +├── utils/ # 工具函数 +└── views/ # 主要视图组件 +``` + +### 核心业务模块(托盘库专用) + +#### 1. 托盘仓库作业 (`layout/`) +**库存管理** +- `stock.vue` - 托盘库存查询和管理 +- `inventory.vue` - 托盘库存盘点 +- `inventoryRecord.vue` - 盘点记录 + +**入出库作业** +- `goodsIn.vue` - 托盘入库作业界面 +- `goodsOut.vue` - 托盘出库作业界面 +- `orderIn.vue` - 托盘入库单管理 +- `orderOut.vue` - 托盘出库单管理 + +**任务监控** +- `taskMonitor.vue` - 托盘任务执行监控 +- `pickTaskMonitor.vue` - 托盘拣选任务监控 +- `inTaskRecord.vue` - 入库任务记录 +- `outTaskRecord.vue` - 出库任务记录 + +#### 2. 托盘基础数据管理 +- `goods.vue` - 托盘物料信息管理 +- `locationsTable.vue` - 托盘库位信息管理 +- `standSettings.vue` - 托盘站台(库口)设置 +- `vehicle.vue` - 托盘载具监控 + +#### 3. 托盘配料系统 +- `kitting.vue` - 托盘配料作业 +- `kittingList.vue` - 托盘配料单管理 +- `kittingRelation.vue` - 托盘配料关系配置 +- `clcKanban.vue` - 托盘需求看板 + +#### 4. 系统管理 +- `wmsConfigNew.vue` - 托盘库系统配置 +- `role_user.vue` - 用户角色管理 +- `role_permission.vue` - 权限管理 +- `wmsLog.vue` - 系统日志 + +### API接口模块 (`api/`) + +**托盘库核心业务接口** +- `goods.js` - 托盘物料信息API +- `stock.js` - 托盘库存相关API +- `task.js` - 托盘任务管理API +- `location.js` - 托盘库位管理API + +**托盘作业流程接口** +- `orderIn.js` - 托盘入库订单API +- `orderOut.js` - 托盘出库订单API +- `kateWork.js` - 托盘配料作业API + +**系统功能接口** +- `login.js` - 登录认证API +- `user.js` - 用户管理API +- `config.js` - 托盘库系统配置API +- `excel.js` - 托盘库Excel处理API + +### 公共组件 (`components/`) +- `sideMenu.vue` - 侧边菜单导航(托盘库功能菜单) +- `appTag.vue` - 标签页管理 + +### 工具模块 (`utils/`) +- `dateUtils.js` - 日期处理工具 +- `formatter.js` - 数据格式化(托盘库数据格式) +- `hashUtils.js` - 哈希计算 +- `stringUtils.js` - 字符串处理 +- `loading.js` - 加载状态管理 +- `myMessageBox.js` - 消息提示封装 + +## 托盘库特色功能 + +### 托盘存储特点 +- **大型货物管理**:支持重型和大尺寸货物的界面展示 +- **托盘堆叠显示**:可视化托盘堆叠状态和高度限制 +- **存取路径优化**:界面显示最优存取路径建议 +- **托盘载具追踪**:实时显示托盘在系统中的位置 + +### 与BOX版本的界面差异 +1. **数据字段不同**:托盘尺寸、重量、堆叠层数等专用字段 +2. **操作流程优化**:针对托盘存储的特殊操作步骤 +3. **监控界面**:托盘堆垛机状态、托盘载具位置等专用监控 +4. **报表格式**:托盘库专用的统计和报表格式 + +## 开发注意事项 + +### 路由配置 +- 使用Hash路由模式,兼容性更好 +- 实现了路由守卫,未登录用户自动跳转登录页 +- 登录状态通过`sessionStorage`中的`user`字段判断 + +### 状态管理 +- 使用Vuex进行全局状态管理 +- 主要管理用户信息、菜单权限、标签页状态 +- **托盘库专用状态**:托盘载具状态、堆垛机状态等 + +### HTTP请求 +- 统一使用Axios进行API调用 +- 请求封装在`/http/request.js`中 +- API接口按托盘库业务模块分类组织 +- **注意**:对接TP版本后端API(端口12315) + +### Excel处理(托盘库数据) +- 支持托盘库专用Excel模板的上传和解析 +- 专门的Excel上传组件位于`excel/`目录 +- 支持托盘物料、库存、任务等数据的Excel导入导出 + +### 打印功能 +- 使用`vue3-print-nb`实现打印功能 +- 打印组件位于`print/`目录 +- **托盘库专用**:托盘标签、任务单等打印格式 + +### 样式规范 +- 使用Sass预处理器 +- 全局样式文件:`styles/index.scss` +- 响应式设计,支持不同屏幕尺寸 +- **托盘库界面优化**:适配托盘库的数据展示需求 + +## 常见开发任务 + +### 添加托盘库新页面 +1. 在`layout/`目录创建Vue组件 +2. 在`router/index.js`中配置路由 +3. 如需API调用,在`api/`目录创建对应的托盘库接口文件 +4. 更新侧边菜单配置 +5. **注意**:考虑托盘库的业务特点和数据格式 + +### 托盘库Excel上传功能 +1. 参考`excel/`目录下的现有组件 +2. 使用Element Plus的上传组件 +3. 后端TP版本API处理托盘Excel数据解析 +4. **关键**:使用托盘库专用的Excel模板格式 + +### 新增托盘库API接口 +1. 在`api/`目录按模块创建文件 +2. 使用`@/http/request`进行请求封装 +3. 导出接口函数供组件使用 +4. **重要**:确保对接TP版本后端API + +### 调试和测试 +- 使用Vue DevTools检查组件状态 +- 浏览器开发者工具调试网络请求 +- ESLint检查代码质量 +- 在不同浏览器中测试兼容性 +- **托盘库专用测试**:验证托盘数据格式和业务逻辑 + +## 后端API集成 + +### 默认后端地址 +根据当前配置,后端TP版本API地址需要在`http/request.js`中配置: +- 开发环境:`http://localhost:12315`(TP版本后端) +- 生产环境:`http://10.18.58.21:12315` + +### 认证机制 +- 支持Microsoft OAuth认证代理 +- 登录状态存储在`sessionStorage`中 +- 路由守卫自动验证用户登录状态 + +## 开发建议 + +### TP与BOX版本协同开发 +1. **代码复用**:公共组件和工具函数可以复用 +2. **业务差异**:注意托盘库和料箱库的业务逻辑差异 +3. **数据格式**:确保使用正确的数据字段和格式 +4. **API对接**:确认对接的是TP版本后端而非BOX版本 + +### 性能优化 +- 托盘库数据量通常较大,注意列表分页和懒加载 +- 图表和监控界面的实时更新优化 +- Excel处理时的内存管理 + +### 用户体验 +- 托盘库操作相对复杂,提供清晰的操作指引 +- 错误提示和状态反馈要及时准确 +- 支持键盘快捷操作,提高操作效率 \ No newline at end of file