add:第一版测试版本,第二次联调。
This commit is contained in:
@@ -14,5 +14,5 @@ public class ScheduleAPISettingSpeedParam {
|
||||
* 速度,单位m/s
|
||||
*/
|
||||
@NotBlank(message = "速度不能为空")
|
||||
private Integer customSpeed;
|
||||
private double customSpeed;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.nl.api.task.api;
|
||||
|
||||
import org.nl.api.task.core.QRCodeTaskRequestParam;
|
||||
import org.nl.response.WebResponse;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/11
|
||||
@@ -28,4 +31,32 @@ public interface TaskAPI {
|
||||
* @return
|
||||
*/
|
||||
String taskOperationConfirm(String taskCode,String vehicleNumber);
|
||||
|
||||
/**
|
||||
* 二维码生成任务
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
WebResponse createTask(QRCodeTaskRequestParam param);
|
||||
|
||||
/**
|
||||
* 二维码生成任务
|
||||
* @param taskCode
|
||||
* @return
|
||||
*/
|
||||
WebResponse cancelTask(String taskCode);
|
||||
|
||||
/**
|
||||
* 二维码查询任务信息
|
||||
* @param room
|
||||
* @return
|
||||
*/
|
||||
WebResponse queryTaskInfoByRoom(String room);
|
||||
|
||||
/**
|
||||
* 二维码查询任务信息
|
||||
* @param taskCode
|
||||
* @return
|
||||
*/
|
||||
WebResponse taskOperationConfirm(String taskCode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.nl.api.task.core;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/23
|
||||
*/
|
||||
@Data
|
||||
public class QRCodeTaskRequestParam {
|
||||
|
||||
/**
|
||||
* 目标点
|
||||
*/
|
||||
@NotBlank(message = "目标点不能为空")
|
||||
private String destinations;
|
||||
|
||||
/**
|
||||
* 任务类型
|
||||
*/
|
||||
@NotBlank(message = "任务类型不能为空")
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 任务号
|
||||
*/
|
||||
private String task_code;
|
||||
|
||||
/**
|
||||
* 任务优先级
|
||||
*/
|
||||
private String priority;
|
||||
|
||||
/**
|
||||
* 指定车号
|
||||
*/
|
||||
private String vehicle_number;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.nl.map.controller;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.nl.logging.annotation.Log;
|
||||
import org.nl.map.service.MapService;
|
||||
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/18
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/mapinfo")
|
||||
public class MapInfoController {
|
||||
|
||||
@Resource
|
||||
private MapService mapService;
|
||||
|
||||
@GetMapping("/queryCurrentMapInfo")
|
||||
@Log("获取当前地图信息")
|
||||
public ResponseEntity<Object> queryCurrentMapInfo() {
|
||||
return new ResponseEntity<>(mapService.queryCurrentMapInfo(), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
51
nl-business-map/src/main/java/org/nl/map/entity/MapInfo.java
Normal file
51
nl-business-map/src/main/java/org/nl/map/entity/MapInfo.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package org.nl.map.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Data
|
||||
@TableName("map_info")
|
||||
public class MapInfo {
|
||||
|
||||
/**
|
||||
* 地图编号
|
||||
*/
|
||||
@TableId
|
||||
private String mapCode;
|
||||
|
||||
/**
|
||||
* 地图名称
|
||||
*/
|
||||
private String mapName;
|
||||
|
||||
/**
|
||||
* 地图图片地址
|
||||
*/
|
||||
private String mapImageAddress;
|
||||
|
||||
|
||||
/**
|
||||
* 点云图像素比例
|
||||
*/
|
||||
private Double resolution;
|
||||
|
||||
/**
|
||||
* 左下角x坐标
|
||||
*/
|
||||
private Double x;
|
||||
|
||||
/**
|
||||
* 左下角y坐标
|
||||
*/
|
||||
private Double y;
|
||||
|
||||
/**
|
||||
* 左下角 角度
|
||||
*/
|
||||
private Double angle;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.nl.map.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.nl.map.entity.MapInfo;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Mapper
|
||||
public interface MapInfoMapper extends BaseMapper<MapInfo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.nl.map.service;
|
||||
|
||||
import org.nl.response.WebResponse;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
public interface MapService {
|
||||
WebResponse queryCurrentMapInfo();
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package org.nl.map.service.impl;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.nl.map.entity.MapInfo;
|
||||
import org.nl.map.mapper.MapInfoMapper;
|
||||
import org.nl.map.service.MapService;
|
||||
import org.nl.map.station.entity.Station;
|
||||
import org.nl.map.station.mapper.StationMapper;
|
||||
import org.nl.response.WebResponse;
|
||||
import org.nl.util.FileProperties;
|
||||
import org.nl.util.URLConstant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MapServiceImpl implements MapService {
|
||||
|
||||
@Resource
|
||||
private StationMapper stationMapper;
|
||||
|
||||
@Resource
|
||||
private MapInfoMapper mapInfoMapper;
|
||||
|
||||
@Resource
|
||||
private FileProperties properties;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
getCurrentMapInfo();
|
||||
downloadImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载图片并保存
|
||||
*/
|
||||
public void downloadImage() {
|
||||
String filename = "currentMapImage.png";
|
||||
Path filePath = Paths.get(properties.getPath().getPath(), filename);
|
||||
|
||||
try {
|
||||
// 确保目录存在
|
||||
createDirectoryIfNotExists();
|
||||
|
||||
// 发送请求
|
||||
HttpResponse response = HttpRequest.get("http://"+ URLConstant.SCHEDULE_IP_PORT+"/maps/current/image/file")
|
||||
.header("Accept", "image/png")
|
||||
.header("User-Agent", "Hutool-HTTP")
|
||||
.timeout(30000)
|
||||
.execute();
|
||||
|
||||
if (response.getStatus() != HttpStatus.HTTP_OK) {
|
||||
throw new RuntimeException("HTTP请求失败,状态码: " + response.getStatus());
|
||||
}
|
||||
|
||||
// 获取 Content-Type 验证
|
||||
String contentType = response.header("Content-Type");
|
||||
log.info("Content-Type: {}", contentType);
|
||||
|
||||
// 保存文件
|
||||
byte[] bytes = response.bodyBytes();
|
||||
Files.write(filePath, bytes);
|
||||
|
||||
log.info("图片下载成功: {}, 大小: {} bytes",
|
||||
filePath.toAbsolutePath(), bytes.length);
|
||||
|
||||
mapInfoMapper.delete(new LambdaQueryWrapper<>());
|
||||
|
||||
MapInfo mapInfo = new MapInfo();
|
||||
mapInfo.setMapCode(filename);
|
||||
mapInfo.setMapName(filename);
|
||||
mapInfo.setMapImageAddress("/file/" + filename);
|
||||
mapInfoMapper.insert(mapInfo);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("下载图片失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建下载目录
|
||||
*/
|
||||
private void createDirectoryIfNotExists() throws IOException {
|
||||
Path dirPath = Paths.get(properties.getPath().getPath());
|
||||
if (!Files.exists(dirPath)) {
|
||||
Files.createDirectories(dirPath);
|
||||
log.info("创建下载目录: {}", dirPath.toAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public void getCurrentMapInfo(){
|
||||
try {
|
||||
|
||||
// 发送请求
|
||||
HttpResponse response = HttpRequest
|
||||
.get("http://"+ URLConstant.SCHEDULE_IP_PORT+"/maps/current")
|
||||
.execute();
|
||||
|
||||
if (response.getStatus() != HttpStatus.HTTP_OK) {
|
||||
throw new RuntimeException("HTTP请求失败,状态码: " + response.getStatus());
|
||||
}
|
||||
|
||||
// 清除站点数据
|
||||
stationMapper.delete(new LambdaQueryWrapper<>());
|
||||
|
||||
JSONArray pois = JSONArray.parseArray(JSONObject.parseObject(response.body()).getString("pois"));
|
||||
for (int i = 0; i < pois.size(); i++) {
|
||||
JSONObject poi = pois.getJSONObject(i);
|
||||
Station station = new Station();
|
||||
station.setStation_id(poi.getString("id"));
|
||||
station.setStation_code(poi.getString("name"));
|
||||
station.setStation_name(poi.getString("name"));
|
||||
station.setStation_type("Normal");
|
||||
JSONObject pose = poi.getJSONObject("pose");
|
||||
station.setX(pose.getDouble("x"));
|
||||
station.setY(pose.getDouble("y"));
|
||||
station.setAngle(pose.getDouble("yaw"));
|
||||
stationMapper.insert(station);
|
||||
}
|
||||
}catch (Exception e){
|
||||
log.info("获取当前地图信息失败:{}",e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse queryCurrentMapInfo() {
|
||||
|
||||
MapInfo mapInfo = mapInfoMapper.selectOne(new LambdaQueryWrapper<>(MapInfo.class)
|
||||
.eq(MapInfo::getMapCode, "currentMapImage.png")
|
||||
);
|
||||
return WebResponse.requestParamOk(mapInfo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.nl.map.station.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Data
|
||||
@TableName("station")
|
||||
public class Station {
|
||||
|
||||
@TableId
|
||||
private String station_id;
|
||||
|
||||
/**
|
||||
* 站点编码 对应地图上站点
|
||||
*/
|
||||
private String station_code;
|
||||
|
||||
/**
|
||||
* 站点别名
|
||||
*/
|
||||
private String station_name;
|
||||
|
||||
/**
|
||||
* 站点类型 (Normal 普通站点)
|
||||
*/
|
||||
private String station_type;
|
||||
|
||||
/**
|
||||
* x坐标
|
||||
*/
|
||||
private Double x;
|
||||
|
||||
/**
|
||||
* y坐标
|
||||
*/
|
||||
private Double y;
|
||||
|
||||
/**
|
||||
* 角度
|
||||
*/
|
||||
private Double angle;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.nl.map.station.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.nl.map.station.entity.Station;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Mapper
|
||||
public interface StationMapper extends BaseMapper<Station> {
|
||||
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class MapMonitorServiceImpl implements MapMonitorService {
|
||||
JSONObject jsonObject = jsonArray.getJSONObject(i);
|
||||
StationInfoDto stationInfoDto =new StationInfoDto();
|
||||
stationInfoDto.setId(jsonObject.getString("id"));
|
||||
stationInfoDto.setName(String.valueOf(i+1));
|
||||
stationInfoDto.setName(jsonObject.getString("name"));
|
||||
stationInfoDto.setType("1");
|
||||
JSONObject poseJson = jsonObject.getJSONObject("pose");
|
||||
stationInfoDto.setX(poseJson.getDouble("x"));
|
||||
|
||||
@@ -7,6 +7,7 @@ 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.nl.util.URLConstant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -22,7 +23,7 @@ public class ScheduleMapAPIProvider implements ScheduleMapAPI {
|
||||
log.info("获取当前地图中的所有POI");
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest.get("http://127.0.0.1:8011/api/core/artifact/v1/pois")
|
||||
result = HttpRequest.get(URLConstant.SCHEDULE_IP_PORT+"/maps/pois")
|
||||
.execute();
|
||||
log.info("获取当前地图中的所有POI响应结果:{}",result.body());
|
||||
}catch (Exception e){
|
||||
|
||||
@@ -9,6 +9,7 @@ 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.nl.util.URLConstant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ public class ScheduleSettingAPIProvider implements ScheduleSettingAPI {
|
||||
log.info("设置调度配送速度参数:{}", scheduleAPISettingSpeedParam);
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest.put("http://127.0.0.1:8011/system/motion/speed")
|
||||
result = HttpRequest.put(URLConstant.SCHEDULE_IP_PORT+"/system/motion/speed")
|
||||
.body(String.valueOf(JSONObject.toJSON(scheduleAPISettingSpeedParam)))
|
||||
.execute();
|
||||
log.info("设置调度配送速度响应结果:{}",result.body());
|
||||
@@ -45,7 +46,7 @@ public class ScheduleSettingAPIProvider implements ScheduleSettingAPI {
|
||||
log.info("设置调度充电参数:{}", scheduleAPISettingChargeParam);
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest.put("http://127.0.0.1:8011/system/charging/auto-threshold")
|
||||
result = HttpRequest.put(URLConstant.SCHEDULE_IP_PORT+"/system/charging/auto-threshold")
|
||||
.body(String.valueOf(JSONObject.toJSON(scheduleAPISettingChargeParam)))
|
||||
.execute();
|
||||
log.info("设置调度充电响应结果:{}",result.body());
|
||||
|
||||
@@ -11,6 +11,7 @@ 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.nl.util.URLConstant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@@ -55,7 +56,7 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest
|
||||
.post("http://127.0.0.1:8011/tasks/"+scheduleAPICreateTaskParam.getTask_code())
|
||||
.post(URLConstant.SCHEDULE_IP_PORT+"/tasks/"+scheduleAPICreateTaskParam.getTask_code())
|
||||
.body(String.valueOf(request_body))
|
||||
.execute();
|
||||
|
||||
@@ -75,7 +76,7 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest
|
||||
.post("http://127.0.0.1:8011/tasks/"+taskId+"/withdrawl")
|
||||
.post(URLConstant.SCHEDULE_IP_PORT+"/tasks/"+taskId+"/withdrawl")
|
||||
.body(String.valueOf(new JSONObject()))
|
||||
.execute();
|
||||
|
||||
@@ -95,7 +96,7 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest
|
||||
.get("http://127.0.0.1:8011/tasks/"+taskId)
|
||||
.get(URLConstant.SCHEDULE_IP_PORT+"/tasks/"+taskId)
|
||||
.execute();
|
||||
|
||||
log.info("查询调度任务状态响应结果:{}",result.body());
|
||||
@@ -114,7 +115,7 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest
|
||||
.post("http://127.0.0.1:8011/tasks/"+taskId+"/pause")
|
||||
.post(URLConstant.SCHEDULE_IP_PORT+"/tasks/"+taskId+"/pause")
|
||||
.body(String.valueOf(new JSONObject()))
|
||||
.execute();
|
||||
|
||||
@@ -134,7 +135,7 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
HttpResponse result = null;
|
||||
try {
|
||||
result = HttpRequest
|
||||
.post("http://127.0.0.1:8011/tasks/"+taskId+"/resume")
|
||||
.post(URLConstant.SCHEDULE_IP_PORT+"/tasks/"+taskId+"/resume")
|
||||
.body(String.valueOf(new JSONObject()))
|
||||
.execute();
|
||||
|
||||
@@ -162,14 +163,14 @@ public class ScheduleTaskAPIProvider implements ScheduleTaskAPI {
|
||||
|
||||
JSONObject request_body = new JSONObject();
|
||||
request_body.put("vehicleNumber", vehicleNumber);
|
||||
request_body.put("taskId",task_code);
|
||||
// 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")
|
||||
.post(URLConstant.SCHEDULE_IP_PORT+"/tasks/one-click/"+task_code)
|
||||
.body(String.valueOf(request_body))
|
||||
.execute();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ 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.nl.util.URLConstant;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -22,6 +23,8 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import static org.nl.util.URLConstant.SCHEDULE_IP_PORT;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/11/25
|
||||
@@ -75,10 +78,10 @@ public class VehicleServiceImpl implements VehicleService {
|
||||
|
||||
@Override
|
||||
public List<VehicleInfoDto> getAllVehicles() {
|
||||
String url = "http://127.0.0.1:8011/schedule/vehicles";
|
||||
String url = URLConstant.SCHEDULE_IP_PORT+"/vehicles";
|
||||
List<VehicleInfoDto> vehicles = new ArrayList<>();
|
||||
try {
|
||||
try (HttpResponse response = HttpRequest.get("http://127.0.0.1:8011/schedule/vehicles")
|
||||
try (HttpResponse response = HttpRequest.get(URLConstant.SCHEDULE_IP_PORT+"/vehicles")
|
||||
.setConnectionTimeout(10000)
|
||||
.setReadTimeout(10000)
|
||||
.execute()) {
|
||||
|
||||
@@ -73,8 +73,8 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
|
||||
throw new BadRequestException("修改配送速度,设置值不能为空");
|
||||
}
|
||||
ScheduleAPISettingSpeedParam scheduleAPISettingSpeedParam = new ScheduleAPISettingSpeedParam();
|
||||
// 前端值是0.1-1.0,传给调度需要转换成1-100。
|
||||
int customSpeed = (int) (Double.parseDouble(setting_value) * 100);
|
||||
// 前端值是0.1-1.0
|
||||
double customSpeed = Double.parseDouble(setting_value);
|
||||
scheduleAPISettingSpeedParam.setCustomSpeed(customSpeed);
|
||||
HttpResponse speedResult = scheduleSettingAPI.settingSpeed(scheduleAPISettingSpeedParam);
|
||||
if (speedResult == null || !speedResult.isOk()){
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.nl.sys.modular.qrcode.controller;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.nl.api.task.core.QRCodeTaskRequestParam;
|
||||
import org.nl.logging.annotation.Log;
|
||||
import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam;
|
||||
import org.nl.sys.modular.qrcode.service.QRCodeService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/22
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/qrcodeManager")
|
||||
public class QRCodeController {
|
||||
|
||||
@Resource
|
||||
private QRCodeService qrCodeService;
|
||||
|
||||
@PostMapping("/generateQRCode")
|
||||
@Log("生成二维码")
|
||||
public ResponseEntity<Object> generateQRCode(@RequestBody GenerateQRCodeParam generateQRCodeParam){
|
||||
return new ResponseEntity<>(qrCodeService.generateQRCode(generateQRCodeParam), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/queryTaskInfoByRoom")
|
||||
@Log("获取当前队列信息")
|
||||
public ResponseEntity<Object> queryTaskInfoByRoom(@RequestParam String room){
|
||||
return new ResponseEntity<>(qrCodeService.queryTaskInfoByRoom(room),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/createTask")
|
||||
@Log("二维码创建任务")
|
||||
public ResponseEntity<Object> createTask(@RequestBody QRCodeTaskRequestParam param){
|
||||
return new ResponseEntity<>(qrCodeService.createTask(param),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/cancelTask")
|
||||
@Log("二维码取消任务")
|
||||
public ResponseEntity<Object> cancelTask(@RequestParam String taskCode){
|
||||
return new ResponseEntity<>(qrCodeService.cancelTask(taskCode),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/taskOperationConfirm")
|
||||
@Log("二维码任务操作确认")
|
||||
public ResponseEntity<Object> taskOperationConfirm(@RequestParam String taskCode){
|
||||
return new ResponseEntity<>(qrCodeService.taskOperationConfirm(taskCode),HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.nl.sys.modular.qrcode.param;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/22
|
||||
*/
|
||||
@Data
|
||||
public class GenerateQRCodeParam {
|
||||
|
||||
/**
|
||||
* 房间号
|
||||
*/
|
||||
@NotBlank(message = "房间号不能为空")
|
||||
private String room;
|
||||
|
||||
/**
|
||||
* 二维码内容(文本/URL/WiFi配置等)
|
||||
*/
|
||||
@NotBlank(message = "二维码内容不能为空")
|
||||
private String data;
|
||||
|
||||
/**
|
||||
* 二维码宽度(像素)
|
||||
*/
|
||||
@NotBlank(message = "二维码宽度不能为空")
|
||||
private int width;
|
||||
|
||||
/**
|
||||
* 二维码高度(像素)
|
||||
*/
|
||||
@NotBlank(message = "二维码高度不能为空")
|
||||
private int height;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.nl.sys.modular.qrcode.service;
|
||||
|
||||
import org.nl.api.task.core.QRCodeTaskRequestParam;
|
||||
import org.nl.response.WebResponse;
|
||||
import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/22
|
||||
*/
|
||||
public interface QRCodeService {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
* @param generateQRCodeParam
|
||||
* @return
|
||||
*/
|
||||
WebResponse generateQRCode(GenerateQRCodeParam generateQRCodeParam);
|
||||
|
||||
/**
|
||||
* 二维码创建任务
|
||||
* @param qrCodeTaskRequestParam
|
||||
* @return
|
||||
*/
|
||||
WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam);
|
||||
|
||||
/**
|
||||
* 二维码创建任务
|
||||
* @return
|
||||
*/
|
||||
WebResponse cancelTask(String taskCode);
|
||||
|
||||
/**
|
||||
* 二维码房间是否有任务
|
||||
* @param room
|
||||
* @return
|
||||
*/
|
||||
WebResponse queryTaskInfoByRoom(String room);
|
||||
|
||||
/**
|
||||
* 二维码操作确认
|
||||
* @param taskCode
|
||||
* @return
|
||||
*/
|
||||
WebResponse taskOperationConfirm(String taskCode);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.nl.sys.modular.qrcode.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.nl.api.task.api.TaskAPI;
|
||||
import org.nl.api.task.core.QRCodeTaskRequestParam;
|
||||
import org.nl.exception.BadRequestException;
|
||||
import org.nl.response.WebResponse;
|
||||
import org.nl.sys.modular.qrcode.param.GenerateQRCodeParam;
|
||||
import org.nl.sys.modular.qrcode.service.QRCodeService;
|
||||
import org.nl.util.FileProperties;
|
||||
import org.nl.util.QRCodeUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/22
|
||||
*/
|
||||
@Service
|
||||
public class QRCodeServiceImpl implements QRCodeService {
|
||||
|
||||
@Resource
|
||||
private FileProperties fileProperties;
|
||||
|
||||
@Resource
|
||||
private TaskAPI taskAPI;
|
||||
|
||||
@Override
|
||||
public WebResponse generateQRCode(GenerateQRCodeParam param) {
|
||||
String result = QRCodeUtil.generateQRCode(param.getData(), param.getWidth(),
|
||||
param.getHeight(),fileProperties.getPath().getQrcode(),param.getRoom()+".png");
|
||||
if (StrUtil.isBlank(result)){
|
||||
throw new BadRequestException("生成二维码失败");
|
||||
}
|
||||
return WebResponse.requestOk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam) {
|
||||
taskAPI.createTask(qrCodeTaskRequestParam);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse cancelTask(String taskCode) {
|
||||
return taskAPI.cancelTask(taskCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse queryTaskInfoByRoom(String room) {
|
||||
return taskAPI.queryTaskInfoByRoom(room);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse taskOperationConfirm(String taskCode) {
|
||||
return taskAPI.taskOperationConfirm(taskCode);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.nl.task.provider;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -8,10 +9,15 @@ 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.api.task.core.QRCodeTaskRequestParam;
|
||||
import org.nl.enums.ScheduleTaskReportStatusEnum;
|
||||
import org.nl.exception.BadRequestException;
|
||||
import org.nl.response.WebResponse;
|
||||
import org.nl.task.entity.Task;
|
||||
import org.nl.task.enums.TaskSourceEnum;
|
||||
import org.nl.task.enums.TaskStatusEnum;
|
||||
import org.nl.task.param.CancelTaskRequestParam;
|
||||
import org.nl.task.param.CreateTaskRequestParam;
|
||||
import org.nl.task.service.TaskService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -54,7 +60,7 @@ public class TaskAPIProvider implements TaskAPI {
|
||||
@Override
|
||||
public String taskOperationConfirm(String taskCode,String vehicleNumber) {
|
||||
Task task = this.queryCurrentTaskByVehicleNumber(vehicleNumber);
|
||||
if (ObjectUtil.isEmpty(task)){
|
||||
if (task == null || BeanUtil.isEmpty(task)){
|
||||
log.info("任务操作确认失败,任务不存在");
|
||||
return null;
|
||||
}
|
||||
@@ -64,4 +70,38 @@ public class TaskAPIProvider implements TaskAPI {
|
||||
}
|
||||
return task.getVehicleReportStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse createTask(QRCodeTaskRequestParam qrCodeTaskRequestParam) {
|
||||
CreateTaskRequestParam param = BeanUtil.toBean(qrCodeTaskRequestParam, CreateTaskRequestParam.class);
|
||||
return taskService.createTask(param, TaskSourceEnum.QRCODE.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse cancelTask(String taskCode) {
|
||||
CancelTaskRequestParam param = new CancelTaskRequestParam();
|
||||
param.setTask_code(taskCode);
|
||||
return taskService.cancelTask(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse queryTaskInfoByRoom(String room) {
|
||||
// 获取当前存在的任务
|
||||
List<Task> taskList = taskService.queryCurrentTaskInfo();
|
||||
// 根据房间号查找当前任务中是否存在
|
||||
Task currentTask = taskList.stream().filter(task -> room.equals(task.getDestinations()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
if (ObjectUtil.isNotEmpty(currentTask)){
|
||||
jsonObject.put("currentTaskInfo", currentTask);
|
||||
}
|
||||
jsonObject.put("currentTaskCount", taskList.size());
|
||||
return WebResponse.requestParamOk(jsonObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResponse taskOperationConfirm(String taskCode) {
|
||||
return taskService.taskOperationConfirm(taskCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ public interface TaskService extends IService<Task>{
|
||||
WebResponse resumeTask(PauseAndResumeTaskParam pauseAndResumeTaskParam);
|
||||
|
||||
/**
|
||||
* 查询当前未完成的任务
|
||||
* 根据车号查询当前未完成的任务
|
||||
* @return WebResponse
|
||||
*/
|
||||
WebResponse queryNotFinishTaskInfoByVehicleNumber(String vehicle_number);
|
||||
|
||||
/**
|
||||
* 查询当前未完成的任务
|
||||
* 根据车号查询当前未完成的任务
|
||||
* @return List<Task>
|
||||
*/
|
||||
List<Task> queryCurrentTaskInfoByVehicleNumber(String vehicle_number);
|
||||
@@ -64,4 +64,10 @@ public interface TaskService extends IService<Task>{
|
||||
* @return WebResponse
|
||||
*/
|
||||
WebResponse oneClickOperation(OneClickOperationRequestParam oneClickOperationRequestParam,String taskSource);
|
||||
|
||||
/**
|
||||
* 根据房间号查询当前任务信息
|
||||
* @return List<Task>
|
||||
*/
|
||||
List<Task> queryCurrentTaskInfo();
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -56,8 +57,16 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper,Task> implements Tas
|
||||
@Resource
|
||||
private ScheduleTaskAPI scheduleTaskAPI;
|
||||
|
||||
/**
|
||||
* <车号,List<任务信息>>
|
||||
*/
|
||||
private ConcurrentHashMap<String,List<Task>> taskInfoList = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 当前任务集合
|
||||
*/
|
||||
private List<Task> currentTaskList = new CopyOnWriteArrayList<>();
|
||||
|
||||
/**
|
||||
* 定时查询车辆任务状态(每秒执行)
|
||||
*/
|
||||
@@ -67,51 +76,56 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper,Task> implements Tas
|
||||
List<Task> taskList = taskMapper.selectList(new LambdaQueryWrapper<>(Task.class)
|
||||
.lt(Task::getStatus,TaskStatusEnum.FINISHED.getCode())
|
||||
);
|
||||
currentTaskList.clear();
|
||||
currentTaskList = taskList;
|
||||
taskInfoList.clear();
|
||||
//根据车辆编号分类 车辆任务队列。
|
||||
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"));
|
||||
if (!taskList.isEmpty()) {
|
||||
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("更新任务状态成功");
|
||||
}
|
||||
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());
|
||||
log.error("更新任务状态失败: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,4 +301,9 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper,Task> implements Tas
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Task> queryCurrentTaskInfo() {
|
||||
return currentTaskList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,5 +59,17 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- zxing -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- zxing -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.nl.config;
|
||||
|
||||
import org.nl.util.FileProperties;
|
||||
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.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
@@ -14,6 +16,24 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@EnableWebMvc
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
/** 文件配置 */
|
||||
private final FileProperties properties;
|
||||
|
||||
public CorsConfig(FileProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
FileProperties.ElPath path = properties.getPath();
|
||||
String qrcodeUtl = "file:" + path.getQrcode().replace("\\","/");
|
||||
String pathUtl = "file:" + path.getPath().replace("\\","/");
|
||||
registry.addResourceHandler("/qrcode/**").addResourceLocations(qrcodeUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
|
||||
45
nl-common/src/main/java/org/nl/util/FileProperties.java
Normal file
45
nl-common/src/main/java/org/nl/util/FileProperties.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package org.nl.util;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/18
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "file")
|
||||
public class FileProperties {
|
||||
|
||||
/** 文件大小限制 */
|
||||
private Long maxSize;
|
||||
|
||||
/** 头像大小限制 */
|
||||
private Long avatarMaxSize;
|
||||
|
||||
private ElPath mac;
|
||||
|
||||
private ElPath linux;
|
||||
|
||||
private ElPath windows;
|
||||
|
||||
public ElPath getPath(){
|
||||
String os = System.getProperty("os.name");
|
||||
if(os.toLowerCase().startsWith("win")) {
|
||||
return windows;
|
||||
} else if(os.toLowerCase().startsWith("mac")){
|
||||
return mac;
|
||||
}
|
||||
return linux;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ElPath{
|
||||
|
||||
private String path;
|
||||
|
||||
private String qrcode;
|
||||
}
|
||||
}
|
||||
73
nl-common/src/main/java/org/nl/util/QRCodeUtil.java
Normal file
73
nl-common/src/main/java/org/nl/util/QRCodeUtil.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package org.nl.util;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/22
|
||||
*/
|
||||
@Slf4j
|
||||
public class QRCodeUtil {
|
||||
|
||||
/**
|
||||
* 生成二维码图片并保存到指定路径
|
||||
*
|
||||
* @param data 二维码内容(文本/URL/WiFi配置等)
|
||||
* @param width 二维码宽度(像素)
|
||||
* @param height 二维码高度(像素)
|
||||
* @param filePath 保存路径(需包含.png后缀)
|
||||
* @return 生成的二维码文件路径,失败时返回null
|
||||
*/
|
||||
public static String generateQRCode(String data, int width, int height, String filePath,String fileName) {
|
||||
|
||||
try {
|
||||
//1.设置二维码生成参数
|
||||
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||
// 支持中文等特殊字符
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
// 30%容错率
|
||||
hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.H);
|
||||
// 二维码边框空白宽度
|
||||
hints.put(EncodeHintType.MARGIN, 1);
|
||||
|
||||
//2.生成二维码矩阵数据
|
||||
MultiFormatWriter writer = new MultiFormatWriter();
|
||||
BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height, hints);
|
||||
|
||||
//3.转换为图像对象
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
image.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
// 确保目录存在
|
||||
File outputDir = new File(filePath);
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.mkdirs();
|
||||
log.info("目录已创建: {}", outputDir.getAbsolutePath());
|
||||
}
|
||||
//4.保存为PNG文件
|
||||
File qrCodeFile = new File(filePath, fileName);
|
||||
ImageIO.write(image, "png", qrCodeFile);
|
||||
log.info("二维码已生成并保存到: {}", filePath);
|
||||
return filePath;
|
||||
} catch (Exception e) {
|
||||
log.info("生成二维码错误:{}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
nl-common/src/main/java/org/nl/util/URLConstant.java
Normal file
13
nl-common/src/main/java/org/nl/util/URLConstant.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.nl.util;
|
||||
|
||||
/**
|
||||
* @author dsh
|
||||
* 2025/12/16
|
||||
*/
|
||||
public class URLConstant {
|
||||
|
||||
/**
|
||||
* 调度IP及端口
|
||||
*/
|
||||
public static String SCHEDULE_IP_PORT = "127.0.0.1:55200";
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
server:
|
||||
# 端口
|
||||
port: 8081
|
||||
port: 8011
|
||||
tomcat:
|
||||
max-swallow-size: 100MB
|
||||
spring:
|
||||
@@ -64,13 +64,13 @@ spring:
|
||||
file:
|
||||
mac:
|
||||
path: ~/file/
|
||||
avatar: ~/avatar/
|
||||
qrcode: ~/avatar/
|
||||
linux:
|
||||
path: /home/eladmin/file/
|
||||
avatar: /home/eladmin/avatar/
|
||||
qrcode: /home/eladmin/qrcode/
|
||||
windows:
|
||||
path: C:\eladmin\file\
|
||||
avatar: C:\eladmin\avatar\
|
||||
qrcode: C:\eladmin\qrcode\
|
||||
# 文件大小 /M
|
||||
maxSize: 100
|
||||
avatarMaxSize: 5
|
||||
|
||||
@@ -5,12 +5,15 @@ server:
|
||||
max-swallow-size: 100MB
|
||||
spring:
|
||||
datasource:
|
||||
dynamic:
|
||||
datasource:
|
||||
master:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/nl_frobot?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
|
||||
username: root
|
||||
password: nlrobot
|
||||
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
|
||||
# 最小连接数
|
||||
@@ -57,13 +60,13 @@ spring:
|
||||
file:
|
||||
mac:
|
||||
path: ~/file/
|
||||
avatar: ~/avatar/
|
||||
qrcode: ~/qrcode/
|
||||
linux:
|
||||
path: /home/fr1511b/nlapt15e/file/
|
||||
avatar: /home/fr1511b/nlapt15e/avatar/
|
||||
path: /home/pi/nl_robot/map/
|
||||
qrcode: /home/pi/nl_robot/qrcode/
|
||||
windows:
|
||||
path: C:\eladmin\file\
|
||||
avatar: C:\eladmin\avatar\
|
||||
path: C:\eladmin\file\currentMap\
|
||||
qrcode: C:\eladmin\qrcode\currentMap\
|
||||
# 文件大小 /M
|
||||
maxSize: 100
|
||||
avatarMaxSize: 5
|
||||
|
||||
@@ -7,7 +7,7 @@ spring:
|
||||
basename: language/task/task,language/error/error,language/buss/buss
|
||||
encoding: UTF-8
|
||||
profiles:
|
||||
active: dev
|
||||
active: prod
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
|
||||
|
||||
14
pom.xml
14
pom.xml
@@ -139,6 +139,20 @@
|
||||
<version>3.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- zxing -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- zxing -->
|
||||
<dependency>
|
||||
<groupId>com.google.zxing</groupId>
|
||||
<artifactId>javase</artifactId>
|
||||
<version>3.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- easy-trans-mybatis-plus-extend -->
|
||||
<dependency>
|
||||
<groupId>com.fhs-opensource</groupId>
|
||||
|
||||
Reference in New Issue
Block a user