[add] 新增无人机模块后端项目

[refactor] 重构后端项目
This commit is contained in:
lcj
2025-05-21 11:30:59 +08:00
parent 4c238435d8
commit dc1de34116
1699 changed files with 54361 additions and 325 deletions

View File

@ -0,0 +1,350 @@
package com.ruoyi.wayline.controller;
import com.ruoyi.system.domain.FlightPaths;
import com.ruoyi.system.domain.ManageDeviceDictionary;
import com.ruoyi.system.service.IFlightPathsService;
import com.ruoyi.system.service.IManageDeviceDictionaryService;
import com.ruoyi.wayline.domain.AddWaypointVo;
import com.ruoyi.wayline.domain.RenameVo;
import com.ruoyi.wayline.domain.WaypointData;
import com.ruoyi.wayline.utils.HttpResult;
import com.ruoyi.wayline.utils.MD5Util;
import com.ruoyi.wayline.waypoint.WayPointKmlProcessorModify;
import com.ruoyi.wayline.waypoint.WayPointWpmlProcessorModify;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.*;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.zip.*;
@Slf4j
@RestController
@Api(tags = "航线文件管理")
public class WaypointController {
@Resource
private IFlightPathsService flightPathsService;
@Resource
private IManageDeviceDictionaryService manageDeviceDictionaryService;
@Resource
private Environment environment;
private static final String UPLOAD_DIR = System.getProperty("user.dir") + "/upload";
// 工具方法:使用 flag 和 fileName 组合计算 MD5 值
private String calculateMD5(String flag, String fileName) {
String input = flag + fileName;
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : digest) sb.append(String.format("%02x", b));
log.info("MD5: {}", sb.toString());
return sb.toString();
}
// 工具方法:检查文件是否已存在并返回错误信息
private ResponseEntity<HttpResult> checkFileExistence(String fileName, String flag) {
FlightPaths flightPaths = new FlightPaths();
flightPaths.setFileName(fileName);
flightPaths.setFlag(flag);
List<FlightPaths> pathsList = flightPathsService.selectByCondition(flightPaths);
if (pathsList != null && !pathsList.isEmpty()) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("文件名重复,请重新命名");
return ResponseEntity.ok(httpResult);
}
return null;
}
private boolean checkFileExistenceWithBool(String fileName, String flag) {
FlightPaths flightPaths = new FlightPaths();
flightPaths.setFileName(fileName);
flightPaths.setFlag(flag);
List<FlightPaths> pathsList = flightPathsService.selectByCondition(flightPaths);
return pathsList != null && !pathsList.isEmpty();
}
@ApiOperation("导入航线文件")
@PostMapping("/dj/router/import")
public ResponseEntity<HttpResult> importWaypoint(@RequestParam("file") MultipartFile file, @RequestParam("flag") String flag) {
if (file.isEmpty()) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("文件为空");
return ResponseEntity.ok(httpResult);
}
try {
String fileName = file.getOriginalFilename();
ResponseEntity<HttpResult> existenceCheck = checkFileExistence(fileName, flag);
if (existenceCheck != null) return existenceCheck;
// 创建上传目录
Path uploadPath = Paths.get(UPLOAD_DIR);
Files.createDirectories(uploadPath);
byte[] fileBytes = file.getBytes();
String md5 = calculateMD5(flag, fileName); // 使用 flag 和 fileName 组合生成 MD5
String md5FileNameWithExtension = md5 + ".kmz";
Path serverPath = uploadPath.resolve(md5FileNameWithExtension);
Files.write(serverPath, fileBytes);
String downloadLink = buildDownloadLink(md5FileNameWithExtension);
saveFlightPath(fileName, flag, md5, downloadLink, true);
HttpResult httpResult = HttpResult.ok();
httpResult.setMessage("文件导入成功");
return ResponseEntity.ok(httpResult);
} catch (Exception e) {
log.error("文件保存失败: {}", e.getMessage());
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("保存失败");
return ResponseEntity.ok(httpResult);
}
}
private void saveFlightPath(String fileName, String flag, String md5, String fileUrl, boolean isImport) {
FlightPaths flightPath = new FlightPaths();
flightPath.setFileName(fileName);
flightPath.setFlag(flag);
flightPath.setFileMd5(md5);
flightPath.setFileUrl(fileUrl);
flightPath.setIsImport(isImport ? "true" : "false");
flightPath.setCreatedAt(new Date());
flightPath.setUpdatedAt(new Date());
flightPathsService.insertFlightPaths(flightPath);
}
private String buildDownloadLink(String md5FileNameWithExtension) throws IOException {
String ip = environment.getProperty("server.host", InetAddress.getLocalHost().getHostAddress());
int port = environment.getProperty("server.port", Integer.class, 8080);
return "http://" + ip + ":" + port + "/dj/router/download/" + md5FileNameWithExtension;
}
@ApiOperation("新增航线文件")
@PostMapping("/dj/router/add")
public ResponseEntity<HttpResult> addWaypoint(@RequestBody AddWaypointVo addWaypointVo) {
ResponseEntity<HttpResult> existenceCheck = checkFileExistence(addWaypointVo.getFilename(), addWaypointVo.getFlag());
if (existenceCheck != null) return existenceCheck;
FlightPaths flightPaths = new FlightPaths();
flightPaths.setFileName(addWaypointVo.getFilename());
flightPaths.setFlag(addWaypointVo.getFlag());
flightPaths.setIsImport("false");
flightPaths.setGlobalPointHeight(addWaypointVo.getGlobalPointHeight());
flightPaths.setCreatedAt(new Date());
flightPaths.setUpdatedAt(new Date());
// 获取飞机类型
String[] split = addWaypointVo.getRemark().split("-");
ManageDeviceDictionary manageDeviceDictionary = manageDeviceDictionaryService
.selectManageDeviceDictionaryByCondition(split[0], split[1], split[2]);
flightPaths.setDeviceType(manageDeviceDictionary.getDeviceName());
flightPathsService.insertFlightPaths(flightPaths);
return ResponseEntity.ok(HttpResult.ok());
}
@ApiOperation("根据参数追数据到加航线文件")
@PostMapping("/dj/router/waypoint")
public ResponseEntity<HttpResult> downloadWaypoint(@RequestBody WaypointData dataRequest) {
HttpResult httpResult = HttpResult.ok();
Map<String, Object> map = new HashMap<>();
String fileName = flightPathsService.selectFlightPathsById(Long.valueOf(dataRequest.getId())).getFileName();
Path uploadPath = Paths.get(UPLOAD_DIR);
try {
Files.createDirectories(uploadPath);
String md5FileName = calculateMD5(dataRequest.getFlag(), fileName); // 使用 flag 和 fileName 组合生成 MD5
String md5FileNameWithExtension = md5FileName + ".kmz";
Path serverPath = uploadPath.resolve(md5FileNameWithExtension);
// 日志:显示生成的文件路径
log.info("下载航线文件路径: {}", serverPath);
// 创建并压缩文件
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOut = new ZipOutputStream(byteArrayOutputStream)) {
byte[] file1 = new WayPointKmlProcessorModify().processKml(dataRequest, new Random().nextInt(9000) + 1000);
zipOut.putNextEntry(new ZipEntry("wpmz/template.kml"));
zipOut.write(file1);
zipOut.closeEntry();
byte[] file2 = new WayPointWpmlProcessorModify().processWpml(dataRequest, new Random().nextInt(9000) + 1000);
zipOut.putNextEntry(new ZipEntry("wpmz/waylines.wpml"));
zipOut.write(file2);
zipOut.closeEntry();
zipOut.finish();
Files.write(serverPath, byteArrayOutputStream.toByteArray());
}
// 构建下载链接并更新数据库
String downloadLink = buildDownloadLink(md5FileNameWithExtension);
map.put("downloadLink", downloadLink);
map.put("flag", true);
map.put("signature", md5FileName);
httpResult.setData(map);
httpResult.setMessage("生成航线文件并转存至服务器成功!");
// 更新数据库中的航线文件记录保存生成的MD5值
FlightPaths flightPaths = new FlightPaths();
flightPaths.setId(Long.valueOf(dataRequest.getId()));
flightPaths.setFileName(fileName);
flightPaths.setFileUrl(downloadLink);
flightPaths.setFileMd5(md5FileName); // 存储 MD5 值
flightPaths.setPhotoNum(Long.valueOf(dataRequest.getPhotoNum()));
flightPaths.setEstimateTime(dataRequest.getEstimateTime());
flightPaths.setType(dataRequest.getType());
flightPaths.setWaylineLen(dataRequest.getWaylineLen());
flightPaths.setPoints(dataRequest.getPoints());
flightPaths.setUpdatedAt(new Date());
flightPathsService.updateFlightPaths(flightPaths);
} catch (Exception e) {
httpResult = HttpResult.error();
httpResult.setMessage("生成航线文件并转存至服务器失败,原因:" + e.getMessage());
}
return ResponseEntity.ok(httpResult);
}
@ApiOperation("下载航线文件")
@GetMapping("/dj/router/download/{fileName}")
public ResponseEntity<byte[]> downloadFile(@PathVariable String fileName) {
Path filePath = Paths.get(UPLOAD_DIR, fileName);
if (!Files.exists(filePath)) {
return ResponseEntity.notFound().build();
}
try {
byte[] fileContent = Files.readAllBytes(filePath);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDisposition(ContentDisposition.builder("attachment").filename(fileName, StandardCharsets.UTF_8).build());
return ResponseEntity.ok().headers(headers).body(fileContent);
} catch (IOException e) {
log.error("文件下载失败, 原因: {}", e.getMessage());
return ResponseEntity.status(500).build();
}
}
@ApiOperation("复制航线文件")
@PostMapping("/dj/router/copy/{id}")
public ResponseEntity<HttpResult> copyWaypoint(@PathVariable Long id) {
FlightPaths originalFlightPaths = flightPathsService.selectFlightPathsById(id);
if (originalFlightPaths == null) return ResponseEntity.notFound().build();
String originalFileName = originalFlightPaths.getFileName();
String originalMd5 = originalFlightPaths.getFileMd5();
Path originalFilePath = Paths.get(UPLOAD_DIR, originalMd5 + ".kmz");
// 日志:显示待复制的原始文件路径
log.info("复制航线文件路径: {}", originalFilePath);
if (!Files.exists(originalFilePath)) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("请先生成航线文件再执行复制");
return ResponseEntity.ok(httpResult);
}
String newFileName = originalFileName + "(1)";
// 查询文件是否已存在
if (checkFileExistenceWithBool(newFileName, originalFlightPaths.getFlag())) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("航线文件" + newFileName + "已存在");
return ResponseEntity.ok(httpResult);
}
String newMd5 = calculateMD5(originalFlightPaths.getFlag(), newFileName);
Path newFilePath = Paths.get(UPLOAD_DIR, newMd5 + ".kmz");
try {
Files.copy(originalFilePath, newFilePath);
FlightPaths newFlightPaths = new FlightPaths();
newFlightPaths.setFileName(newFileName);
newFlightPaths.setFileUrl(buildDownloadLink(newMd5 + ".kmz"));
newFlightPaths.setFileMd5(newMd5);
newFlightPaths.setFlag(originalFlightPaths.getFlag());
newFlightPaths.setIsImport(originalFlightPaths.getIsImport());
newFlightPaths.setPoints(originalFlightPaths.getPoints());
newFlightPaths.setDeviceType(originalFlightPaths.getDeviceType());
newFlightPaths.setPhotoNum(originalFlightPaths.getPhotoNum());
newFlightPaths.setEstimateTime(originalFlightPaths.getEstimateTime());
newFlightPaths.setType(originalFlightPaths.getType());
newFlightPaths.setWaylineLen(originalFlightPaths.getWaylineLen());
newFlightPaths.setRemark(originalFlightPaths.getRemark());
newFlightPaths.setCreatedAt(new Date());
newFlightPaths.setUpdatedAt(new Date());
flightPathsService.insertFlightPaths(newFlightPaths);
HttpResult httpResult = HttpResult.ok();
httpResult.setMessage("复制航线文件成功!");
return ResponseEntity.ok(httpResult);
} catch (IOException e) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("复制航线文件失败, 原因:" + e.getMessage());
return ResponseEntity.ok(httpResult);
}
}
@ApiOperation("重命名航线文件")
@PostMapping("/dj/router/rename")
public ResponseEntity<HttpResult> renameWaypoint(@RequestBody RenameVo renameVo) {
FlightPaths flightPaths = flightPathsService.selectFlightPathsById(renameVo.getId());
if (flightPaths == null) return ResponseEntity.notFound().build();
// 如果文件名称和现在已有的名称相同则不进行任何处理
if (flightPaths.getFileName().equals(renameVo.getNewFileName())) {
HttpResult httpResult = HttpResult.ok();
return ResponseEntity.ok(httpResult);
}
if (checkFileExistenceWithBool(renameVo.getNewFileName(), flightPaths.getFlag())) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("航线文件" + renameVo.getNewFileName() + "已存在,请重新命名");
return ResponseEntity.ok(httpResult);
}
String newMd5 = calculateMD5(flightPaths.getFlag(), renameVo.getNewFileName());
String originalMd5 = flightPaths.getFileMd5();
Path originalFilePath = Paths.get(UPLOAD_DIR, originalMd5 + ".kmz");
Path newFilePath = Paths.get(UPLOAD_DIR, newMd5 + ".kmz");
try {
Files.move(originalFilePath, newFilePath);
flightPaths.setFileName(renameVo.getNewFileName());
flightPaths.setFileUrl(buildDownloadLink(newMd5 + ".kmz"));
flightPaths.setFileMd5(newMd5);
flightPaths.setGlobalPointHeight(flightPaths.getGlobalPointHeight());
flightPaths.setUpdatedAt(new Date());
flightPathsService.updateFlightPaths(flightPaths);
HttpResult httpResult = HttpResult.ok();
httpResult.setMessage("重命名航线文件成功!");
return ResponseEntity.ok(httpResult);
} catch (IOException e) {
HttpResult httpResult = HttpResult.error();
httpResult.setMessage("重命名航线文件失败, 原因: " + e.getMessage());
return ResponseEntity.ok(httpResult);
}
}
}