From cd483c81d1dffac5613575f52649d5b0e0b72df3 Mon Sep 17 00:00:00 2001 From: liejiu946 Date: Mon, 15 Dec 2025 10:42:02 +0800 Subject: [PATCH] =?UTF-8?q?add:=E7=AC=AC=E4=B8=80=E7=89=88=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=89=88=E6=9C=AC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/schedule/map/api/ScheduleMapAPI.java | 13 + .../setting/api/ScheduleSettingAPI.java | 26 ++ .../core/ScheduleAPISettingChargeParam.java | 31 ++ .../core/ScheduleAPISettingSpeedParam.java | 18 ++ .../schedule/task/api/ScheduleTaskAPI.java | 58 ++++ .../ScheduleAPICreateOneClickTaskParam.java | 30 ++ .../task/core/ScheduleAPICreateTaskParam.java | 36 +++ .../org/nl/api/setting/api/SettingAPI.java | 16 + .../java/org/nl/api/task/api/TaskAPI.java | 31 ++ .../map/controller/MapMonitorController.java | 26 ++ .../nl/monitor/map/dto/StationInfoDto.java | 47 +++ .../map/service/MapMonitorService.java | 12 + .../service/impl/MapMonitorServiceImpl.java | 53 ++++ nl-business-schedule/pom.xml | 21 ++ .../nl/schedule/core/util/ScheduleUtil.java | 31 ++ .../websocket/WebSocketVehicleInfoServer.java | 153 +++++++++ .../map/provider/ScheduleMapAPIProvider.java | 33 ++ .../provider/ScheduleSettingAPIProvider.java | 57 ++++ .../ScheduleTaskRequestReportController.java | 28 ++ .../param/ScheduleTaskArrivedReportParam.java | 30 ++ .../provider/ScheduleTaskAPIProvider.java | 182 +++++++++++ .../task/service/ScheduleTaskService.java | 13 + .../service/impl/ScheduleTaskServiceImpl.java | 88 ++++++ .../vehicle/controller/VehicleController.java | 32 ++ .../modular/vehicle/dto/VehicleInfoDto.java | 70 +++++ .../modular/vehicle/entity/Location.java | 21 ++ .../vehicle/service/VehicleService.java | 24 ++ .../service/impl/VehicleServiceImpl.java | 103 +++++++ .../modular/controller/SettingController.java | 36 +++ .../modular/controller/TestController.java | 23 -- .../nl/setting/modular/entity/Setting.java | 65 ++++ .../modular/enums/SettingCodeEnum.java | 61 ++++ .../setting/modular/mapper/SettingMapper.java | 14 + .../modular/mapper/mapping/SettingMapping.xml | 5 + .../modular/param/UpdateSettingParam.java | 33 ++ .../modular/provider/SettingAPIProvider.java | 38 +++ .../modular/service/SettingService.java | 26 ++ .../service/impl/SettingServiceImpl.java | 139 +++++++++ nl-business-task/pom.xml | 6 + .../nl/task/controller/TaskController.java | 73 +++++ .../main/java/org/nl/task/entity/Task.java | 99 ++++++ .../nl/task/enums/ScheduleTaskStatusEnum.java | 60 ++++ .../org/nl/task/enums/TaskSourceEnum.java | 39 +++ .../org/nl/task/enums/TaskStatusEnum.java | 39 +++ .../java/org/nl/task/enums/TaskTypeEnum.java | 53 ++++ .../java/org/nl/task/mapper/TaskMapper.java | 14 + .../org/nl/task/mapper/mapping/TaskMapper.xml | 5 + .../nl/task/param/CancelTaskRequestParam.java | 18 ++ .../nl/task/param/CreateTaskRequestParam.java | 39 +++ .../param/OneClickOperationRequestParam.java | 24 ++ .../task/param/PauseAndResumeTaskParam.java | 18 ++ .../org/nl/task/provider/TaskAPIProvider.java | 67 ++++ .../java/org/nl/task/service/TaskService.java | 67 ++++ .../nl/task/service/impl/TaskServiceImpl.java | 290 ++++++++++++++++++ nl-common/pom.xml | 35 +++ .../main/java/org/nl/config/CorsConfig.java | 26 ++ .../enums/ScheduleTaskReportStatusEnum.java | 44 +++ .../main/java/org/nl/enums/YesOrNoEnum.java | 31 ++ .../main/java/org/nl/exception/ApiError.java | 49 +++ .../org/nl/exception/BadRequestException.java | 25 ++ .../nl/exception/GlobalExceptionHandler.java | 77 +++++ .../java/org/nl/logging/annotation/Log.java | 15 + .../java/org/nl/logging/aspect/LogAspect.java | 79 +++++ .../java/org/nl/response/WebResponse.java | 77 +++++ .../src/main/java/org/nl/util/IdUtil.java | 11 + .../org/nl/util/TaskCodeGeneratorUtil.java | 123 ++++++++ .../main/java/org/nl/util/ThrowableUtil.java | 22 ++ .../java/org/nl/util/WebSocketConfig.java | 18 ++ .../src/main/java/org/nl/Application.java | 9 +- nl-web-app/src/main/resources/banner.txt | 8 + .../main/resources/config/application-dev.yml | 93 ++++++ .../resources/config/application-prod.yml | 86 ++++++ .../src/main/resources/config/application.yml | 54 ++++ .../resources/language/buss/buss.properties | 7 + .../language/buss/buss_en_US.properties | 7 + .../language/buss/buss_zh_CN.properties | 7 + .../resources/language/error/error.properties | 29 ++ .../language/error/error_en_US.properties | 28 ++ .../language/error/error_zh_CN.properties | 28 ++ .../resources/language/task/task.properties | 5 + .../language/task/task_en_US.properties | 5 + .../language/task/task_zh_CN.properties | 5 + .../src/main/resources/logback-spring.xml | 73 +++++ pom.xml | 30 +- 84 files changed, 3714 insertions(+), 26 deletions(-) create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/map/api/ScheduleMapAPI.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/setting/api/ScheduleSettingAPI.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingChargeParam.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingSpeedParam.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/task/api/ScheduleTaskAPI.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateOneClickTaskParam.java create mode 100644 nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateTaskParam.java create mode 100644 nl-business-api/src/main/java/org/nl/api/setting/api/SettingAPI.java create mode 100644 nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java create mode 100644 nl-business-monitor/src/main/java/org/nl/monitor/map/controller/MapMonitorController.java create mode 100644 nl-business-monitor/src/main/java/org/nl/monitor/map/dto/StationInfoDto.java create mode 100644 nl-business-monitor/src/main/java/org/nl/monitor/map/service/MapMonitorService.java create mode 100644 nl-business-monitor/src/main/java/org/nl/monitor/map/service/impl/MapMonitorServiceImpl.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/core/util/ScheduleUtil.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/core/websocket/WebSocketVehicleInfoServer.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/map/provider/ScheduleMapAPIProvider.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/setting/provider/ScheduleSettingAPIProvider.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/task/controller/ScheduleTaskRequestReportController.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/task/param/ScheduleTaskArrivedReportParam.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/task/provider/ScheduleTaskAPIProvider.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/ScheduleTaskService.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/impl/ScheduleTaskServiceImpl.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/dto/VehicleInfoDto.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/entity/Location.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java create mode 100644 nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/controller/SettingController.java delete mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/controller/TestController.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/entity/Setting.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/enums/SettingCodeEnum.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/mapper/SettingMapper.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/mapper/mapping/SettingMapping.xml create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/param/UpdateSettingParam.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/provider/SettingAPIProvider.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/service/SettingService.java create mode 100644 nl-business-setting/src/main/java/org/nl/setting/modular/service/impl/SettingServiceImpl.java create mode 100644 nl-business-task/src/main/java/org/nl/task/controller/TaskController.java create mode 100644 nl-business-task/src/main/java/org/nl/task/entity/Task.java create mode 100644 nl-business-task/src/main/java/org/nl/task/enums/ScheduleTaskStatusEnum.java create mode 100644 nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java create mode 100644 nl-business-task/src/main/java/org/nl/task/enums/TaskStatusEnum.java create mode 100644 nl-business-task/src/main/java/org/nl/task/enums/TaskTypeEnum.java create mode 100644 nl-business-task/src/main/java/org/nl/task/mapper/TaskMapper.java create mode 100644 nl-business-task/src/main/java/org/nl/task/mapper/mapping/TaskMapper.xml create mode 100644 nl-business-task/src/main/java/org/nl/task/param/CancelTaskRequestParam.java create mode 100644 nl-business-task/src/main/java/org/nl/task/param/CreateTaskRequestParam.java create mode 100644 nl-business-task/src/main/java/org/nl/task/param/OneClickOperationRequestParam.java create mode 100644 nl-business-task/src/main/java/org/nl/task/param/PauseAndResumeTaskParam.java create mode 100644 nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java create mode 100644 nl-business-task/src/main/java/org/nl/task/service/TaskService.java create mode 100644 nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java create mode 100644 nl-common/src/main/java/org/nl/config/CorsConfig.java create mode 100644 nl-common/src/main/java/org/nl/enums/ScheduleTaskReportStatusEnum.java create mode 100644 nl-common/src/main/java/org/nl/enums/YesOrNoEnum.java create mode 100644 nl-common/src/main/java/org/nl/exception/ApiError.java create mode 100644 nl-common/src/main/java/org/nl/exception/BadRequestException.java create mode 100644 nl-common/src/main/java/org/nl/exception/GlobalExceptionHandler.java create mode 100644 nl-common/src/main/java/org/nl/logging/annotation/Log.java create mode 100644 nl-common/src/main/java/org/nl/logging/aspect/LogAspect.java create mode 100644 nl-common/src/main/java/org/nl/response/WebResponse.java create mode 100644 nl-common/src/main/java/org/nl/util/IdUtil.java create mode 100644 nl-common/src/main/java/org/nl/util/TaskCodeGeneratorUtil.java create mode 100644 nl-common/src/main/java/org/nl/util/ThrowableUtil.java create mode 100644 nl-common/src/main/java/org/nl/util/WebSocketConfig.java create mode 100644 nl-web-app/src/main/resources/banner.txt create mode 100644 nl-web-app/src/main/resources/config/application-dev.yml create mode 100644 nl-web-app/src/main/resources/config/application-prod.yml create mode 100644 nl-web-app/src/main/resources/config/application.yml create mode 100644 nl-web-app/src/main/resources/language/buss/buss.properties create mode 100644 nl-web-app/src/main/resources/language/buss/buss_en_US.properties create mode 100644 nl-web-app/src/main/resources/language/buss/buss_zh_CN.properties create mode 100644 nl-web-app/src/main/resources/language/error/error.properties create mode 100644 nl-web-app/src/main/resources/language/error/error_en_US.properties create mode 100644 nl-web-app/src/main/resources/language/error/error_zh_CN.properties create mode 100644 nl-web-app/src/main/resources/language/task/task.properties create mode 100644 nl-web-app/src/main/resources/language/task/task_en_US.properties create mode 100644 nl-web-app/src/main/resources/language/task/task_zh_CN.properties create mode 100644 nl-web-app/src/main/resources/logback-spring.xml diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/map/api/ScheduleMapAPI.java b/nl-business-api/src/main/java/org/nl/api/schedule/map/api/ScheduleMapAPI.java new file mode 100644 index 0000000..b0b27ea --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/map/api/ScheduleMapAPI.java @@ -0,0 +1,13 @@ +package org.nl.api.schedule.map.api; + +import cn.hutool.http.HttpResponse; +import org.nl.response.WebResponse; + +/** + * @author dsh + * 2025/12/13 + */ +public interface ScheduleMapAPI { + + HttpResponse queryCurrentMapPointInfo(); +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/setting/api/ScheduleSettingAPI.java b/nl-business-api/src/main/java/org/nl/api/schedule/setting/api/ScheduleSettingAPI.java new file mode 100644 index 0000000..58cb03b --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/setting/api/ScheduleSettingAPI.java @@ -0,0 +1,26 @@ +package org.nl.api.schedule.setting.api; + +import cn.hutool.http.HttpResponse; +import org.nl.api.schedule.setting.core.ScheduleAPISettingChargeParam; +import org.nl.api.schedule.setting.core.ScheduleAPISettingSpeedParam; + +/** + * @author dsh + * 2025/12/8 + */ +public interface ScheduleSettingAPI { + + /** + * 设置配送速度 + * @param scheduleAPISettingSpeedParam + * @return HttpResponse + */ + HttpResponse settingSpeed(ScheduleAPISettingSpeedParam scheduleAPISettingSpeedParam); + + /** + * 充电设置 + * @param scheduleAPISettingChargeParam + * @return HttpResponse + */ + HttpResponse settingCharge(ScheduleAPISettingChargeParam scheduleAPISettingChargeParam); +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingChargeParam.java b/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingChargeParam.java new file mode 100644 index 0000000..9f7078e --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingChargeParam.java @@ -0,0 +1,31 @@ +package org.nl.api.schedule.setting.core; + +import lombok.Data; + +/** + * @author dsh + * 2025/12/8 + */ +@Data +public class ScheduleAPISettingChargeParam { + + /** + * 强制充电阈值,低于该电量完成当前任务后立刻充电 + */ + private Integer forceChargeThreshold; + + /** + * 自由充电阈值,低于该电量空闲时主动充电 + */ + private Integer freeChargeThreshold; + + /** + * 可接任务阈值,充电时电量高于该值即可接单 + */ + private Integer usableForTaskThreshold; + + /** + * 充电上限,电量高于该值后停止充电 + */ + private Integer chargingUpperLimit; +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingSpeedParam.java b/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingSpeedParam.java new file mode 100644 index 0000000..14f2bb1 --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/setting/core/ScheduleAPISettingSpeedParam.java @@ -0,0 +1,18 @@ +package org.nl.api.schedule.setting.core; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/8 + */ +@Data +public class ScheduleAPISettingSpeedParam { + + /** + * 速度,单位m/s + */ + @NotBlank(message = "速度不能为空") + private Integer customSpeed; +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/task/api/ScheduleTaskAPI.java b/nl-business-api/src/main/java/org/nl/api/schedule/task/api/ScheduleTaskAPI.java new file mode 100644 index 0000000..4c1609c --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/task/api/ScheduleTaskAPI.java @@ -0,0 +1,58 @@ +package org.nl.api.schedule.task.api; + + +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONObject; +import org.nl.api.schedule.task.core.ScheduleAPICreateOneClickTaskParam; +import org.nl.api.schedule.task.core.ScheduleAPICreateTaskParam; + +/** + * 调度任务API + * + * @author dsh + * 2025/12/1 + */ +public interface ScheduleTaskAPI { + + /** + * 创建调度任务 + * @param scheduleAPICreateTaskParam + * @return + */ + HttpResponse createTask(ScheduleAPICreateTaskParam scheduleAPICreateTaskParam); + + /** + * 取消调度任务 + * @param taskId + * @return + */ + HttpResponse cancelTask(String taskId); + + /** + * 根据任务号获取任务信息 + * @param taskId + * @return + */ + HttpResponse queryTaskStatusByTaskId(String taskId); + + /** + * 暂停调度任务 + * @param taskId + * @return + */ + HttpResponse pauseTask(String taskId); + + /** + * 恢复调度任务 + * @param taskId + * @return + */ + HttpResponse resumeTask(String taskId); + + /** + * 生成一键任务 + * @param scheduleAPICreateOneClickTaskParam + * @return + */ + HttpResponse oneClickOperationTask(ScheduleAPICreateOneClickTaskParam scheduleAPICreateOneClickTaskParam); +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateOneClickTaskParam.java b/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateOneClickTaskParam.java new file mode 100644 index 0000000..c582dc9 --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateOneClickTaskParam.java @@ -0,0 +1,30 @@ +package org.nl.api.schedule.task.core; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/13 + */ +@Data +public class ScheduleAPICreateOneClickTaskParam { + + /** + * 任务号 + */ + @NotBlank(message = "调度任务号不能为空") + private String task_code; + + /** + * 一键任务类型 + */ + @NotBlank(message = "调度一键任务类型不能为空") + private String type; + + /** + * 车号 + */ + @NotBlank(message = "车号不能为空") + private String vehicle_number; +} diff --git a/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateTaskParam.java b/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateTaskParam.java new file mode 100644 index 0000000..f8eeb6a --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/schedule/task/core/ScheduleAPICreateTaskParam.java @@ -0,0 +1,36 @@ +package org.nl.api.schedule.task.core; + +import lombok.Data; + +/** + * @author dsh + * 2025/12/2 + */ +@Data +public class ScheduleAPICreateTaskParam { + + /** + * 任务号 + */ + private String task_code; + + /** + * 目标点 + */ + private String destinations; + + /** + * 任务类型 + */ + private String type; + + /** + * 任务优先级 (1-10数字越低优先级越高) + */ + private String priority; + + /** + * 指定车号 + */ + private String vehicle_number; +} diff --git a/nl-business-api/src/main/java/org/nl/api/setting/api/SettingAPI.java b/nl-business-api/src/main/java/org/nl/api/setting/api/SettingAPI.java new file mode 100644 index 0000000..d53b07d --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/setting/api/SettingAPI.java @@ -0,0 +1,16 @@ +package org.nl.api.setting.api; + +import com.alibaba.fastjson.JSONObject; + +/** + * @author dsh + * 2025/12/13 + */ +public interface SettingAPI { + + /** + * 根据设置编号查询设置参数是否启用 + * @return + */ + JSONObject querySttingParamIsActiveByCode(String setting_code); +} diff --git a/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java b/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java new file mode 100644 index 0000000..67e8792 --- /dev/null +++ b/nl-business-api/src/main/java/org/nl/api/task/api/TaskAPI.java @@ -0,0 +1,31 @@ +package org.nl.api.task.api; + +/** + * @author dsh + * 2025/12/11 + */ +public interface TaskAPI { + + /** + * 根据车号获取当前车俩正在执行的任务 + * @param vehicleNumber + * @return + */ + Object queryCurrentTaskByVehicleNumber(String vehicleNumber); + + /** + * 根据任务号修改任务上报状态和等待时间 + * @param taskCode + * @param newReportStatus + * @return + */ + boolean updateTaskReportStatusByCode(String taskCode,String newReportStatus,String waiting_time); + + /** + * 查询当前任务上报状态阶段 + * @param taskCode + * @param vehicleNumber + * @return + */ + String taskOperationConfirm(String taskCode,String vehicleNumber); +} diff --git a/nl-business-monitor/src/main/java/org/nl/monitor/map/controller/MapMonitorController.java b/nl-business-monitor/src/main/java/org/nl/monitor/map/controller/MapMonitorController.java new file mode 100644 index 0000000..9eade48 --- /dev/null +++ b/nl-business-monitor/src/main/java/org/nl/monitor/map/controller/MapMonitorController.java @@ -0,0 +1,26 @@ +package org.nl.monitor.map.controller; + +import jakarta.annotation.Resource; +import org.nl.monitor.map.service.MapMonitorService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author dsh + * 2025/12/13 + */ +@RestController +@RequestMapping("/mapMonitor") +public class MapMonitorController { + + @Resource + private MapMonitorService mapMonitorService; + + @GetMapping("/queryCurrentMapPoint") + public ResponseEntity queryCurrentMapPoint() { + return new ResponseEntity<>(mapMonitorService.queryCurrentMapPoint(), HttpStatus.OK); + } +} diff --git a/nl-business-monitor/src/main/java/org/nl/monitor/map/dto/StationInfoDto.java b/nl-business-monitor/src/main/java/org/nl/monitor/map/dto/StationInfoDto.java new file mode 100644 index 0000000..7acccc1 --- /dev/null +++ b/nl-business-monitor/src/main/java/org/nl/monitor/map/dto/StationInfoDto.java @@ -0,0 +1,47 @@ +package org.nl.monitor.map.dto; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +/** + * @author dsh + * 2025/12/13 + */ +@Data +public class StationInfoDto { + + /** + * 点位唯一标识 + */ + private String id; + + /** + * 点位名称 + */ + private String name; + + /** + * 点位类型 + */ + private String type; + + /** + * x坐标 + */ + private double x; + + /** + * Y坐标 + */ + private double y; + + /** + * 偏航角 + */ + private double yaw; + + /** + * 元数据 + */ + private JSONObject metadata; +} diff --git a/nl-business-monitor/src/main/java/org/nl/monitor/map/service/MapMonitorService.java b/nl-business-monitor/src/main/java/org/nl/monitor/map/service/MapMonitorService.java new file mode 100644 index 0000000..7675d46 --- /dev/null +++ b/nl-business-monitor/src/main/java/org/nl/monitor/map/service/MapMonitorService.java @@ -0,0 +1,12 @@ +package org.nl.monitor.map.service; + +import org.nl.response.WebResponse; + +/** + * @author dsh + * 2025/12/13 + */ +public interface MapMonitorService { + + WebResponse queryCurrentMapPoint(); +} diff --git a/nl-business-monitor/src/main/java/org/nl/monitor/map/service/impl/MapMonitorServiceImpl.java b/nl-business-monitor/src/main/java/org/nl/monitor/map/service/impl/MapMonitorServiceImpl.java new file mode 100644 index 0000000..9831264 --- /dev/null +++ b/nl-business-monitor/src/main/java/org/nl/monitor/map/service/impl/MapMonitorServiceImpl.java @@ -0,0 +1,53 @@ +package org.nl.monitor.map.service.impl; + +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.map.api.ScheduleMapAPI; +import org.nl.exception.BadRequestException; +import org.nl.monitor.map.dto.StationInfoDto; +import org.nl.monitor.map.service.MapMonitorService; +import org.nl.response.WebResponse; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author dsh + * 2025/12/13 + */ +@Slf4j +@Service +public class MapMonitorServiceImpl implements MapMonitorService { + + @Resource + private ScheduleMapAPI scheduleMapAPI; + + @Override + public WebResponse queryCurrentMapPoint() { + HttpResponse httpResponse = scheduleMapAPI.queryCurrentMapPointInfo(); + if (httpResponse == null || !httpResponse.isOk()){ + throw new BadRequestException("获取调度当前地图点位信息失败"); + } + List result = new ArrayList<>(); + JSONArray jsonArray = JSONArray.parseArray(httpResponse.body()); + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject jsonObject = jsonArray.getJSONObject(i); + StationInfoDto stationInfoDto =new StationInfoDto(); + stationInfoDto.setId(jsonObject.getString("id")); + stationInfoDto.setName(String.valueOf(i+1)); + stationInfoDto.setType("1"); + JSONObject poseJson = jsonObject.getJSONObject("pose"); + stationInfoDto.setX(poseJson.getDouble("x")); + stationInfoDto.setY(poseJson.getDouble("y")); + stationInfoDto.setYaw(poseJson.getDouble("yaw")); + JSONObject metaDataJson = jsonObject.getJSONObject("metadata"); + stationInfoDto.setMetadata(metaDataJson); + result.add(stationInfoDto); + } + return WebResponse.requestParamOk(result); + } +} diff --git a/nl-business-schedule/pom.xml b/nl-business-schedule/pom.xml index 3be81d9..38fddc8 100644 --- a/nl-business-schedule/pom.xml +++ b/nl-business-schedule/pom.xml @@ -27,6 +27,27 @@ org.nl nl-business-api + + + cn.hutool + hutool-all + + + + com.alibaba + fastjson + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-websocket + + diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/core/util/ScheduleUtil.java b/nl-business-schedule/src/main/java/org/nl/schedule/core/util/ScheduleUtil.java new file mode 100644 index 0000000..e67c1de --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/core/util/ScheduleUtil.java @@ -0,0 +1,31 @@ +package org.nl.schedule.core.util; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * @author dsh + * 2025/12/2 + */ +public class ScheduleUtil { + + /** + * 获得之后num个天的时间 + * + * @param num + * @return + */ + public static String getNextDay(int num) { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, num); + Date date = calendar.getTime(); + TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + df.setTimeZone(tz); + String nowAsISO = df.format(date); + return nowAsISO; + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/core/websocket/WebSocketVehicleInfoServer.java b/nl-business-schedule/src/main/java/org/nl/schedule/core/websocket/WebSocketVehicleInfoServer.java new file mode 100644 index 0000000..6dcc94b --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/core/websocket/WebSocketVehicleInfoServer.java @@ -0,0 +1,153 @@ +package org.nl.schedule.core.websocket; + +import cn.hutool.core.map.MapUtil; +import com.alibaba.fastjson.JSON; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import lombok.Data; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * @author dsh + * 2025/11/26 + */ +@Slf4j +@Getter +@Component +@ServerEndpoint("/WebSocket/VehicleInfo/{sid}") +public class WebSocketVehicleInfoServer { + + /** + * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 + */ + private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>(); + + /** + * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 + */ + private static int onlineCount = 0; + + + /** + * 与某个客户端的连接会话,需要通过它来给客户端发送数据 + */ + private Session session; + /** + * 接收userId + */ + private String sid = ""; + + /** + * 默认语言 + */ + private String lang = "zh"; + + /** + * 连接建立成功调用的方法 + */ + @OnOpen + public void onOpen(Session session, @PathParam("sid") String sid) { + this.session = session; + + // 获取查询参数中的语言设置 + String queryString = session.getRequestURI().getQuery(); + if (queryString != null) { + String[] params = queryString.split("&"); + for (String param : params) { + if (param.startsWith("lang=")) { + // 获取lang参数值 + this.lang = param.substring(5); + break; + } + } + } + + //如果存在就先删除一个,防止重复推送消息 + webSocketSet.removeIf(webSocket -> webSocket.sid.equals(sid)); + webSocketSet.add(this); + //在线数加1 + addOnlineCount(); + log.info("VehicleWS:sid{}连接成功,当前在线人数为{}", sid, getOnlineCount()); + this.sid = sid; + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose() { + webSocketSet.remove(this); + //在线数减1 + subOnlineCount(); + log.info("VehicleWS:sid{}关闭连接!当前在线人数为{}", sid, getOnlineCount()); + } + + /** + * 收到客户端消息后调用的方法 + * + * @param message 客户端发送过来的消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + //System.out.println(webSocketSet.size() + "_接收到消息_" + session.getId()); + } + + @OnError + public void onError(Session session, Throwable error) { + //log.error("发生错误"); + webSocketSet.remove(session); + error.printStackTrace(); + } + + public Session getSession() { + return session; + } + + // 获取语言的方法 + public String getLang() { + return lang; + } + + // 推送方法 + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + + public void sendDataToClient(Map data) { + try { + if (this.session != null&& MapUtil.isNotEmpty(data)) { + this.session.getBasicRemote().sendText(JSON.toJSONString(data)); + } + } catch (IOException e) { + log.error("发送消息给客户端失败", e); + } + } + public static synchronized int getOnlineCount() { + return onlineCount; + } + + public static CopyOnWriteArraySet getWebSocketSet() { + return webSocketSet; + } + + + public void setSession(Session session) { + this.session = session; + } + + public static synchronized void addOnlineCount() { + WebSocketVehicleInfoServer.onlineCount++; + } + + public static synchronized void subOnlineCount() { + WebSocketVehicleInfoServer.onlineCount--; + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/map/provider/ScheduleMapAPIProvider.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/map/provider/ScheduleMapAPIProvider.java new file mode 100644 index 0000000..69faa20 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/map/provider/ScheduleMapAPIProvider.java @@ -0,0 +1,33 @@ +package org.nl.schedule.modular.map.provider; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.map.api.ScheduleMapAPI; +import org.nl.exception.BadRequestException; +import org.springframework.stereotype.Service; + +/** + * @author dsh + * 2025/12/13 + */ +@Slf4j +@Service +public class ScheduleMapAPIProvider implements ScheduleMapAPI { + + @Override + public HttpResponse queryCurrentMapPointInfo() { + log.info("获取当前地图中的所有POI"); + HttpResponse result = null; + try { + result = HttpRequest.get("http://127.0.0.1:8011/api/core/artifact/v1/pois") + .execute(); + log.info("获取当前地图中的所有POI响应结果:{}",result.body()); + }catch (Exception e){ + log.info("获取当前地图中的所有POI失败"); + } + return result; + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/setting/provider/ScheduleSettingAPIProvider.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/setting/provider/ScheduleSettingAPIProvider.java new file mode 100644 index 0000000..3bf5187 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/setting/provider/ScheduleSettingAPIProvider.java @@ -0,0 +1,57 @@ +package org.nl.schedule.modular.setting.provider; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.setting.api.ScheduleSettingAPI; +import org.nl.api.schedule.setting.core.ScheduleAPISettingChargeParam; +import org.nl.api.schedule.setting.core.ScheduleAPISettingSpeedParam; +import org.nl.exception.BadRequestException; +import org.springframework.stereotype.Service; + +/** + * @author dsh + * 2025/12/8 + */ +@Slf4j +@Service +public class ScheduleSettingAPIProvider implements ScheduleSettingAPI { + + @Override + public HttpResponse settingSpeed(ScheduleAPISettingSpeedParam scheduleAPISettingSpeedParam) { + if (ObjectUtil.isEmpty(scheduleAPISettingSpeedParam)){ + throw new BadRequestException("调度设置配送速度参数不能为空"); + } + log.info("设置调度配送速度参数:{}", scheduleAPISettingSpeedParam); + HttpResponse result = null; + try { + result = HttpRequest.put("http://127.0.0.1:8011/system/motion/speed") + .body(String.valueOf(JSONObject.toJSON(scheduleAPISettingSpeedParam))) + .execute(); + log.info("设置调度配送速度响应结果:{}",result.body()); + }catch (Exception e){ + log.info("调度设置配送速度失败"); + } + return result; + } + + @Override + public HttpResponse settingCharge(ScheduleAPISettingChargeParam scheduleAPISettingChargeParam) { + if (ObjectUtil.isEmpty(scheduleAPISettingChargeParam)){ + throw new BadRequestException("调度设置充电参数不能为空"); + } + log.info("设置调度充电参数:{}", scheduleAPISettingChargeParam); + HttpResponse result = null; + try { + result = HttpRequest.put("http://127.0.0.1:8011/system/charging/auto-threshold") + .body(String.valueOf(JSONObject.toJSON(scheduleAPISettingChargeParam))) + .execute(); + log.info("设置调度充电响应结果:{}",result.body()); + }catch (Exception e){ + log.info("设置调度充电参数失败"); + } + return result; + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/controller/ScheduleTaskRequestReportController.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/controller/ScheduleTaskRequestReportController.java new file mode 100644 index 0000000..00ed01e --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/controller/ScheduleTaskRequestReportController.java @@ -0,0 +1,28 @@ +package org.nl.schedule.modular.task.controller; + +import jakarta.annotation.Resource; +import org.nl.schedule.modular.task.param.ScheduleTaskArrivedReportParam; +import org.nl.schedule.modular.task.service.ScheduleTaskService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author dsh + * 2025/12/8 + */ +@RestController +@RequestMapping("/api/scheduleTask") +public class ScheduleTaskRequestReportController { + + @Resource + private ScheduleTaskService scheduleTaskService; + + @PostMapping("/arrivedReport") + public ResponseEntity arrivedReport(@RequestBody ScheduleTaskArrivedReportParam scheduleTaskArrivedReportParam){ + return new ResponseEntity<>(scheduleTaskService.taskArrivedReport(scheduleTaskArrivedReportParam), HttpStatus.OK); + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/param/ScheduleTaskArrivedReportParam.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/param/ScheduleTaskArrivedReportParam.java new file mode 100644 index 0000000..2cdac80 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/param/ScheduleTaskArrivedReportParam.java @@ -0,0 +1,30 @@ +package org.nl.schedule.modular.task.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/11 + */ +@Data +public class ScheduleTaskArrivedReportParam { + + /** + * 点位 + */ + @NotBlank(message = "点位不能为空") + private String location; + + /** + * 车号 + */ + @NotBlank(message = "车号不能为空") + private String vehicle_number; + + /** + * 任务号 + */ + @NotBlank(message = "任务号不能为空") + private String task_code; +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/provider/ScheduleTaskAPIProvider.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/provider/ScheduleTaskAPIProvider.java new file mode 100644 index 0000000..a5b5df3 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/provider/ScheduleTaskAPIProvider.java @@ -0,0 +1,182 @@ +package org.nl.schedule.modular.task.provider; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.task.api.ScheduleTaskAPI; +import org.nl.api.schedule.task.core.ScheduleAPICreateOneClickTaskParam; +import org.nl.api.schedule.task.core.ScheduleAPICreateTaskParam; +import org.nl.exception.BadRequestException; +import org.nl.schedule.core.util.ScheduleUtil; +import org.springframework.stereotype.Service; + +/** + * @author dsh + * 2025/12/1 + */ +@Slf4j +@Service +public class ScheduleTaskAPIProvider implements ScheduleTaskAPI { + + @Override + public HttpResponse createTask(ScheduleAPICreateTaskParam scheduleAPICreateTaskParam) { + String task_code = scheduleAPICreateTaskParam.getTask_code(); + String destinations = scheduleAPICreateTaskParam.getDestinations(); + String type = scheduleAPICreateTaskParam.getType(); + if (StrUtil.isBlank(task_code)){ + throw new BadRequestException("任务号不能为空"); + } + if (StrUtil.isBlank(destinations)){ + throw new BadRequestException("目标点不能为空"); + } + if (StrUtil.isBlank(type)){ + throw new BadRequestException("任务操作类型不能为空"); + } + + JSONObject request_body = new JSONObject(); + request_body.put("deadline", ScheduleUtil.getNextDay(1)); + if (StrUtil.isNotBlank(scheduleAPICreateTaskParam.getVehicle_number())){ + request_body.put("intendedVehicle", scheduleAPICreateTaskParam.getVehicle_number()); + } + JSONArray body_destinations = new JSONArray(); + JSONObject body_destination = new JSONObject(); + body_destination.put("locationName", destinations); + body_destination.put("operation", type); + body_destinations.add(body_destination); + request_body.put("destinations", body_destinations); + if (StrUtil.isNotBlank(scheduleAPICreateTaskParam.getPriority())){ + request_body.put("priority", Integer.parseInt(scheduleAPICreateTaskParam.getPriority())); + } + + log.info("下发调度任务参数:{}", request_body); + HttpResponse result = null; + try { + result = HttpRequest + .post("http://127.0.0.1:8011/tasks/"+scheduleAPICreateTaskParam.getTask_code()) + .body(String.valueOf(request_body)) + .execute(); + + log.info("下发调度任务响应结果:{}",result.body()); + }catch (Exception e){ + log.error("下发调度任务失败:{}",e.getMessage()); + } + return result; + } + + @Override + public HttpResponse cancelTask(String taskId) { + if (StrUtil.isBlank(taskId)){ + throw new BadRequestException("任务号不能为空"); + } + log.info("取消调度任务参数:{}", taskId); + HttpResponse result = null; + try { + result = HttpRequest + .post("http://127.0.0.1:8011/tasks/"+taskId+"/withdrawl") + .body(String.valueOf(new JSONObject())) + .execute(); + + log.info("取消调度任务响应结果:{}",result.body()); + }catch (Exception e){ + log.error("取消调度任务失败:{}",e.getMessage()); + } + return result; + } + + @Override + public HttpResponse queryTaskStatusByTaskId(String taskId) { + if (StrUtil.isBlank(taskId)){ + throw new BadRequestException("任务号不能为空"); + } + log.info("查询调度任务状态参数:{}", taskId); + HttpResponse result = null; + try { + result = HttpRequest + .get("http://127.0.0.1:8011/tasks/"+taskId) + .execute(); + + log.info("查询调度任务状态响应结果:{}",result.body()); + }catch (Exception e){ + log.error("查询调度任务状态失败:{}",e.getMessage()); + } + return result; + } + + @Override + public HttpResponse pauseTask(String taskId) { + if (StrUtil.isBlank(taskId)){ + throw new BadRequestException("任务号不能为空"); + } + log.info("暂停调度任务参数:{}", taskId); + HttpResponse result = null; + try { + result = HttpRequest + .post("http://127.0.0.1:8011/tasks/"+taskId+"/pause") + .body(String.valueOf(new JSONObject())) + .execute(); + + log.info("暂停调度任务响应结果:{}",result.body()); + }catch (Exception e){ + log.error("暂停调度任务失败:{}",e.getMessage()); + } + return result; + } + + @Override + public HttpResponse resumeTask(String taskId) { + if (StrUtil.isBlank(taskId)){ + throw new BadRequestException("任务号不能为空"); + } + log.info("恢复调度任务参数:{}", taskId); + HttpResponse result = null; + try { + result = HttpRequest + .post("http://127.0.0.1:8011/tasks/"+taskId+"/resume") + .body(String.valueOf(new JSONObject())) + .execute(); + + log.info("恢复调度任务响应结果:{}",result.body()); + }catch (Exception e){ + log.error("恢复调度任务失败:{}",e.getMessage()); + } + return result; + } + + @Override + public HttpResponse oneClickOperationTask(ScheduleAPICreateOneClickTaskParam scheduleAPICreateOneClickTaskParam) { + String task_code = scheduleAPICreateOneClickTaskParam.getTask_code(); + String type = scheduleAPICreateOneClickTaskParam.getType(); + String vehicleNumber = scheduleAPICreateOneClickTaskParam.getVehicle_number(); + if (StrUtil.isBlank(task_code)){ + throw new BadRequestException("任务号不能为空"); + } + if (StrUtil.isBlank(type)){ + throw new BadRequestException("任务操作类型不能为空"); + } + if (StrUtil.isBlank(vehicleNumber)){ + throw new BadRequestException("车号不能为空"); + } + + JSONObject request_body = new JSONObject(); + request_body.put("vehicleNumber", vehicleNumber); + request_body.put("taskId",task_code); + request_body.put("taskType",type); + + log.info("下发调度一键任务参数:{}", request_body); + HttpResponse result = null; + try { + result = HttpRequest + .post("http://127.0.0.1:8011/tasks/quick-create") + .body(String.valueOf(request_body)) + .execute(); + + log.info("下发调度一键任务响应结果:{}",result.body()); + }catch (Exception e){ + log.error("下发调度一键任务失败:{}",e.getMessage()); + } + return result; + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/ScheduleTaskService.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/ScheduleTaskService.java new file mode 100644 index 0000000..5b50b75 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/ScheduleTaskService.java @@ -0,0 +1,13 @@ +package org.nl.schedule.modular.task.service; + +import org.nl.response.WebResponse; +import org.nl.schedule.modular.task.param.ScheduleTaskArrivedReportParam; + +/** + * @author dsh + * 2025/12/2 + */ +public interface ScheduleTaskService { + + WebResponse taskArrivedReport(ScheduleTaskArrivedReportParam scheduleTaskArrivedReportParam); +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/impl/ScheduleTaskServiceImpl.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/impl/ScheduleTaskServiceImpl.java new file mode 100644 index 0000000..e488b97 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/task/service/impl/ScheduleTaskServiceImpl.java @@ -0,0 +1,88 @@ +package org.nl.schedule.modular.task.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.setting.api.SettingAPI; +import org.nl.api.task.api.TaskAPI; +import org.nl.enums.YesOrNoEnum; +import org.nl.exception.BadRequestException; +import org.nl.response.WebResponse; +import org.nl.enums.ScheduleTaskReportStatusEnum; +import org.nl.schedule.modular.task.param.ScheduleTaskArrivedReportParam; +import org.nl.schedule.modular.task.service.ScheduleTaskService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author dsh + * 2025/12/2 + */ +@Slf4j +@Service +public class ScheduleTaskServiceImpl implements ScheduleTaskService { + + @Resource + private TaskAPI taskAPI; + + @Resource + private SettingAPI settingAPI; + + @Override + public WebResponse taskArrivedReport(ScheduleTaskArrivedReportParam scheduleTaskArrivedReportParam) { + String location = scheduleTaskArrivedReportParam.getLocation(); + String vehicle_number = scheduleTaskArrivedReportParam.getVehicle_number(); + String task_code = scheduleTaskArrivedReportParam.getTask_code(); + if (StrUtil.isBlank(location)) { + throw new BadRequestException("上报点位不能为空"); + } + if (StrUtil.isBlank(vehicle_number)) { + throw new BadRequestException("上报车号不能为空"); + } + if (StrUtil.isBlank(task_code)) { + throw new BadRequestException("上报任务号不能为空"); + } + log.info("调度上报到达,参数:{}",scheduleTaskArrivedReportParam); + String status = taskAPI.taskOperationConfirm(task_code,vehicle_number); + if (StrUtil.isBlank(status)){ + throw new BadRequestException("未找到该上报阶段"); + } + ScheduleTaskReportStatusEnum scheduleTaskReportStatusEnum = ScheduleTaskReportStatusEnum.getByCode(status); + if (scheduleTaskReportStatusEnum == null) { + throw new BadRequestException("未找到该上报类型"); + } + + boolean flag = false; + // 到达时等待设置参数 + JSONObject jsonObject = settingAPI.querySttingParamIsActiveByCode("call_arrival_waiting_time").getJSONObject("data"); + String is_active = jsonObject.getString("is_active"); + String arrive_waiting_time = jsonObject.getString("value"); + if (StrUtil.isNotBlank(is_active) && YesOrNoEnum.YES.getCode().equals(is_active)){ + switch (scheduleTaskReportStatusEnum){ + case NOT_REPORTED: + boolean result = taskAPI.updateTaskReportStatusByCode(task_code, ScheduleTaskReportStatusEnum.REPORTED.getCode(),arrive_waiting_time); + if (!result) { + log.info("更新调度上报状态失败"); + } + break; + case REPORTED: + log.info("已接收上报,但未确认操作"); + break; + case FINISH_REPORTED: + flag = true; + log.info("确认操作"); + break; + } + }else { + // 如果没有启用 到达时等待,则直接反馈调度成功。 + flag = true; + } + + if (flag) { + return WebResponse.requestOk(); + } + + throw new BadRequestException("未确认操作"); + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java new file mode 100644 index 0000000..5c4d2ba --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/controller/VehicleController.java @@ -0,0 +1,32 @@ +package org.nl.schedule.modular.vehicle.controller; + +import jakarta.validation.constraints.NotBlank; +import org.nl.schedule.modular.vehicle.service.VehicleService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author dsh + * 2025/11/25 + */ +@RestController +@RequestMapping("/schedule/vehicle") +@Validated +public class VehicleController { + + private final VehicleService vehicleService; + + public VehicleController(VehicleService vehicleService) { + this.vehicleService = vehicleService; + } + + @GetMapping("/getVehicleInfoByNumber/{vehicleNumber}") + public ResponseEntity getVehicleInfoByNumber(@PathVariable @NotBlank String vehicleNumber) { + return new ResponseEntity<>(vehicleService.getVehicleInfoByNumber(vehicleNumber), HttpStatus.OK); + } +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/dto/VehicleInfoDto.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/dto/VehicleInfoDto.java new file mode 100644 index 0000000..fbc90fb --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/dto/VehicleInfoDto.java @@ -0,0 +1,70 @@ +package org.nl.schedule.modular.vehicle.dto; + +import lombok.Data; +import org.nl.schedule.modular.vehicle.entity.Location; + +import java.io.Serializable; +import java.util.List; + +/** + * @author dsh + * 2025/11/25 + */ +@Data +public class VehicleInfoDto{ + + /** + * 车辆ID + */ + private String vehicleId; + + /** + * 车辆编号 + */ + private String vehicleNumber; + + /** + * 车辆IP + */ + private String ip; + + /** + * 电量 + */ + private int batteryLevel; + + /** + * 冰容量 + */ + private int iceCapacity; + + /** + * 水容量 + */ + private int waterCapacity; + + /** + * 信号类型 + */ + private String signalType; + + /** + * 信号强度 + */ + private int signalStrength; + + /** + * 异常信息集合 + */ + private List exceptions; + + /** + * 当前位置 + */ + private Location currentLocation; + + /** + * 最后更新时间 + */ + private String lastUpdated; +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/entity/Location.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/entity/Location.java new file mode 100644 index 0000000..b7121f9 --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/entity/Location.java @@ -0,0 +1,21 @@ +package org.nl.schedule.modular.vehicle.entity; + +import lombok.Data; + +/** + * @author dsh + * 2025/11/25 + */ +@Data +public class Location { + + /** + * 楼层 + */ + private String floor; + + /** + * 房间 + */ + private String room; +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java new file mode 100644 index 0000000..3b7521e --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/VehicleService.java @@ -0,0 +1,24 @@ +package org.nl.schedule.modular.vehicle.service; + +import org.nl.response.WebResponse; +import org.nl.schedule.modular.vehicle.dto.VehicleInfoDto; + +import java.util.List; + +/** + * @author dsh + * 2025/11/25 + */ +public interface VehicleService { + + List getAllVehicles(); + + /** + * 根据车号获取车辆信息 + * @param vehicleNumber + * @return VehicleInfoDto + */ + VehicleInfoDto getVehicleInfoByNumber(String vehicleNumber); + + +} diff --git a/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java new file mode 100644 index 0000000..8005b1f --- /dev/null +++ b/nl-business-schedule/src/main/java/org/nl/schedule/modular/vehicle/service/impl/VehicleServiceImpl.java @@ -0,0 +1,103 @@ +package org.nl.schedule.modular.vehicle.service.impl; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.task.api.TaskAPI; +import org.nl.response.WebResponse; +import org.nl.schedule.core.websocket.WebSocketVehicleInfoServer; +import org.nl.schedule.modular.vehicle.dto.VehicleInfoDto; +import org.nl.schedule.modular.vehicle.service.VehicleService; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; + +/** + * @author dsh + * 2025/11/25 + */ +@Slf4j +@Service +public class VehicleServiceImpl implements VehicleService { + + private final ConcurrentHashMap vehicleCache = new ConcurrentHashMap<>(); + + @Resource + private TaskAPI taskAPI; + + /** + * 定时更新车辆信息(每秒执行) + */ + @Scheduled(fixedRate = 1000) // 每秒执行一次 + public void updateVehicleInfo() { + try { + List vehicles = getAllVehicles(); + + if (ObjectUtil.isNotEmpty(vehicles)) { + // 清空旧数据 + vehicleCache.clear(); + + // 更新缓存 + for (VehicleInfoDto vehicle : vehicles) { + vehicleCache.put(vehicle.getVehicleNumber(), vehicle); + } + + log.debug("成功更新 {} 辆车辆信息", vehicles.size()); + } + } catch (Exception e) { + log.error("更新车辆信息失败: {}", e.getMessage()); + } + } + + @Scheduled(fixedRate = 1000) + public void pushVehicleInfo(){ + CopyOnWriteArraySet webSocketSet = + WebSocketVehicleInfoServer.getWebSocketSet(); + if (webSocketSet.size() > 0) { + webSocketSet.forEach(c -> { + Map vehicleInfoMap = new HashMap<>(); + vehicleInfoMap.put("vehicleInfo", getVehicleInfoByNumber(c.getSid())); + vehicleInfoMap.put("currentTask", taskAPI.queryCurrentTaskByVehicleNumber(c.getSid())); + c.sendDataToClient(vehicleInfoMap); + }); + } + } + + @Override + public List getAllVehicles() { + String url = "http://127.0.0.1:8011/schedule/vehicles"; + List vehicles = new ArrayList<>(); + try { + try (HttpResponse response = HttpRequest.get("http://127.0.0.1:8011/schedule/vehicles") + .setConnectionTimeout(10000) + .setReadTimeout(10000) + .execute()) { + if (response.isOk() && response.body() != null) { + // 获取响应体内容 + String body = response.body(); + vehicles = JSON.parseArray(body, VehicleInfoDto.class); + log.info(vehicles.toString()); + } + } + }catch (Exception e) { + log.error("获取调度车辆信息失败:{}",e.getMessage()); + } + return vehicles; + } + + @Override + public VehicleInfoDto getVehicleInfoByNumber(String vehicleNumber) { + // 直接从缓存中获取 + return vehicleCache.get(vehicleNumber); + } +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/controller/SettingController.java b/nl-business-setting/src/main/java/org/nl/setting/modular/controller/SettingController.java new file mode 100644 index 0000000..6cad84a --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/controller/SettingController.java @@ -0,0 +1,36 @@ +package org.nl.setting.modular.controller; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.logging.annotation.Log; +import org.nl.setting.modular.param.UpdateSettingParam; +import org.nl.setting.modular.service.SettingService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author dsh + * 2025/12/6 + */ +@Slf4j +@RestController +@RequestMapping("/setting") +public class SettingController { + + @Resource + private SettingService settingService; + + @Log("查询所有设置参数") + @GetMapping("/queryAllSettingParam") + public ResponseEntity queryAllSettingParam(){ + return new ResponseEntity<>(settingService.queryAllSettingParam(), HttpStatus.OK); + } + + @Log("根据设置编号设置参数") + @PostMapping("/updateSettingParamByCode") + public ResponseEntity updateSettingParamByCode(@RequestBody @Validated UpdateSettingParam updateSettingParam){ + return new ResponseEntity<>(settingService.updateSettingParamByCode(updateSettingParam), HttpStatus.OK); + } +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/controller/TestController.java b/nl-business-setting/src/main/java/org/nl/setting/modular/controller/TestController.java deleted file mode 100644 index 7390d47..0000000 --- a/nl-business-setting/src/main/java/org/nl/setting/modular/controller/TestController.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.nl.setting.modular.controller; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @Author: lyd - * @Date: 2025/11/21 - */ - -@RequestMapping("/api") -@RestController -public class TestController { - - @GetMapping("/") - public ResponseEntity PressedMonitor() { - return new ResponseEntity<>("aaa", HttpStatus.OK); - } -} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/entity/Setting.java b/nl-business-setting/src/main/java/org/nl/setting/modular/entity/Setting.java new file mode 100644 index 0000000..a438f38 --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/entity/Setting.java @@ -0,0 +1,65 @@ +package org.nl.setting.modular.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author dsh + * 2025/12/6 + */ +@Data +@TableName("setting_param") +public class Setting { + + /** + * 设置标识 + */ + @TableId(value = "id") + private String id; + + /** + * 设置类型 + */ + private String setting_type; + + /** + * 设置编码 + */ + private String setting_code; + + /** + * 设置名称 + */ + private String label; + + /** + * 设置值 + */ + private String value; + + /** + * 是否启用 + */ + private String is_active; + + /** + * 创建者 + */ + private String create_by; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改者 + */ + private String update_by; + + /** + * 修改时间 + */ + private String update_time; +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/enums/SettingCodeEnum.java b/nl-business-setting/src/main/java/org/nl/setting/modular/enums/SettingCodeEnum.java new file mode 100644 index 0000000..679b09b --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/enums/SettingCodeEnum.java @@ -0,0 +1,61 @@ +package org.nl.setting.modular.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/12/8 + */ +@Getter +public enum SettingCodeEnum { + + /** + * 调度IP + */ + SCHEDULE_IP("0", "schedule_ip", "调度IP"), + /** + * 配送速度 + */ + DELIVERY_SPEED("1", "delivery_speed", "配送速度"), + /** + * 远程呼叫 + */ + FAR_CALL("2", "far_call", "远程呼叫"), + + /** + * 呼叫到达等待时间 + */ + CALL_ARRIVAL_WAITING_TIME("3", "call_arrival_waiting_time", "呼叫到达等待时间"), + /** + * 呼叫时等待时间 + */ + WAITING_TIME_WHEN_MAKING_A_CALL("4", "waiting_time_when_making_a_call", "呼叫时等待时间"), + /** + * 自动回充 + */ + AUTOMATIC_RECHARGE("5", "automatic_recharge", "自动回充"), + /** + * 充电时是否可呼叫 + */ + CAN_IT_BE_CALLED_WHILE_CHARGING("6", "can_it_be_called_while_charging", "充电时是否可呼叫"); + + private String code; + private String name; + private String desc; + + + SettingCodeEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } + + public static SettingCodeEnum getByCode(String code) { + for (SettingCodeEnum e : SettingCodeEnum.values()) { + if (e.name.equals(code)) { + return e; + } + } + return null; + } +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/SettingMapper.java b/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/SettingMapper.java new file mode 100644 index 0000000..6a41922 --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/SettingMapper.java @@ -0,0 +1,14 @@ +package org.nl.setting.modular.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.nl.setting.modular.entity.Setting; + +/** + * @author dsh + * 2025/12/6 + */ +@Mapper +public interface SettingMapper extends BaseMapper { + +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/mapping/SettingMapping.xml b/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/mapping/SettingMapping.xml new file mode 100644 index 0000000..dece03c --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/mapper/mapping/SettingMapping.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/param/UpdateSettingParam.java b/nl-business-setting/src/main/java/org/nl/setting/modular/param/UpdateSettingParam.java new file mode 100644 index 0000000..5a7d8c5 --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/param/UpdateSettingParam.java @@ -0,0 +1,33 @@ +package org.nl.setting.modular.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/6 + */ +@Data +public class UpdateSettingParam { + + /** + * 设置编码 + */ + @NotBlank(message = "设置编码不能为空") + private String setting_code; + + /** + * 设置值 + */ + private String value; + + /** + * 是否开启 0关 1开 + */ + private String is_active; + + /** + * 修改者 (屏幕就传车号,外部就传用户) + */ + private String update_by; +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/provider/SettingAPIProvider.java b/nl-business-setting/src/main/java/org/nl/setting/modular/provider/SettingAPIProvider.java new file mode 100644 index 0000000..37b299f --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/provider/SettingAPIProvider.java @@ -0,0 +1,38 @@ +package org.nl.setting.modular.provider; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.setting.api.SettingAPI; +import org.nl.enums.YesOrNoEnum; +import org.nl.exception.BadRequestException; +import org.nl.setting.modular.entity.Setting; +import org.nl.setting.modular.enums.SettingCodeEnum; +import org.nl.setting.modular.service.SettingService; +import org.springframework.stereotype.Service; + +/** + * @author dsh + * 2025/12/13 + */ +@Slf4j +@Service +public class SettingAPIProvider implements SettingAPI { + + @Resource + private SettingService settingService; + + @Override + public JSONObject querySttingParamIsActiveByCode(String setting_code) { + if (StrUtil.isBlank(setting_code)){ + log.info("设置编号不能为空"); + throw new BadRequestException("设置编号不能为空"); + } + JSONObject result = new JSONObject(); + result.put("data",settingService.getOne(new LambdaQueryWrapper<>(Setting.class).eq(Setting::getSetting_code,setting_code))); + return result; + } +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/service/SettingService.java b/nl-business-setting/src/main/java/org/nl/setting/modular/service/SettingService.java new file mode 100644 index 0000000..80b7266 --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/service/SettingService.java @@ -0,0 +1,26 @@ +package org.nl.setting.modular.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.response.WebResponse; +import org.nl.setting.modular.entity.Setting; +import org.nl.setting.modular.param.UpdateSettingParam; + +/** + * @author dsh + * 2025/12/6 + */ +public interface SettingService extends IService { + + /** + * 获取所有设置参数 + * @return WebResponse + */ + WebResponse queryAllSettingParam(); + + /** + * 根据设置编码修改设置参数 + * @return WebResponse + */ + WebResponse updateSettingParamByCode(UpdateSettingParam updateSettingParam); + +} diff --git a/nl-business-setting/src/main/java/org/nl/setting/modular/service/impl/SettingServiceImpl.java b/nl-business-setting/src/main/java/org/nl/setting/modular/service/impl/SettingServiceImpl.java new file mode 100644 index 0000000..1b6d389 --- /dev/null +++ b/nl-business-setting/src/main/java/org/nl/setting/modular/service/impl/SettingServiceImpl.java @@ -0,0 +1,139 @@ +package org.nl.setting.modular.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpResponse; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.setting.api.ScheduleSettingAPI; +import org.nl.api.schedule.setting.core.ScheduleAPISettingChargeParam; +import org.nl.api.schedule.setting.core.ScheduleAPISettingSpeedParam; +import org.nl.enums.YesOrNoEnum; +import org.nl.exception.BadRequestException; +import org.nl.response.WebResponse; +import org.nl.setting.modular.entity.Setting; +import org.nl.setting.modular.enums.SettingCodeEnum; +import org.nl.setting.modular.mapper.SettingMapper; +import org.nl.setting.modular.param.UpdateSettingParam; +import org.nl.setting.modular.service.SettingService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * @author dsh + * 2025/12/6 + */ +@Slf4j +@Service +public class SettingServiceImpl extends ServiceImpl implements SettingService { + + @Resource + private SettingMapper settingMapper; + + @Resource + private ScheduleSettingAPI scheduleSettingAPI; + + @Override + public WebResponse queryAllSettingParam() { + List setting = settingMapper.selectList(new LambdaQueryWrapper<>(Setting.class)); + return WebResponse.requestParamOk(setting); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse updateSettingParamByCode(UpdateSettingParam updateSettingParam) { + + String setting_code = updateSettingParam.getSetting_code(); + String is_active = updateSettingParam.getIs_active(); + String setting_value = updateSettingParam.getValue(); + + if (StrUtil.isBlank(setting_code)){ + throw new BadRequestException("设置编号不能为空"); + } + SettingCodeEnum settingCodeEnum = SettingCodeEnum.getByCode(setting_code); + if (settingCodeEnum == null){ + throw new BadRequestException("未找到该设置编码"); + } + + try { + + switch (settingCodeEnum){ + case SCHEDULE_IP: + log.info("修改调度IP"); + break; + case DELIVERY_SPEED: + log.info("修改配送速度"); + if (StrUtil.isBlank(setting_value)){ + throw new BadRequestException("修改配送速度,设置值不能为空"); + } + ScheduleAPISettingSpeedParam scheduleAPISettingSpeedParam = new ScheduleAPISettingSpeedParam(); + // 前端值是0.1-1.0,传给调度需要转换成1-100。 + int customSpeed = (int) (Double.parseDouble(setting_value) * 100); + scheduleAPISettingSpeedParam.setCustomSpeed(customSpeed); + HttpResponse speedResult = scheduleSettingAPI.settingSpeed(scheduleAPISettingSpeedParam); + if (speedResult == null || !speedResult.isOk()){ + throw new BadRequestException("设置调度配送速度失败"); + } + break; + case FAR_CALL: + log.info("修改远程设备呼叫"); + break; + case CALL_ARRIVAL_WAITING_TIME: + log.info("修改呼叫到达等待时间"); + break; + case WAITING_TIME_WHEN_MAKING_A_CALL: + log.info("修改呼叫时等待时间"); + break; + case AUTOMATIC_RECHARGE: + log.info("修改自动回充"); + if (StrUtil.isBlank(setting_value) || StrUtil.isBlank(is_active) ){ + throw new BadRequestException("修改自动回充,设置值和是否启用值不能为空"); + } + ScheduleAPISettingChargeParam scheduleAPISettingFreeChargeThreshold = new ScheduleAPISettingChargeParam(); + // 调度有默认强制充电阈值(不接任务),目前我们设置的是空闲无任务时车辆自动去充电的阈值。如果没启用将阈值设置成0。 + scheduleAPISettingFreeChargeThreshold.setFreeChargeThreshold( + YesOrNoEnum.YES.getCode().equals(is_active) ? Integer.parseInt(setting_value) : 0 + ); + HttpResponse freeChargeResult = scheduleSettingAPI.settingCharge(scheduleAPISettingFreeChargeThreshold); + if (freeChargeResult == null || !freeChargeResult.isOk()){ + throw new BadRequestException("设置调度自由充电阈值失败"); + } + break; + case CAN_IT_BE_CALLED_WHILE_CHARGING: + log.info("修改充电时是否可呼叫"); + if (StrUtil.isBlank(setting_value) || StrUtil.isBlank(is_active) ){ + throw new BadRequestException("修改充电时是否可呼叫,设置值和是否启用值不能为空"); + } + ScheduleAPISettingChargeParam scheduleAPISettingUsableForTaskThreshold = new ScheduleAPISettingChargeParam(); + // 如果充电时不可呼叫,将阈值改成100。 + scheduleAPISettingUsableForTaskThreshold.setFreeChargeThreshold( + YesOrNoEnum.YES.getCode().equals(is_active) ? Integer.parseInt(setting_value) : 100 + ); + HttpResponse chargeResult = scheduleSettingAPI.settingCharge(scheduleAPISettingUsableForTaskThreshold); + if (chargeResult == null || !chargeResult.isOk()){ + throw new BadRequestException("设置调度可接任务阈值失败"); + } + break; + } + + settingMapper.update(new LambdaUpdateWrapper<>(Setting.class) + .set(StrUtil.isNotBlank(setting_value),Setting::getValue,setting_value) + .set(StrUtil.isNotBlank(is_active),Setting::getIs_active,is_active) + .set(StrUtil.isNotBlank(updateSettingParam.getUpdate_by()),Setting::getUpdate_by,updateSettingParam.getUpdate_by()) + .set(Setting::getUpdate_time, DateUtil.now()) + .eq(Setting::getSetting_code,updateSettingParam.getSetting_code()) + ); + }catch (Exception e){ + log.info("更新设置失败:{}",e.getMessage()); + throw new BadRequestException("更新设置失败:"+e.getMessage()); + } + + return WebResponse.requestOk(); + } +} diff --git a/nl-business-task/pom.xml b/nl-business-task/pom.xml index 7e13dd6..557c825 100644 --- a/nl-business-task/pom.xml +++ b/nl-business-task/pom.xml @@ -27,5 +27,11 @@ org.nl nl-business-api + + + + + + diff --git a/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java b/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java new file mode 100644 index 0000000..0fed757 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/controller/TaskController.java @@ -0,0 +1,73 @@ +package org.nl.task.controller; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.logging.annotation.Log; +import org.nl.task.enums.TaskSourceEnum; +import org.nl.task.param.CancelTaskRequestParam; +import org.nl.task.param.CreateTaskRequestParam; +import org.nl.task.param.OneClickOperationRequestParam; +import org.nl.task.param.PauseAndResumeTaskParam; +import org.nl.task.service.TaskService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author dsh + * 2025/11/27 + */ +@Slf4j +@RestController +@RequestMapping("/task/") +public class TaskController { + + @Resource + private TaskService taskService; + + @PostMapping("/createTask") + @Log("创建任务") + public ResponseEntity sendTask(@RequestBody @Validated CreateTaskRequestParam createTaskRequestParam){ + return new ResponseEntity<>(taskService.createTask(createTaskRequestParam, TaskSourceEnum.SCREEN.getName()), HttpStatus.OK); + } + + @PostMapping("/cancelTask") + @Log("取消任务") + public ResponseEntity cancelTask(@RequestBody @Validated CancelTaskRequestParam cancelTaskRequestParam){ + return new ResponseEntity<>(taskService.cancelTask(cancelTaskRequestParam), HttpStatus.OK); + } + + @PostMapping("/pauseTask") + @Log("暂停任务") + public ResponseEntity pauseTask(@RequestBody @Validated PauseAndResumeTaskParam pauseAndResumeTaskParam){ + return new ResponseEntity<>(taskService.pauseTask(pauseAndResumeTaskParam), HttpStatus.OK); + } + + @PostMapping("/resumeTask") + @Log("恢复任务") + public ResponseEntity resumeTask(@RequestBody @Validated PauseAndResumeTaskParam pauseAndResumeTaskParam){ + return new ResponseEntity<>(taskService.resumeTask(pauseAndResumeTaskParam), HttpStatus.OK); + } + + @GetMapping("/queryNotFinishTaskInfoByVehicleNumber") + @Log("查询当前未完成的任务") + public ResponseEntity queryNotFinishTaskInfoByVehicleNumber(@RequestParam String vehicle_number){ + return new ResponseEntity<>(taskService.queryNotFinishTaskInfoByVehicleNumber(vehicle_number), HttpStatus.OK); + } + + @PostMapping("/taskOperationConfirm") + @Log("任务操作确认") + public ResponseEntity taskOperationConfirm(@RequestParam String task_code){ + return new ResponseEntity<>(taskService.taskOperationConfirm(task_code), HttpStatus.OK); + } + + @PostMapping("/oneClickOperation") + @Log("一键操作任务") + public ResponseEntity oneClickOperation(@RequestBody OneClickOperationRequestParam oneClickOperationRequestParam){ + return new ResponseEntity<>(taskService.oneClickOperation(oneClickOperationRequestParam, TaskSourceEnum.SCREEN.getName()),HttpStatus.OK); + } + +} diff --git a/nl-business-task/src/main/java/org/nl/task/entity/Task.java b/nl-business-task/src/main/java/org/nl/task/entity/Task.java new file mode 100644 index 0000000..4b188b9 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/entity/Task.java @@ -0,0 +1,99 @@ +package org.nl.task.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author dsh + * 2025/11/27 + */ +@Data +@TableName("task") +public class Task { + + /** + * 任务标识 + */ + @TableId(value = "id") + private String id; + + /** + * 任务号 + */ + private String task_code; + + /** + * 目标点 + */ + private String destinations; + + /** + * 任务类型 + */ + private String type; + + /** + * 任务状态 + */ + private String status; + + /** + * 车辆上报状态(0未上报,1上报,2处理完成) + */ + private String vehicleReportStatus; + + /** + * 到达等待时间 + */ + private Integer arrive_waiting_time; + /** + * 任务优先级 + */ + private String priority; + + /** + * 指定车号 + */ + private String vehicle_number; + + /** + * 实际执行车号 + */ + private String processingVehicle; + + /** + * 是否任务暂停 + */ + private String isPause; + + /** + * 备注 + */ + private String remark; + + /** + * 任务来源 + */ + private String source; + + /** + * 创建者 + */ + private String create_by; + + /** + * 创建时间 + */ + private String create_time; + + /** + * 修改时间 + */ + private String update_time; + + /** + * 修改者 + */ + private String update_by; +} diff --git a/nl-business-task/src/main/java/org/nl/task/enums/ScheduleTaskStatusEnum.java b/nl-business-task/src/main/java/org/nl/task/enums/ScheduleTaskStatusEnum.java new file mode 100644 index 0000000..f90c0ed --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/enums/ScheduleTaskStatusEnum.java @@ -0,0 +1,60 @@ +package org.nl.task.enums; + +import lombok.Data; +import lombok.Getter; + +/** + * @author dsh + * 2025/12/2 + */ +@Getter +public enum ScheduleTaskStatusEnum { + /** + * A transport order's initial state. + * A transport order remains in this state until its parameters have been + * set up completely. + */ + RAW("0", "RAW", "初始状态"), + /** + * Set (by a user/client) when a transport order's parameters have been set + * up completely and the kernel should dispatch it when possible. + */ + ACTIVE("1", "ACTIVE", "就绪"), + /** + * Marks a transport order as ready to be dispatched to a vehicle (i.e. all + * its dependencies have been finished). + */ + DISPATCHABLE("2", "DISPATCHABLE", "待分配车辆"), + + BEING_PROCESSED("3", "BEING_PROCESSED", "执行中"), + /** + * Marks a transport order as successfully completed. + */ + FINISHED("4", "FINISHED", "完成"), + /** + * General failure state that marks a transport order as failed. + */ + FAILED("5", "FAILED", "已取消"), + /** + * Failure state that marks a transport order as unroutable, i.e. it is + * impossible to find a route that would allow a vehicle to process the + * transport order completely. + */ + UNROUTABLE("6", "UNROUTABLE", "无路由"); + + private String code; + private String name; + private String desc; + + + ScheduleTaskStatusEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } + + public static boolean isFinalState(String state) { + return FAILED.getName().equals(state) + || UNROUTABLE.getName().equals(state); + } +} diff --git a/nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java b/nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java new file mode 100644 index 0000000..79344c2 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/enums/TaskSourceEnum.java @@ -0,0 +1,39 @@ +package org.nl.task.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/11/27 + */ +@Getter +public enum TaskSourceEnum { + + /** + * APP + */ + APP("1", "app", "app"), + /** + * 屏幕 + */ + SCREEN("2", "screen", "屏幕"), + /** + * 外部API + */ + EXTERNAL_API("3", "API", "外部API"), + /** + * 二维码 + */ + QRCODE("4", "QRCode", "二维码"); + + private String code; + private String name; + private String desc; + + + TaskSourceEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } +} diff --git a/nl-business-task/src/main/java/org/nl/task/enums/TaskStatusEnum.java b/nl-business-task/src/main/java/org/nl/task/enums/TaskStatusEnum.java new file mode 100644 index 0000000..6b6183d --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/enums/TaskStatusEnum.java @@ -0,0 +1,39 @@ +package org.nl.task.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/11/27 + */ +@Getter +public enum TaskStatusEnum { + + /** + * 生成 + */ + CREATE("0", "生成", "生成"), + /** + * 执行中 + */ + EXECUTING("1", "执行中", "执行中"), + /** + * 完成 + */ + FINISHED("2", "完成", "完成"), + /** + * 已取消 + */ + CANCELED("3", "已取消", "已取消"); + + private String code; + private String name; + private String desc; + + + TaskStatusEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } +} diff --git a/nl-business-task/src/main/java/org/nl/task/enums/TaskTypeEnum.java b/nl-business-task/src/main/java/org/nl/task/enums/TaskTypeEnum.java new file mode 100644 index 0000000..cd628f6 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/enums/TaskTypeEnum.java @@ -0,0 +1,53 @@ +package org.nl.task.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/12/1 + */ +@Getter +public enum TaskTypeEnum { + + /** + * 送冰水、配送任务都用这个任务类型 + */ + DELIVER("0", "Deliver", "送冰水、配送任务"), + /** + * 充电 + */ + CHARGE("1", "Charge", "充电"), + /** + * 加水 + */ + REFILL("2", "Refill", "加水"), + /** + * 移动 + */ + MOVE("3", "Move", "移动"); + + private String code; + private String name; + private String desc; + + + TaskTypeEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } + + /** + * 校验任务类型是否存在 + * @param taskType + * @return + */ + public static boolean validationTaskType(String taskType){ + return TaskTypeEnum.DELIVER.getName().equals(taskType) + || TaskTypeEnum.CHARGE.getName().equals(taskType) + || TaskTypeEnum.REFILL.getName().equals(taskType) + || TaskTypeEnum.MOVE.getName().equals(taskType); + + } + +} diff --git a/nl-business-task/src/main/java/org/nl/task/mapper/TaskMapper.java b/nl-business-task/src/main/java/org/nl/task/mapper/TaskMapper.java new file mode 100644 index 0000000..aaf80dd --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/mapper/TaskMapper.java @@ -0,0 +1,14 @@ +package org.nl.task.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.nl.task.entity.Task; + +/** + * @author dsh + * 2025/11/28 + */ +@Mapper +public interface TaskMapper extends BaseMapper { + +} diff --git a/nl-business-task/src/main/java/org/nl/task/mapper/mapping/TaskMapper.xml b/nl-business-task/src/main/java/org/nl/task/mapper/mapping/TaskMapper.xml new file mode 100644 index 0000000..564c27d --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/mapper/mapping/TaskMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/nl-business-task/src/main/java/org/nl/task/param/CancelTaskRequestParam.java b/nl-business-task/src/main/java/org/nl/task/param/CancelTaskRequestParam.java new file mode 100644 index 0000000..3873f8d --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/param/CancelTaskRequestParam.java @@ -0,0 +1,18 @@ +package org.nl.task.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/11/28 + */ +@Data +public class CancelTaskRequestParam { + + /** + * 任务编号 + */ + @NotBlank(message = "任务号不能为空") + private String task_code; +} diff --git a/nl-business-task/src/main/java/org/nl/task/param/CreateTaskRequestParam.java b/nl-business-task/src/main/java/org/nl/task/param/CreateTaskRequestParam.java new file mode 100644 index 0000000..e0714c1 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/param/CreateTaskRequestParam.java @@ -0,0 +1,39 @@ +package org.nl.task.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/11/27 + */ +@Data +public class CreateTaskRequestParam { + + /** + * 目标点 + */ + @NotBlank(message = "目标点不能为空") + private String destinations; + + /** + * 任务类型 + */ + @NotBlank(message = "任务类型不能为空") + private String type; + + /** + * 任务号 + */ + private String task_code; + + /** + * 任务优先级 + */ + private String priority; + + /** + * 指定车号 + */ + private String vehicle_number; +} diff --git a/nl-business-task/src/main/java/org/nl/task/param/OneClickOperationRequestParam.java b/nl-business-task/src/main/java/org/nl/task/param/OneClickOperationRequestParam.java new file mode 100644 index 0000000..3450432 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/param/OneClickOperationRequestParam.java @@ -0,0 +1,24 @@ +package org.nl.task.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/13 + */ +@Data +public class OneClickOperationRequestParam { + + /** + * 车号 + */ + @NotBlank(message = "车号不能为空") + private String vehicle_number; + + /** + * 一键任务类型 + */ + @NotBlank(message = "任务类型不能为空") + private String type; +} diff --git a/nl-business-task/src/main/java/org/nl/task/param/PauseAndResumeTaskParam.java b/nl-business-task/src/main/java/org/nl/task/param/PauseAndResumeTaskParam.java new file mode 100644 index 0000000..0f597f2 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/param/PauseAndResumeTaskParam.java @@ -0,0 +1,18 @@ +package org.nl.task.param; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * @author dsh + * 2025/12/3 + */ +@Data +public class PauseAndResumeTaskParam { + + /** + * 任务编号 + */ + @NotBlank(message = "任务号不能为空") + private String task_code; +} diff --git a/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java b/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java new file mode 100644 index 0000000..9787137 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/provider/TaskAPIProvider.java @@ -0,0 +1,67 @@ +package org.nl.task.provider; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.task.api.TaskAPI; +import org.nl.enums.ScheduleTaskReportStatusEnum; +import org.nl.exception.BadRequestException; +import org.nl.task.entity.Task; +import org.nl.task.enums.TaskStatusEnum; +import org.nl.task.service.TaskService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author dsh + * 2025/12/11 + */ +@Slf4j +@Service +public class TaskAPIProvider implements TaskAPI { + + @Resource + private TaskService taskService; + + @Override + public Task queryCurrentTaskByVehicleNumber(String vehicleNumber) { + List taskList = taskService.queryCurrentTaskInfoByVehicleNumber(vehicleNumber); + Task currentTask = new Task(); + if (ObjectUtil.isNotEmpty(taskList)){ + currentTask = taskList.stream() + .filter(task -> TaskStatusEnum.EXECUTING.getCode().equals(task.getStatus())) + .findFirst() + .orElse(new Task()); + } + return currentTask; + } + + @Override + public boolean updateTaskReportStatusByCode(String taskCode, String newReportStatus,String waiting_time) { + return taskService.update(new LambdaUpdateWrapper<>(Task.class) + .set(Task::getVehicleReportStatus, newReportStatus) + .set(StrUtil.isNotBlank(waiting_time),Task::getArrive_waiting_time,Integer.parseInt(waiting_time)) + .set(Task::getUpdate_time, DateUtil.now()) + .eq(Task::getTask_code,taskCode) + ); + } + + @Override + public String taskOperationConfirm(String taskCode,String vehicleNumber) { + Task task = this.queryCurrentTaskByVehicleNumber(vehicleNumber); + if (ObjectUtil.isEmpty(task)){ + log.info("任务操作确认失败,任务不存在"); + return null; + } + if (!task.getTask_code().equals(taskCode)){ + log.info("任务操作确认失败,上报的任务号不相同"); + return null; + } + return task.getVehicleReportStatus(); + } +} diff --git a/nl-business-task/src/main/java/org/nl/task/service/TaskService.java b/nl-business-task/src/main/java/org/nl/task/service/TaskService.java new file mode 100644 index 0000000..fa7dd51 --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/service/TaskService.java @@ -0,0 +1,67 @@ +package org.nl.task.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import org.nl.response.WebResponse; +import org.nl.task.entity.Task; +import org.nl.task.param.CancelTaskRequestParam; +import org.nl.task.param.CreateTaskRequestParam; +import org.nl.task.param.OneClickOperationRequestParam; +import org.nl.task.param.PauseAndResumeTaskParam; + +import java.util.List; + +/** + * @author dsh + * 2025/11/28 + */ +public interface TaskService extends IService{ + + /** + * 创建任务 + * @return WebResponse + */ + WebResponse createTask(CreateTaskRequestParam createTaskRequestParam, String taskSource); + + /** + * 取消任务 + * @return WebResponse + */ + WebResponse cancelTask(CancelTaskRequestParam cancelTaskRequestParam); + + /** + * 暂停任务 + * @return WebResponse + */ + WebResponse pauseTask(PauseAndResumeTaskParam pauseAndResumeTaskParam); + + /** + * 恢复任务 + * @return WebResponse + */ + WebResponse resumeTask(PauseAndResumeTaskParam pauseAndResumeTaskParam); + + /** + * 查询当前未完成的任务 + * @return WebResponse + */ + WebResponse queryNotFinishTaskInfoByVehicleNumber(String vehicle_number); + + /** + * 查询当前未完成的任务 + * @return List + */ + List queryCurrentTaskInfoByVehicleNumber(String vehicle_number); + + /** + * 任务操作确认 + * @return WebResponse + */ + WebResponse taskOperationConfirm(String task_code); + + /** + * 一键任务操作 + * @param oneClickOperationRequestParam + * @return WebResponse + */ + WebResponse oneClickOperation(OneClickOperationRequestParam oneClickOperationRequestParam,String taskSource); +} diff --git a/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java b/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java new file mode 100644 index 0000000..2d38b8c --- /dev/null +++ b/nl-business-task/src/main/java/org/nl/task/service/impl/TaskServiceImpl.java @@ -0,0 +1,290 @@ +package org.nl.task.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.nl.api.schedule.task.api.ScheduleTaskAPI; +import org.nl.api.schedule.task.core.ScheduleAPICreateOneClickTaskParam; +import org.nl.api.schedule.task.core.ScheduleAPICreateTaskParam; +import org.nl.enums.ScheduleTaskReportStatusEnum; +import org.nl.enums.YesOrNoEnum; +import org.nl.exception.BadRequestException; +import org.nl.response.WebResponse; +import org.nl.task.entity.Task; +import org.nl.task.enums.ScheduleTaskStatusEnum; +import org.nl.task.enums.TaskStatusEnum; +import org.nl.task.enums.TaskTypeEnum; +import org.nl.task.mapper.TaskMapper; +import org.nl.task.param.CancelTaskRequestParam; +import org.nl.task.param.CreateTaskRequestParam; +import org.nl.task.param.OneClickOperationRequestParam; +import org.nl.task.param.PauseAndResumeTaskParam; +import org.nl.task.service.TaskService; +import org.nl.util.IdUtil; +import org.nl.util.TaskCodeGeneratorUtil; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author dsh + * 2025/11/28 + */ +@Slf4j +@Service +public class TaskServiceImpl extends ServiceImpl implements TaskService { + + @Resource + private TaskMapper taskMapper; + + @Resource + private ScheduleTaskAPI scheduleTaskAPI; + + private ConcurrentHashMap> taskInfoList = new ConcurrentHashMap<>(); + + /** + * 定时查询车辆任务状态(每秒执行) + */ + @Scheduled(fixedRate = 1000) // 每秒执行一次 + public void queryScheduleTaskStatus() { + try { + List taskList = taskMapper.selectList(new LambdaQueryWrapper<>(Task.class) + .lt(Task::getStatus,TaskStatusEnum.FINISHED.getCode()) + ); + //根据车辆编号分类 车辆任务队列。 + taskInfoList = taskList.stream() + .filter(task -> StrUtil.isNotBlank(task.getVehicle_number()) || StrUtil.isNotBlank(task.getProcessingVehicle())) + .collect(Collectors.groupingByConcurrent(task -> + StrUtil.isNotBlank(task.getProcessingVehicle()) ? + task.getProcessingVehicle() : + task.getVehicle_number(), + ConcurrentHashMap::new, + Collectors.toList() + )); + for (Task task : taskList) { + HttpResponse result = scheduleTaskAPI.queryTaskStatusByTaskId(task.getTask_code()); + if (result == null || !result.isOk()){ + log.info("获取调度任务状态失败"); + continue; + } + JSONObject scheduleTaskStatusJSON = JSONObject.parseObject(result.body()); + String scheduleTaskState = scheduleTaskStatusJSON.getString("state"); + String newTaskState = ""; + if (ScheduleTaskStatusEnum.FINISHED.name().equals(scheduleTaskState)){ + newTaskState = TaskStatusEnum.FINISHED.getCode(); + } else if (ScheduleTaskStatusEnum.isFinalState(scheduleTaskState)) { + newTaskState = TaskStatusEnum.CANCELED.getCode(); + task.setRemark("无路由或取消:" + scheduleTaskState); + } else if (ScheduleTaskStatusEnum.BEING_PROCESSED.name().equals(scheduleTaskState)) { + newTaskState = TaskStatusEnum.EXECUTING.getCode(); + // 充电和加水任务的目标点是调度分配的,在查询任务状态时更新目标点。 + if (StrUtil.isBlank(task.getDestinations()) && ObjectUtil.isNotEmpty(scheduleTaskStatusJSON.getJSONArray("destinations"))){ + JSONObject destination = scheduleTaskStatusJSON.getJSONArray("destinations").getJSONObject(0); + task.setDestinations(destination.getString("locationName")); + } + task.setProcessingVehicle(scheduleTaskStatusJSON.getString("processingVehicle")); + } + // 任务状态改变 进行更新 + if (StrUtil.isNotBlank(newTaskState) && !newTaskState.equals(task.getStatus())){ + log.info("更新任务状态,任务号:{},更新前状态:{},需要更新成的状态:{}",task.getTask_code(),task.getStatus(),newTaskState); + task.setStatus(newTaskState); + task.setUpdate_time(DateUtil.now()); + // 更新任务状态 + taskMapper.updateById(task); + log.info("更新任务状态成功"); + } + } + } catch (Exception e) { + log.error("更新任务状态失败: {}", e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse createTask(CreateTaskRequestParam createTaskRequestParam, String taskSource) { + try { + if (!TaskTypeEnum.validationTaskType(createTaskRequestParam.getType())) { + throw new BadRequestException("任务类型不存在"); + } + Task task = BeanUtil.copyProperties(createTaskRequestParam, Task.class); + task.setId(IdUtil.getStringId()); + if (StrUtil.isBlank(task.getTask_code())){ + task.setTask_code(TaskCodeGeneratorUtil.generateTaskId()); + } + task.setType(createTaskRequestParam.getType()); + task.setSource(taskSource); + task.setStatus(TaskStatusEnum.CREATE.getCode()); + task.setIsPause(YesOrNoEnum.NO.getCode()); + task.setVehicleReportStatus("0"); + task.setCreate_time(DateUtil.now()); + taskMapper.insert(task); + + ScheduleAPICreateTaskParam scheduleAPICreateTaskParam = BeanUtil.copyProperties(task, ScheduleAPICreateTaskParam.class); + HttpResponse result = scheduleTaskAPI.createTask(scheduleAPICreateTaskParam); + if (result == null || !result.isOk()){ + throw new BadRequestException("调度生成任务失败"); + } + return WebResponse.requestOk(); + }catch (Exception e){ + log.error("创建任务失败:{}",e.getMessage()); + throw new BadRequestException("创建任务失败:"+e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse cancelTask(CancelTaskRequestParam cancelTaskRequestParam) { + try { + if (StrUtil.isBlank(cancelTaskRequestParam.getTask_code())){ + throw new BadRequestException("任务号不能为空"); + } + + HttpResponse result = scheduleTaskAPI.cancelTask(cancelTaskRequestParam.getTask_code()); + if (result == null || !result.isOk()){ + log.info("取消调度任务失败"); + throw new BadRequestException("取消调度任务失败"); + } + + taskMapper.update(new LambdaUpdateWrapper<>(Task.class) + .set(Task::getStatus,TaskStatusEnum.CANCELED.getCode()) + .eq(Task::getTask_code,cancelTaskRequestParam.getTask_code()) + ); + }catch (Exception e){ + log.error("取消任务失败:{}",e.getMessage()); + throw new BadRequestException("取消任务失败:"+e.getMessage()); + } + + return WebResponse.requestOk(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse pauseTask(PauseAndResumeTaskParam pauseAndResumeTaskParam) { + try { + if (StrUtil.isBlank(pauseAndResumeTaskParam.getTask_code())){ + throw new BadRequestException("任务号不能为空"); + } + + HttpResponse result = scheduleTaskAPI.pauseTask(pauseAndResumeTaskParam.getTask_code()); + if (result == null || !result.isOk()){ + throw new BadRequestException("暂停调度任务失败"); + } + + taskMapper.update(new LambdaUpdateWrapper<>(Task.class) + .set(Task::getIsPause, YesOrNoEnum.YES.getCode()) + .set(Task::getRemark,"暂停任务") + .set(Task::getUpdate_time,DateUtil.now()) + .eq(Task::getTask_code,pauseAndResumeTaskParam.getTask_code()) + ); + + return WebResponse.requestOk(); + }catch (Exception e){ + log.error("暂停任务失败:{}",e.getMessage()); + throw new BadRequestException("暂停任务失败:"+e.getMessage()); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse resumeTask(PauseAndResumeTaskParam pauseAndResumeTaskParam) { + try { + if (StrUtil.isBlank(pauseAndResumeTaskParam.getTask_code())){ + throw new BadRequestException("任务号不能为空"); + } + + HttpResponse result = scheduleTaskAPI.resumeTask(pauseAndResumeTaskParam.getTask_code()); + if (result == null || !result.isOk()){ + throw new BadRequestException("恢复调度任务失败"); + } + + taskMapper.update(new LambdaUpdateWrapper<>(Task.class) + .set(Task::getIsPause, YesOrNoEnum.NO.getCode()) + .set(Task::getRemark,"恢复任务") + .set(Task::getUpdate_time,DateUtil.now()) + .eq(Task::getTask_code,pauseAndResumeTaskParam.getTask_code()) + ); + + return WebResponse.requestOk(); + }catch (Exception e){ + log.error("恢复任务失败:{}",e.getMessage()); + throw new BadRequestException("恢复任务失败:"+e.getMessage()); + } + } + + @Override + public WebResponse queryNotFinishTaskInfoByVehicleNumber(String vehicle_number) { + if (StrUtil.isBlank(vehicle_number)){ + throw new BadRequestException("车号不能为空"); + } + return WebResponse.requestParamOk(taskInfoList.get(vehicle_number)); + } + + @Override + public List queryCurrentTaskInfoByVehicleNumber(String vehicle_number) { + if (StrUtil.isBlank(vehicle_number)){ + throw new BadRequestException("车号不能为空"); + } + return taskInfoList.get(vehicle_number); + } + + @Override + public WebResponse taskOperationConfirm(String task_code) { + + boolean reuslt = taskMapper.update(new LambdaUpdateWrapper<>(Task.class) + .set(Task::getVehicleReportStatus, ScheduleTaskReportStatusEnum.FINISH_REPORTED.getCode()) + .set(Task::getUpdate_time,DateUtil.now()) + .eq(Task::getTask_code,task_code) + ) > 0; + if (!reuslt){ + throw new BadRequestException("任务操作确认失败"); + } + return WebResponse.requestOk(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public WebResponse oneClickOperation(OneClickOperationRequestParam oneClickOperationRequestParam,String taskSource) { + try { + log.info("一键任务操作参数:{}",oneClickOperationRequestParam); + Task task = BeanUtil.copyProperties(oneClickOperationRequestParam, Task.class); + task.setId(IdUtil.getStringId()); + if (StrUtil.isBlank(task.getTask_code())){ + task.setTask_code(TaskCodeGeneratorUtil.generateTaskId()); + } + task.setType(oneClickOperationRequestParam.getType()); + task.setSource(taskSource); + task.setStatus(TaskStatusEnum.CREATE.getCode()); + task.setIsPause(YesOrNoEnum.NO.getCode()); + task.setVehicleReportStatus("0"); + task.setCreate_time(DateUtil.now()); + taskMapper.insert(task); + + ScheduleAPICreateOneClickTaskParam scheduleAPICreateOneClickTaskParam = BeanUtil.copyProperties(task, ScheduleAPICreateOneClickTaskParam.class); + HttpResponse result = scheduleTaskAPI.oneClickOperationTask(scheduleAPICreateOneClickTaskParam); + if (result == null || !result.isOk()){ + throw new BadRequestException("调度生成一键任务失败"); + } + return WebResponse.requestOk(); + }catch (Exception e){ + log.error("创建一键任务失败:{}",e.getMessage()); + throw new BadRequestException("创建一键任务失败:"+e.getMessage()); + } + } + +} diff --git a/nl-common/pom.xml b/nl-common/pom.xml index e01f589..dae1936 100644 --- a/nl-common/pom.xml +++ b/nl-common/pom.xml @@ -24,5 +24,40 @@ org.projectlombok lombok + + + cn.hutool + hutool-all + + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.alibaba + fastjson + + + + + org.springframework.boot + spring-boot-starter-validation + diff --git a/nl-common/src/main/java/org/nl/config/CorsConfig.java b/nl-common/src/main/java/org/nl/config/CorsConfig.java new file mode 100644 index 0000000..66bad19 --- /dev/null +++ b/nl-common/src/main/java/org/nl/config/CorsConfig.java @@ -0,0 +1,26 @@ +package org.nl.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @author dsh + * 2025/12/13 + */ +@Configuration +@EnableWebMvc +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("*") + .allowedHeaders(CorsConfiguration.ALL) + .allowedMethods(CorsConfiguration.ALL) + .allowCredentials(true) + .maxAge(3600); + } +} diff --git a/nl-common/src/main/java/org/nl/enums/ScheduleTaskReportStatusEnum.java b/nl-common/src/main/java/org/nl/enums/ScheduleTaskReportStatusEnum.java new file mode 100644 index 0000000..a72922f --- /dev/null +++ b/nl-common/src/main/java/org/nl/enums/ScheduleTaskReportStatusEnum.java @@ -0,0 +1,44 @@ +package org.nl.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/12/11 + */ +@Getter +public enum ScheduleTaskReportStatusEnum { + + /** + * 未上报 + */ + NOT_REPORTED("0", "未上报", "Not reported"), + /** + * 已上报 + */ + REPORTED("1", "已上报", "reported"), + /** + * 处理完成 + */ + FINISH_REPORTED("2", "处理完成", "外部API"); + + private String code; + private String name; + private String desc; + + + ScheduleTaskReportStatusEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } + + public static ScheduleTaskReportStatusEnum getByCode(String code) { + for (ScheduleTaskReportStatusEnum e : ScheduleTaskReportStatusEnum.values()) { + if (e.code.equals(code)) { + return e; + } + } + return null; + } +} diff --git a/nl-common/src/main/java/org/nl/enums/YesOrNoEnum.java b/nl-common/src/main/java/org/nl/enums/YesOrNoEnum.java new file mode 100644 index 0000000..7c8bc3b --- /dev/null +++ b/nl-common/src/main/java/org/nl/enums/YesOrNoEnum.java @@ -0,0 +1,31 @@ +package org.nl.enums; + +import lombok.Getter; + +/** + * @author dsh + * 2025/12/3 + */ +@Getter +public enum YesOrNoEnum { + + /** + * 否 + */ + NO("0", "否", "否"), + /** + * 执行中 + */ + YES("1", "是", "是"); + + private String code; + private String name; + private String desc; + + + YesOrNoEnum(String code, String name, String desc) { + this.code = code; + this.name = name; + this.desc = desc; + } +} diff --git a/nl-common/src/main/java/org/nl/exception/ApiError.java b/nl-common/src/main/java/org/nl/exception/ApiError.java new file mode 100644 index 0000000..e5603ea --- /dev/null +++ b/nl-common/src/main/java/org/nl/exception/ApiError.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.nl.exception; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +class ApiError { + + private Integer code = 400; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime Date; + private String message; + + private ApiError() { + Date = LocalDateTime.now(); + } + + public static ApiError error(String message){ + ApiError apiError = new ApiError(); + apiError.setMessage(message); + return apiError; + } + + public static ApiError error(Integer status, String message){ + ApiError apiError = new ApiError(); + apiError.setCode(status); + apiError.setMessage(message); + return apiError; + } +} + + diff --git a/nl-common/src/main/java/org/nl/exception/BadRequestException.java b/nl-common/src/main/java/org/nl/exception/BadRequestException.java new file mode 100644 index 0000000..a9a256c --- /dev/null +++ b/nl-common/src/main/java/org/nl/exception/BadRequestException.java @@ -0,0 +1,25 @@ +package org.nl.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +/** + * @author dsh + * 2025/7/3 + */ +@Getter +public class BadRequestException extends RuntimeException{ + + private Integer status = BAD_REQUEST.value(); + + public BadRequestException(String msg){ + super(msg); + } + + public BadRequestException(HttpStatus status, String msg){ + super(msg); + this.status = status.value(); + } +} diff --git a/nl-common/src/main/java/org/nl/exception/GlobalExceptionHandler.java b/nl-common/src/main/java/org/nl/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..826dcdc --- /dev/null +++ b/nl-common/src/main/java/org/nl/exception/GlobalExceptionHandler.java @@ -0,0 +1,77 @@ +package org.nl.exception; + +import lombok.extern.slf4j.Slf4j; +import org.nl.util.ThrowableUtil; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.Objects; + + +/** + * @author liejiu + */ +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + /** + * 处理所有不可知的异常 + */ + @ExceptionHandler(Throwable.class) + public ResponseEntity handleException(Throwable e){ + // 打印堆栈信息 + log.error(ThrowableUtil.getStackTrace(e)); + return buildResponseEntity(ApiError.error(e.getMessage())); + } + + /** + * token 无效的异常拦截 + * @param e + * @return + */ +// @ExceptionHandler(value = NotLoginException.class) +// public ResponseEntity notLoginException(Exception e) { +//// log.error(ThrowableUtil.getStackTrace(e)); +// return buildResponseEntity(ApiError.error(401,"token 失效")); +// } + + + /** + * 处理自定义异常 + */ + @ExceptionHandler(value = BadRequestException.class) + public ResponseEntity badRequestException(BadRequestException e) { + // 打印堆栈信息 + log.error(ThrowableUtil.getStackTrace(e)); + log.info(e.getMessage()); + return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage())); + } + + + /** + * 处理所有接口数据验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e){ + // 打印堆栈信息 + log.error(ThrowableUtil.getStackTrace(e)); + String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\."); + String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); + String msg = "不能为空"; + if(msg.equals(message)){ + message = str[1] + ":" + message; + } + return buildResponseEntity(ApiError.error(message)); + } + + /** + * 统一返回 + */ + private ResponseEntity buildResponseEntity(ApiError apiError) { + return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getCode())); + } +} diff --git a/nl-common/src/main/java/org/nl/logging/annotation/Log.java b/nl-common/src/main/java/org/nl/logging/annotation/Log.java new file mode 100644 index 0000000..14f94ea --- /dev/null +++ b/nl-common/src/main/java/org/nl/logging/annotation/Log.java @@ -0,0 +1,15 @@ +package org.nl.logging.annotation; + +import java.lang.annotation.*; + +/** + * @author dsh + * 2025/11/28 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log { + String value() default ""; + +} diff --git a/nl-common/src/main/java/org/nl/logging/aspect/LogAspect.java b/nl-common/src/main/java/org/nl/logging/aspect/LogAspect.java new file mode 100644 index 0000000..012f6b0 --- /dev/null +++ b/nl-common/src/main/java/org/nl/logging/aspect/LogAspect.java @@ -0,0 +1,79 @@ +package org.nl.logging.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.nl.logging.annotation.Log; +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + + +/** + * @author dsh + * 2025/11/28 + */ +@Slf4j +@Aspect +@Component +public class LogAspect { + + /** + * 配置切入点 + */ + @Pointcut("@annotation(org.nl.logging.annotation.Log)") + public void logPointCut(){} + + /** + * 环绕通知 + * @param point + * @return + * @throws Throwable + */ + @Around("logPointCut()") + public Object logAround(ProceedingJoinPoint point) throws Throwable { + Object result = null; + long beginTime = System.currentTimeMillis(); + // 执行方法 + result = point.proceed(); + // 执行时长(毫秒) + long time = System.currentTimeMillis() - beginTime; + // 保存日志 + saveLog(point, time); + return result; + } + + private void saveLog(ProceedingJoinPoint joinPoint, long time) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + Log logAnnotation = method.getAnnotation(Log.class); + // 注解上的描述 + String description = ""; + if (logAnnotation != null) { + description = logAnnotation.value(); + } + // 请求的方法名 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = signature.getName(); + // 请求的方法参数值 + Object[] args = joinPoint.getArgs(); + // 请求的方法参数名称 + ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); + String[] paramNames = parameterNameDiscoverer.getParameterNames(method); + String params = ""; + if (args != null && paramNames != null) { + + for (int i = 0; i < args.length; i++) { + params += " " + paramNames[i] + ": " + args[i]; + } + } + log.info("【日志注解】开始执行 -- 描述:{} -- 类方法:{}.{}() -- 参数:{} -- 执行时长:{}毫秒", description, className, methodName, params, time); + } + + +} diff --git a/nl-common/src/main/java/org/nl/response/WebResponse.java b/nl-common/src/main/java/org/nl/response/WebResponse.java new file mode 100644 index 0000000..5357aed --- /dev/null +++ b/nl-common/src/main/java/org/nl/response/WebResponse.java @@ -0,0 +1,77 @@ +package org.nl.response; + +import lombok.Builder; +import lombok.Data; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.OK; + +/** + * @author dsh + * 2025/11/26 + */ +@Data +@Builder +public class WebResponse { + + /** + * 状态码 + */ + private Integer code = 200; + + /** + * 消息 + */ + private String message; + + /** + * 数据 + */ + private T data; + + /** + * 不带数据反馈 + * @return WebResponse + */ + public static WebResponse requestOk() { + return WebResponse.builder() + .message("成功") + .code(OK.value()) + .build(); + } + + /** + * 带消息反馈 + * @return WebResponse + */ + public static WebResponse requestOk(String message) { + return WebResponse.builder() + .message(message) + .code(OK.value()) + .build(); + } + + /** + * 带数据反馈 + * @return WebResponse + */ + public static WebResponse requestParamOk(T data) { + return WebResponse.builder() + .message("成功") + .data(data) + .code(OK.value()) + .build(); + } + + /** + * 带数据和消息反馈 + * @return WebResponse + */ + public static WebResponse requestParamOk(T data, String message) { + return WebResponse.builder() + .message(message) + .data(data) + .code(OK.value()) + .build(); + } +} diff --git a/nl-common/src/main/java/org/nl/util/IdUtil.java b/nl-common/src/main/java/org/nl/util/IdUtil.java new file mode 100644 index 0000000..1b8e2e8 --- /dev/null +++ b/nl-common/src/main/java/org/nl/util/IdUtil.java @@ -0,0 +1,11 @@ +package org.nl.util; + +public class IdUtil { + public static Long getLongId() { + return cn.hutool.core.util.IdUtil.getSnowflake(1, 1).nextId(); + } + + public static String getStringId() { + return String.valueOf(IdUtil.getLongId()); + } +} diff --git a/nl-common/src/main/java/org/nl/util/TaskCodeGeneratorUtil.java b/nl-common/src/main/java/org/nl/util/TaskCodeGeneratorUtil.java new file mode 100644 index 0000000..7fd23da --- /dev/null +++ b/nl-common/src/main/java/org/nl/util/TaskCodeGeneratorUtil.java @@ -0,0 +1,123 @@ +package org.nl.util; + + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.ReentrantLock; + +/** + * @author dsh + * 2025/12/1 + * 任务号生成器工具类 - 时间戳 + 序列号方案 + */ +public class TaskCodeGeneratorUtil { + + private TaskCodeGeneratorUtil() { + throw new IllegalStateException("Utility class"); + } + + // 序列号生成器 + private static final AtomicLong SEQUENCE = new AtomicLong(0); + // 上次时间戳 + private static volatile String LAST_TIMESTAMP = ""; + // 重入锁保证线程安全 + private static final ReentrantLock LOCK = new ReentrantLock(); + + // 日期时间格式化器(线程安全) + private static final DateTimeFormatter DATE_TIME_FORMATTER = + DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS"); + + /** + * 生成任务号(默认格式:yyyyMMddHHmmssSSS + 3位序列号) + * @return 任务号字符串 + */ + public static String generateTaskId() { + return generateTaskId("yyyyMMddHHmmssSSS", 3); + } + + /** + * 生成任务号(自定义时间格式) + * @param datePattern 时间格式,如:yyyyMMddHHmmss + * @param sequenceLength 序列号长度 + * @return 任务号字符串 + */ + public static String generateTaskId(String datePattern, int sequenceLength) { + LOCK.lock(); + try { + String currentTimestamp = getCurrentTimestamp(datePattern); + + // 检查是否是新时间单位 + if (!currentTimestamp.equals(LAST_TIMESTAMP)) { + LAST_TIMESTAMP = currentTimestamp; + SEQUENCE.set(0); + } + + // 获取并增加序列号 + long seq = SEQUENCE.getAndIncrement(); + + // 检查序列号是否超过范围 + long maxSeq = (long) Math.pow(10, sequenceLength) - 1; + if (seq > maxSeq) { + // 序列号超过限制,等待下一时间单位 + try { + Thread.sleep(1); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + // 递归调用(注意:这种情况极少发生) + return generateTaskId(datePattern, sequenceLength); + } + + // 格式化成指定长度的序列号 + String sequenceFormat = "%0" + sequenceLength + "d"; + return currentTimestamp + String.format(sequenceFormat, seq); + } finally { + LOCK.unlock(); + } + } + + /** + * 生成带前缀的任务号 + * @param prefix 任务号前缀,如:TASK、ORDER等 + * @return 带前缀的任务号 + */ + public static String generateTaskIdWithPrefix(String prefix) { + return prefix + "_" + generateTaskId(); + } + + /** + * 生成带前缀的自定义格式任务号 + * @param prefix 前缀 + * @param datePattern 时间格式 + * @param sequenceLength 序列号长度 + * @return 任务号 + */ + public static String generateTaskIdWithPrefix(String prefix, String datePattern, int sequenceLength) { + return prefix + "_" + generateTaskId(datePattern, sequenceLength); + } + + /** + * 获取当前时间戳字符串 + */ + private static String getCurrentTimestamp(String pattern) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); + return LocalDateTime.now().format(formatter); + } + + /** + * 批量生成任务号 + * @param count 生成数量 + * @return 任务号列表 + */ + public static List batchGenerateTaskId(int count) { + List taskIds = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + taskIds.add(generateTaskId()); + } + return taskIds; + } +} diff --git a/nl-common/src/main/java/org/nl/util/ThrowableUtil.java b/nl-common/src/main/java/org/nl/util/ThrowableUtil.java new file mode 100644 index 0000000..5c31ed4 --- /dev/null +++ b/nl-common/src/main/java/org/nl/util/ThrowableUtil.java @@ -0,0 +1,22 @@ +package org.nl.util; + +import java.io.PrintWriter; +import java.io.StringWriter; + + +/** + * @author liejiu + */ +public class ThrowableUtil { + + /** + * 获取堆栈信息 + */ + public static String getStackTrace(Throwable throwable){ + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + throwable.printStackTrace(pw); + return sw.toString(); + } + } +} diff --git a/nl-common/src/main/java/org/nl/util/WebSocketConfig.java b/nl-common/src/main/java/org/nl/util/WebSocketConfig.java new file mode 100644 index 0000000..b3515fd --- /dev/null +++ b/nl-common/src/main/java/org/nl/util/WebSocketConfig.java @@ -0,0 +1,18 @@ +package org.nl.util; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +/** + * @author dsh + * 2025/11/26 + */ +@Configuration +@EnableWebSocket +public class WebSocketConfig { + + @Bean + public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } +} diff --git a/nl-web-app/src/main/java/org/nl/Application.java b/nl-web-app/src/main/java/org/nl/Application.java index 7506117..e1232b5 100644 --- a/nl-web-app/src/main/java/org/nl/Application.java +++ b/nl-web-app/src/main/java/org/nl/Application.java @@ -14,11 +14,13 @@ package org.nl; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.Banner; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -31,6 +33,9 @@ import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController @SpringBootApplication +@EnableScheduling +@EnableTransactionManagement +@MapperScan("org.nl.**.mapper") public class Application { /* 解决druid 日志报错:discard long time none received connection:xxx */ @@ -47,7 +52,7 @@ public class Application { @SneakyThrows public static void main(String[] args) { SpringApplication springApplication = new SpringApplication(Application.class); - springApplication.setBannerMode(Banner.Mode.OFF); +// springApplication.setBannerMode(Banner.Mode.OFF); ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args); Environment env = configurableApplicationContext.getEnvironment(); log.info(""" diff --git a/nl-web-app/src/main/resources/banner.txt b/nl-web-app/src/main/resources/banner.txt new file mode 100644 index 0000000..2914bcc --- /dev/null +++ b/nl-web-app/src/main/resources/banner.txt @@ -0,0 +1,8 @@ + _ _ ___________ _ _____ _ ___________ _____ +| \ | | _ | ___ \ | | ___| | | ___| ___|_ _| +| \| | | | | |_/ / | | |__ | | | |__ | |_ | | +| . ` | | | | ___ \ | | __|| | | __|| _| | | +| |\ \ \_/ / |_/ / |____| |___| |____| |___| | | | +\_| \_/\___/\____/\_____/\____/\_____/\____/\_| \_/ + + :: Spring Boot :: (v3.2.1.RELEASE) \ No newline at end of file diff --git a/nl-web-app/src/main/resources/config/application-dev.yml b/nl-web-app/src/main/resources/config/application-dev.yml new file mode 100644 index 0000000..ae8b687 --- /dev/null +++ b/nl-web-app/src/main/resources/config/application-dev.yml @@ -0,0 +1,93 @@ +server: + # 端口 + port: 8081 + tomcat: + max-swallow-size: 100MB +spring: + datasource: + dynamic: + datasource: + master: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/nl_frobt?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false + username: root + password: 123456 + druid: + db-type: com.alibaba.druid.pool.DruidDataSource +# driver-class-name: com.mysql.cj.jdbc.Driver +# url: jdbc:mysql://localhost:3306/nl_frobt?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false +# username: root +# password: 123456 + # 初始连接数 + initial-size: 5 + # 最小连接数 + min-idle: 15 + # 最大连接数 + max-active: 30 + # 超时时间(以秒数为单位) + remove-abandoned-timeout: 180 + # 获取连接超时时间 + max-wait: 3000 + # 连接有效性检测时间 + time-between-eviction-runs-millis: 60000 + # 连接在池中最小生存的时间 + min-evictable-idle-time-millis: 300000 + # 连接在池中最大生存的时间 + max-evictable-idle-time-millis: 900000 + # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 + test-while-idle: true + # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 + test-on-borrow: true + # 是否在归还到池中前进行检验 + test-on-return: false + # 检测连接是否有效 + validation-query: select 1 + # 配置监控统计 + webStatFilter: + enabled: true + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + filter: + stat: + enabled: true + # 记录慢SQL + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# 文件存储路径 +file: + mac: + path: ~/file/ + avatar: ~/avatar/ + linux: + path: /home/eladmin/file/ + avatar: /home/eladmin/avatar/ + windows: + path: C:\eladmin\file\ + avatar: C:\eladmin\avatar\ + # 文件大小 /M + maxSize: 100 + avatarMaxSize: 5 + +############## Sa-Token 配置 (文档: https://sa-token.cc) ############## +sa-token: + # token名称 (同时也是cookie名称) + token-name: Authorization + # token有效期,单位s 默认30天, -1代表永不过期 + timeout: 2592000 + # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 + activity-timeout: -1 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # token风格 + token-style: random-128 + # 是否输出操作日志 + is-log: true \ No newline at end of file diff --git a/nl-web-app/src/main/resources/config/application-prod.yml b/nl-web-app/src/main/resources/config/application-prod.yml new file mode 100644 index 0000000..c83a39e --- /dev/null +++ b/nl-web-app/src/main/resources/config/application-prod.yml @@ -0,0 +1,86 @@ +server: + # 端口 + port: 8011 + tomcat: + max-swallow-size: 100MB +spring: + datasource: + druid: + db-type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://192.168.100.201:3307/nl_apt15e?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false + username: root + password: 123456 + # 初始连接数 + initial-size: 5 + # 最小连接数 + min-idle: 15 + # 最大连接数 + max-active: 30 + # 超时时间(以秒数为单位) + remove-abandoned-timeout: 180 + # 获取连接超时时间 + max-wait: 3000 + # 连接有效性检测时间 + time-between-eviction-runs-millis: 60000 + # 连接在池中最小生存的时间 + min-evictable-idle-time-millis: 300000 + # 连接在池中最大生存的时间 + max-evictable-idle-time-millis: 900000 + # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 + test-while-idle: true + # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 + test-on-borrow: true + # 是否在归还到池中前进行检验 + test-on-return: false + # 检测连接是否有效 + validation-query: select 1 + # 配置监控统计 + webStatFilter: + enabled: true + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + filter: + stat: + enabled: true + # 记录慢SQL + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# 文件存储路径 +file: + mac: + path: ~/file/ + avatar: ~/avatar/ + linux: + path: /home/fr1511b/nlapt15e/file/ + avatar: /home/fr1511b/nlapt15e/avatar/ + windows: + path: C:\eladmin\file\ + avatar: C:\eladmin\avatar\ + # 文件大小 /M + maxSize: 100 + avatarMaxSize: 5 + +############## Sa-Token 配置 (文档: https://sa-token.cc) ############## +sa-token: + # token名称 (同时也是cookie名称) + token-name: Authorization + # token有效期,单位s 默认30天, -1代表永不过期 + timeout: 2592000 + # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 + activity-timeout: -1 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # token风格 + token-style: random-128 + # 是否输出操作日志 + is-log: true \ No newline at end of file diff --git a/nl-web-app/src/main/resources/config/application.yml b/nl-web-app/src/main/resources/config/application.yml new file mode 100644 index 0000000..71a981a --- /dev/null +++ b/nl-web-app/src/main/resources/config/application.yml @@ -0,0 +1,54 @@ +spring: + servlet: + multipart: + max-file-size: 100MB + max-request-size: 100MB + messages: + basename: language/task/task,language/error/error,language/buss/buss + encoding: UTF-8 + profiles: + active: dev + jackson: + time-zone: GMT+8 + +mybatis-plus: + configuration: + map-underscore-to-camel-case: false + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + mapper-locations: classpath*:org/nl/**/mapping/*.xml + global-config: + banner: false + +logging: + file: + path: logs + config: classpath:logback-spring.xml + +customize: + log-dir: ${logging.file.path}/root + errorImage-dir: ErrorImage + +#密码加密传输,前端公钥加密,后端私钥解密 +rsa: + private_key: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMjhH5OmC7osPfdelXwkX1uTW1vuj8miZIU546Y6dy7TI2RF04rcW2eneBqrvF/8Ni1b+A+bqAJfMi01TDBmdyp+7vyZzUPRXv02HpI/ZM9dkQhv2m4VnTNnWOM0mY/7fJtDfLXhfDNmBMz7h57oDUFV0ESQtp5i4K7hlIVeezijAgMBAAECgYBVuPQfruksPnsHGB7UhjUHQD/pYEmN8zXQQJ7sLeD0Y3ej78RRaq268xVm1Eij8V4xRyD5kCRHNtaTwj3MHb3V68QC3amBR392yay4+S5ZOEPOjZ64hMSZWPezHbemLMjtUn1NR1k1aGfaiGPEk3npiXJHf9ZXU2GGglLJ50eP+QJBAPD3TTRtOVuTIPQS+m0PEeW6ALZDp3EONoqOMePuGLqj38QjwV+jGdxzA+Hhsf8oQo+QG2S3YPph09TFZc3dvj0CQQDVaY9TGeDyxf2DDL/oBFecIkixkV/AWRJb9CrDCZ8H9K1xWuEmhIW1pFJ+gmjbZccZQe/n1M+tRKq9DPaXsiBfAkANgE27GkOUdfHquwV9BtMh5AIWNEQ1eW5k5QK2mqiYDIaFHtu+2Ayi5W7aQSMQANl54cEnK38riD+uNEE3/6yhAkAN3ZfkTFAjNd3sv81QI8gVatzSPKG9+4uH0etdVKiyeaEzNjZerEmLrat2cL6jUo+HApO1ukvr9AQr2EXFQVt9AkEAoQcTx50AK6osp15kAoOQH5NV7TF2qoDbkNfp4xJReLlNpn9oPh2CNQOuVfna5gDQmkaEaJwwVuBvWN5RPrp2HA== + +# sa-token白名单配置 +security: + # 排除路径 + excludes: + # 认证 + - /auth/login + # apt屏幕操作 + - /mapMonitor/** + - /api/scheduleTask/** + - /setting/** + - /vehicle/** + - /webSocket/** + - /file/** + - /routeInfo/** + - /station/** + # 静态资源 + - /*.html + - /**/*.html + - /**/*.css + - /**/*.js \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/buss/buss.properties b/nl-web-app/src/main/resources/language/buss/buss.properties new file mode 100644 index 0000000..8f76588 --- /dev/null +++ b/nl-web-app/src/main/resources/language/buss/buss.properties @@ -0,0 +1,7 @@ +starting_point = 起点 +end_point = 终点 +successful = 操作成功! +failed = 操作失败! +latest = 已经是最新的! +param_is_null = 参数为空! +password_error = 账号或密码错误 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/buss/buss_en_US.properties b/nl-web-app/src/main/resources/language/buss/buss_en_US.properties new file mode 100644 index 0000000..d817150 --- /dev/null +++ b/nl-web-app/src/main/resources/language/buss/buss_en_US.properties @@ -0,0 +1,7 @@ +starting_point = Starting Point +end_point = End Point +successful = successful! +failed = Failed! +latest = Already up to date! +param_is_null = The parameter is empty! +password_error = Wrong account or password \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/buss/buss_zh_CN.properties b/nl-web-app/src/main/resources/language/buss/buss_zh_CN.properties new file mode 100644 index 0000000..8f76588 --- /dev/null +++ b/nl-web-app/src/main/resources/language/buss/buss_zh_CN.properties @@ -0,0 +1,7 @@ +starting_point = 起点 +end_point = 终点 +successful = 操作成功! +failed = 操作失败! +latest = 已经是最新的! +param_is_null = 参数为空! +password_error = 账号或密码错误 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/error/error.properties b/nl-web-app/src/main/resources/language/error/error.properties new file mode 100644 index 0000000..ac7746d --- /dev/null +++ b/nl-web-app/src/main/resources/language/error/error.properties @@ -0,0 +1,29 @@ +error_request_vehicle = 访问车体接口异常: +error_request_rcs = 访问RCS接口异常: +error_starting_mapping = 开始建图失败 +error_cut_manually = 切手动失败 +error_cut_automatically = 切自动失败 +error_end_mapping = 结束建图失败 +error_set_station = 设置站点失败 +error_get_Maps = 获取地图列表失败 +error_deploy_maps = 部署地图失败 +error_app_maps = 应用地图失败 +error_get_map_pack = 获取地图包失败 +error_map_pack_isNull = "地图包数据为空,扫描失败。请重新建图" +error_map_pgm = 地图PGM转换失败 +error_yaml_isNull = .YAML文件内容为空 +error_formatting_error = 格式错误 +error_parsing = YAML解析失败: +error_process_map_pack = 处理地图包数据失败: +error_png_convert_transparency = .png点云图将灰度图像转换为透明背景图像失败: +error_p5 = 不支持的PGM格式,仅支持P5二进制格式 +error_invalid_size = 无效的尺寸格式 +error_pgm_parse = PGM解析错误: +error_synchronized_map = 同步地图失败 +error_relocate = 重定位指令下发失败 +error_restart = 车体程序重启失败 +error_abandon_mapping = 放弃建图失败 +error_auto_back = 自动返回上一个点失败 +error_restart_system = 重启系统失败 +error_initializing_system = 初始化底层系统失败 +error_set_forkLegs= 操作叉腿避障失败 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/error/error_en_US.properties b/nl-web-app/src/main/resources/language/error/error_en_US.properties new file mode 100644 index 0000000..96d4e2e --- /dev/null +++ b/nl-web-app/src/main/resources/language/error/error_en_US.properties @@ -0,0 +1,28 @@ +error_request_vehicle = Abnormal access to the vehicle body interface +error_request_rcs = Accessing the RCS interface is abnormal +error_starting_mapping = Failed to start mapping +error_cut_manually = Cut manual failure +error_cut_automatically = Cut automatically fails +error_end_mapping = End mapping failed +error_set_station = Setting up the site failed +error_get_Maps = Failed to get the map list +error_deploy_maps = Deploying the map failed +error_app_maps = Applying the map failed +error_get_map_pack = Failed to get the map package +error_map_pack_isNull = The map package data is empty and the scan fails. Please rebuild the map +error_map_pgm = Map PGM conversion failed +error_yaml_isNull = .yaml file content is empty +error_parsing = YAML parsing failed: +error_process_map_pack = Failed to process map packet data: +error_png_convert_transparency = Converting a grayscale image to a transparent background image .png a point cloud plot fails: +error_p5 = PGM format is not supported, only P5 binary format is supported +error_invalid_size = Invalid size format +error_pgm_parse = PGM parsing error: +error_synchronized_map = Syncing maps failed +error_relocate = The relocation instruction failed to be issued +error_restart = The body program restarts failed +error_abandon_mapping = Abandoned mapping failed +error_auto_back = Automatically returning to the previous point failed +error_restart_system = Rebooting the system failed +error_initializing_system = Initializing the underlying system failed +error_set_forkLegs= The operation of the fork leg to avoid obstacles failed \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/error/error_zh_CN.properties b/nl-web-app/src/main/resources/language/error/error_zh_CN.properties new file mode 100644 index 0000000..438c3c3 --- /dev/null +++ b/nl-web-app/src/main/resources/language/error/error_zh_CN.properties @@ -0,0 +1,28 @@ +error_request_vehicle = 访问车体接口异常 +error_request_rcs = 访问RCS接口异常 +error_starting_mapping = 开始建图失败 +error_cut_manually = 切手动失败 +error_cut_automatically = 切自动失败 +error_end_mapping = 结束建图失败 +error_set_station = 设置站点失败 +error_get_Maps = 获取地图列表失败 +error_deploy_maps = 部署地图失败 +error_app_maps = 应用地图失败 +error_get_map_pack = 获取地图包失败 +error_map_pack_isNull = "地图包数据为空,扫描失败。请重新建图" +error_map_pgm = 地图PGM转换失败 +error_yaml_isNull = .YAML文件内容为空 +error_parsing = YAML解析失败: +error_process_map_pack = 处理地图包数据失败: +error_png_convert_transparency = .png点云图将灰度图像转换为透明背景图像失败: +error_p5 = 不支持的PGM格式,仅支持P5二进制格式 +error_invalid_size = 无效的尺寸格式 +error_pgm_parse = PGM解析错误: +error_synchronized_map = 同步地图失败 +error_relocate = 重定位指令下发失败 +error_restart = 车体程序重启失败 +error_abandon_mapping = 放弃建图失败 +error_auto_back = 自动返回上一个点失败 +error_restart_system = 重启系统失败 +error_initializing_system = 初始化底层系统失败 +error_set_forkLegs= 操作叉腿避障失败 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/task/task.properties b/nl-web-app/src/main/resources/language/task/task.properties new file mode 100644 index 0000000..2b35d59 --- /dev/null +++ b/nl-web-app/src/main/resources/language/task/task.properties @@ -0,0 +1,5 @@ +task_Id_isNull=任务不存在!【{0}】 +task_Is_exist=当前有正在执行中的任务! +task_Is_not_exist=当前没有任务在执行中! +not_return_point = 没有返回点! +task_cannot_be_enforced = 任务链操作类型无法执行,请重新选择 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/task/task_en_US.properties b/nl-web-app/src/main/resources/language/task/task_en_US.properties new file mode 100644 index 0000000..81dc72b --- /dev/null +++ b/nl-web-app/src/main/resources/language/task/task_en_US.properties @@ -0,0 +1,5 @@ +task_Id_isNull=The task with the task code of {0} was not found +task_Is_exist=There are tasks in progress! +task_Is_not_exist=No tasks are currently in progress! +not_return_point = There is no return point! +task_cannot_be_enforced = The task chain operation type cannot be executed, please select it again \ No newline at end of file diff --git a/nl-web-app/src/main/resources/language/task/task_zh_CN.properties b/nl-web-app/src/main/resources/language/task/task_zh_CN.properties new file mode 100644 index 0000000..0c367b8 --- /dev/null +++ b/nl-web-app/src/main/resources/language/task/task_zh_CN.properties @@ -0,0 +1,5 @@ +task_Id_isNull=未找到任务编码为{0}的任务 +task_Is_exist=当前有正在执行中的任务! +task_Is_not_exist=当前没有任务在执行中! +not_return_point = 没有返回点! +task_cannot_be_enforced = 任务链操作类型无法执行,请重新选择 \ No newline at end of file diff --git a/nl-web-app/src/main/resources/logback-spring.xml b/nl-web-app/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..493c4a4 --- /dev/null +++ b/nl-web-app/src/main/resources/logback-spring.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + INFO + + + ${log.pattern} + ${log.charset} + + + + + + + + + + + ${LOG_HOME}/root/%d{yyyy-MM-dd}.%i.log + + 15 + + 20MB + + 1GB + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + ${log.charset} + + + + + + + + + + + + + + + + + + + + + 0 + 256 + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0a5d81a..d5a0172 100644 --- a/pom.xml +++ b/pom.xml @@ -157,7 +157,35 @@ cn.hutool hutool-all - 5.8.25 + 5.8.22 + + + + + com.alibaba + fastjson + 1.2.37 + + + + + org.springframework.boot + spring-boot-starter-validation + 3.0.0 + + + + + org.springframework.boot + spring-boot-starter-websocket + 3.2.1 + + + + + org.springframework.boot + spring-boot-starter-aop + 3.2.1