commit f104f23c66c66078786998e0a486781a1c2f4c1d Author: shiyi Date: Thu Jun 12 18:19:02 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9454df7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +README.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +/log diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..cffb029 --- /dev/null +++ b/pom.xml @@ -0,0 +1,120 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.16 + + + com.htfp.service + usm + 0.0.1-SNAPSHOT + pom + htfp-uav-state-manager + htfp-uav-state-manager + + + 1.8 + UTF-8 + UTF-8 + 2.7.6 + + + + + usm-app + usm-dao + usm-common + usm-biz + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + + pom + import + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.3.0 + + + + com.htfp.service + usm-common + 0.0.1-SNAPSHOT + + + com.htfp.service + usm-dao + 0.0.1-SNAPSHOT + + + com.htfp.service + usm-biz + 0.0.1-SNAPSHOT + + + + + + + + org.projectlombok + lombok + true + + + org.junit.jupiter + junit-jupiter-api + test + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + com.htfp.service.ssm.HtfpUavStateManagerApplication + true + + + + repackage + + repackage + + + + + + + + diff --git a/usm-app/pom.xml b/usm-app/pom.xml new file mode 100644 index 0000000..a319625 --- /dev/null +++ b/usm-app/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + + com.htfp.service + usm + 0.0.1-SNAPSHOT + + + com.htfp.service + usm-app + jar + usm-app + usm-app + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + jakarta.validation + jakarta.validation-api + + + + com.htfp.service + usm-biz + + + com.htfp.service + usm-common + compile + + + + diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/UsmAppApplication.java b/usm-app/src/main/java/com/htfp/service/usm/app/UsmAppApplication.java new file mode 100644 index 0000000..f822e49 --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/UsmAppApplication.java @@ -0,0 +1,17 @@ +package com.htfp.service.usm.app; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(value = {"com.htfp.service.usm"}) +@MapperScan(value = "com.htfp.service.usm.dao.mapper") +public class UsmAppApplication { + + public static void main(String[] args) { + SpringApplication.run(UsmAppApplication.class, args); + } + +} diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/config/AppCorsFilter.java b/usm-app/src/main/java/com/htfp/service/usm/app/config/AppCorsFilter.java new file mode 100644 index 0000000..418166d --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/config/AppCorsFilter.java @@ -0,0 +1,37 @@ +package com.htfp.service.usm.app.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * @author : shi_y + * @description : 跨域配置 + * @createTime : 2025-06-09 18:21 + **/ +@Configuration +public class AppCorsFilter { + @Bean + public CorsFilter corsFilter() { + // 1.创建 CORS 配置对象 + CorsConfiguration config = new CorsConfiguration(); + // 支持域 + config.addAllowedOriginPattern("*"); + // 是否发送 Cookie + config.setAllowCredentials(true); + // 支持请求方式 + config.addAllowedMethod("*"); + // 允许的原始请求头部信息 + config.addAllowedHeader("*"); + // 暴露的头部信息 + config.addExposedHeader("*"); + // 2.添加地址映射 + UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource(); + corsConfigurationSource.registerCorsConfiguration("/**", config); + // 3.返回 CorsFilter 对象 + return new CorsFilter(corsConfigurationSource); + } +} + diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/LabelController.java b/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/LabelController.java new file mode 100644 index 0000000..e2548a6 --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/LabelController.java @@ -0,0 +1,76 @@ +package com.htfp.service.usm.app.controller.manage; + +import com.htfp.service.usm.app.model.BaseHttpResponse; +import com.htfp.service.usm.biz.model.request.BatchDeleteLabelRequest; +import com.htfp.service.usm.biz.model.request.InsertLabelRequest; +import com.htfp.service.usm.biz.model.request.UpdateLabelRequest; +import com.htfp.service.usm.biz.model.response.LabelVO; +import com.htfp.service.usm.biz.service.ILabelService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +/** + * @author : shi_y + * @description : 标签管理 + * @createTime : 2025-06-12 09:00 + **/ + +/** + * 标签管理 + */ +@Slf4j +@RestController +@RequestMapping("/manage/label") +public class LabelController { + @Resource + private ILabelService labelService; + + /** + * 查询所有标签 + */ + @RequestMapping(value = "/queryAllLabels", method = RequestMethod.POST) + public BaseHttpResponse> queryAllLabels() { + List labelList= labelService.queryAllLabels(); + log.info("查询所有标签, 结果数量: {}", labelList.size()); + return BaseHttpResponse.success(labelList); + } + + /** + * 新增标签 + */ + @RequestMapping(value = "/insertLabel", method = RequestMethod.POST) + public BaseHttpResponse insertLabel(@RequestBody @Valid InsertLabelRequest insertLabelRequest) { + log.info("新增标签: {}", insertLabelRequest); + Integer id = labelService.insertLabel(insertLabelRequest); + return BaseHttpResponse.success(id); + } + + /** + * 批量删除标签 + */ + @RequestMapping(value = "/batchDeleteLabel", method = RequestMethod.POST) + public BaseHttpResponse batchDeleteLabel(@RequestBody @Valid BatchDeleteLabelRequest batchDeleteLabelRequest) { + List labelIdList = batchDeleteLabelRequest.getLabelIdList(); + log.info("批量删除标签: {}", labelIdList); + labelService.batchDeleteLabels(labelIdList); + return BaseHttpResponse.success(); + } + + /** + * 修改标签 + */ + @RequestMapping(value = "/updateLabel", method = RequestMethod.POST) + public BaseHttpResponse updateLabel(@RequestBody @Validated UpdateLabelRequest updateLabelRequest) { + log.info("修改标签: {}", updateLabelRequest); + labelService.updateLabel(updateLabelRequest); + return BaseHttpResponse.success(); + } +} diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/UavInfoController.java b/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/UavInfoController.java new file mode 100644 index 0000000..d85bf24 --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/controller/manage/UavInfoController.java @@ -0,0 +1,70 @@ +package com.htfp.service.usm.app.controller.manage; + +import com.htfp.service.usm.app.model.BaseHttpResponse; + +import com.htfp.service.usm.biz.model.request.InsertUavInfoRequest; +import com.htfp.service.usm.biz.model.request.QueryUavInfoByIdRequest; + +import com.htfp.service.usm.biz.service.IUavInfoService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-09 18:17 + **/ + +/** + * 无人机信息管理 + */ +@Slf4j +@RestController +@RequestMapping("/manage/uav") +public class UavInfoController { + @Autowired + private IUavInfoService uavInfoService; + + /** + * 根据id查询uav信息 + * @param insertUavInfoRequest 录入uav信息请求体 + * @return 录入uav信息响应体 + */ + @RequestMapping(value = "/queryUavInfoById", method = RequestMethod.POST) + public BaseHttpResponse queryUavInfoById(@RequestBody @Validated QueryUavInfoByIdRequest insertUavInfoRequest) { + log.info("新增无人机: {}", insertUavInfoRequest); + Integer uavId = insertUavInfoRequest.getUavId(); + uavInfoService.queryUavInfoById(uavId); + return BaseHttpResponse.success(); + } + + // /** + // * 根据id查询uav信息 + // * @param insertUavInfoRequest 录入uav信息请求体 + // * @return 录入uav信息响应体 + // */ + // @RequestMapping(value = "/queryUavInfoBySn", method = RequestMethod.POST) + // public BaseHttpResponse queryUavInfoBySn(@RequestBody @Validated QueryUavInfoBySnRequest insertUavInfoRequest) { + // log.info("新增无人机: {}", insertUavInfoRequest); + // return BaseHttpResponse.success(); + // } + // + // + /** + * 录入uav信息 + * @param insertUavInfoRequest 录入uav信息请求体 + * @return 录入uav信息响应体 + */ + @RequestMapping(value = "/insertUavInfo", method = RequestMethod.POST) + public BaseHttpResponse insertUavInfo(@RequestBody InsertUavInfoRequest insertUavInfoRequest) { + log.info("新增无人机: {}", insertUavInfoRequest); + uavInfoService.insertUavInfo(insertUavInfoRequest); + return BaseHttpResponse.success(); + } +} diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/handler/GlobalExceptionHandler.java b/usm-app/src/main/java/com/htfp/service/usm/app/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..9f29a1b --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/handler/GlobalExceptionHandler.java @@ -0,0 +1,94 @@ +package com.htfp.service.usm.app.handler; + +import com.htfp.service.usm.app.model.BaseHttpResponse; +import com.htfp.service.usm.biz.exception.BusinessException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StringUtils; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.ConstraintViolationException; +import java.sql.SQLException; +import java.util.stream.Collectors; + +import com.htfp.service.usm.common.enums.ErrorCodeEnum; +import org.springframework.web.method.HandlerMethod; + +/** + * @author : shi_y + * @description : 全局异常处理器 + * @createTime : 2025-06-11 11:33 + **/ +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + // 参数校验失败:@Valid/@Validated + @RequestBody + @ExceptionHandler(MethodArgumentNotValidException.class) + public BaseHttpResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HandlerMethod handlerMethod) { + StringBuilder errMsgBuilder = new StringBuilder(); + for (FieldError error : ex.getBindingResult().getFieldErrors()) { + errMsgBuilder + // .append(error.getField()) + // .append(": ") + .append(error.getDefaultMessage()).append("; "); + } + // 获取 controller 类名 + 方法名 + String beanName = handlerMethod.getBeanType().getName(); + String methodName = handlerMethod.getMethod().getName(); + String errMsg = errMsgBuilder.toString(); + log.warn("参数校验失败:\n Path: {} - {},\n 错误信息: {}", beanName, methodName, errMsg); + return BaseHttpResponse.fail(ErrorCodeEnum.PARAM_VALIDATION_ERROR, errMsg); + } + + // 参数校验失败:@Validated + @RequestParam / @PathVariable + @ExceptionHandler(ConstraintViolationException.class) + public BaseHttpResponse handleConstraintViolationException(ConstraintViolationException ex, HandlerMethod handlerMethod) { + String message = ex.getConstraintViolations() + .stream() + .map(v -> v.getPropertyPath() + ": " + v.getMessage()) + .collect(Collectors.joining("; ")); + String beanName = handlerMethod.getBeanType().getName(); + String methodName = handlerMethod.getMethod().getName(); + log.warn("路径参数校验失败:\n Path: {} - {},\n 错误信息: {}", beanName, methodName, message); + return BaseHttpResponse.fail(ErrorCodeEnum.PARAM_VALIDATION_ERROR, message); + } + + @ExceptionHandler(BusinessException.class) + public BaseHttpResponse handleBusinessException(BusinessException ex, HandlerMethod handlerMethod) { + ErrorCodeEnum codeEnum = ex.getErrorCodeEnum(); + String content = ex.getcontent(); + String finalMessage; + + String beanName = handlerMethod.getBeanType().getName(); + String methodName = handlerMethod.getMethod().getName(); + + BaseHttpResponse response; + if (!StringUtils.hasLength(content)) { + response = BaseHttpResponse.fail(codeEnum); + } else { + finalMessage = String.format("%s: %s", codeEnum.getDesc(), content); + response = BaseHttpResponse.fail(codeEnum, finalMessage); + } + log.warn("业务异常:\n Path: {} - {},\n 错误信息: {}", beanName, methodName, response); + return response; + } + + @ExceptionHandler(SQLException.class) + public BaseHttpResponse handleSQLException(SQLException ex, HandlerMethod handlerMethod) { + String beanName = handlerMethod.getBeanType().getName(); + String methodName = handlerMethod.getMethod().getName(); + + log.error("数据库异常:\n Path: {} - {},\n 错误信息: {}", beanName, methodName, ex.getMessage()); + return BaseHttpResponse.fail(ErrorCodeEnum.SQL_ERROR, "服务器内部错误,请联系管理员"); + } + // 系统异常兜底 + @ExceptionHandler(Exception.class) + public BaseHttpResponse handleSystemException(Exception ex, HttpServletRequest request) { + log.error("系统异常, path: {}, error: {}", request.getRequestURI(), ex.getMessage(), ex); + return BaseHttpResponse.fail(ErrorCodeEnum.SYSTEM_ERROR, ex.getMessage()); + } +} diff --git a/usm-app/src/main/java/com/htfp/service/usm/app/model/BaseHttpResponse.java b/usm-app/src/main/java/com/htfp/service/usm/app/model/BaseHttpResponse.java new file mode 100644 index 0000000..9026959 --- /dev/null +++ b/usm-app/src/main/java/com/htfp/service/usm/app/model/BaseHttpResponse.java @@ -0,0 +1,85 @@ +package com.htfp.service.usm.app.model; + + +import com.htfp.service.usm.common.enums.ErrorCodeEnum; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.ibatis.annotations.Select; + +/** + * @Author shi_y + * @Date 2025-06-11 + * @Description http响应基类, Controller的统一响应结果 + */ +@Data +public class BaseHttpResponse { + + private boolean success; + private Integer code; + private String message; + private T data; + + public BaseHttpResponse() { + } + + public BaseHttpResponse(boolean success, Integer code, String message, T data) { + this.success = success; + this.code = code; + this.message = message; + this.data = data; + } + + public BaseHttpResponse(boolean success, Integer code, String message) { + this.success = success; + this.code = code; + this.message = message; + } + + + public BaseHttpResponse(boolean success, ErrorCodeEnum errorCodeEnum) { + this.success = success; + this.code = errorCodeEnum.getCode(); + this.message = errorCodeEnum.getDesc(); + } + + + public BaseHttpResponse(boolean success, ErrorCodeEnum errorCodeEnum, T data) { + this.success = success; + this.code = errorCodeEnum.getCode(); + this.message = errorCodeEnum.getDesc(); + this.data = data; + } + + public BaseHttpResponse(boolean success, T data) { + this.success = success; + this.data = data; + } + + public BaseHttpResponse(boolean success) { + this.success = success; + } + + + public static BaseHttpResponse success() { + return new BaseHttpResponse<>(true, 0, "成功", null); + } + + public static BaseHttpResponse success(T data) { + return new BaseHttpResponse<>(true, 0, "成功", data); + } + + public static BaseHttpResponse fail(ErrorCodeEnum errorCodeEnum) { + return new BaseHttpResponse<>(false, errorCodeEnum); + } + + + public static BaseHttpResponse fail(ErrorCodeEnum errorCodeEnum, String msg) { + return new BaseHttpResponse<>(false, errorCodeEnum.getCode(), msg); + } + + public static BaseHttpResponse unknownError(T data) { + return new BaseHttpResponse<>(false, ErrorCodeEnum.UNKNOWN_ERROR, data); + } + +} diff --git a/usm-app/src/main/resources/application-test.yml b/usm-app/src/main/resources/application-test.yml new file mode 100644 index 0000000..8b6e3aa --- /dev/null +++ b/usm-app/src/main/resources/application-test.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/usm?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true + username: root + password: 1234 + driver-class-name: com.mysql.cj.jdbc.Driver +mybatis: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + mapper-locations: + - classpath*:com/htfp/service/dao/mapper/*.xml + type-aliases-package: com.htfp.service.usm.dao.model +logging: + level: + org.springframework.jdbc.support.JdbcTransactionManager: debug \ No newline at end of file diff --git a/usm-app/src/main/resources/application.yml b/usm-app/src/main/resources/application.yml new file mode 100644 index 0000000..5e15bf9 --- /dev/null +++ b/usm-app/src/main/resources/application.yml @@ -0,0 +1,29 @@ +spring: + application: + name: htfp-uav-state-manager + + datasource: + url: jdbc:mysql://127.0.0.1:3306/usm?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true + username: root + password: 1234 + driver-class-name: com.mysql.cj.jdbc.Driver + servlet: + multipart: + max-file-size: 10MB + max-request-size: 10MB +mybatis: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + mapper-locations: + - classpath*:com/htfp/service/dao/mapper/*.xml + +logging: + level: + org.springframework.jdbc.support.JdbcTransactionManager: debug + +#aliyun: +# oss: +# endpoint: "https://oss-cn-shanghai.aliyuncs.com" +# bucketName: "java-ai-test-sy" +# region: "cn-shanghai \ No newline at end of file diff --git a/usm-app/src/main/resources/logback.xml b/usm-app/src/main/resources/logback.xml new file mode 100644 index 0000000..37108ba --- /dev/null +++ b/usm-app/src/main/resources/logback.xml @@ -0,0 +1,33 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %magenta([%thread]) %cyan(%logger{36})-%msg%n + + + + + + + + ./log/usm-%d{yyyy-MM-dd}-%i.log + + 30 + + 10MB + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{25}-%msg%n + + + + + + + + + \ No newline at end of file diff --git a/usm-app/src/test/java/com/htfp/service/usm/app/UsmAppApplicationTests.java b/usm-app/src/test/java/com/htfp/service/usm/app/UsmAppApplicationTests.java new file mode 100644 index 0000000..9330295 --- /dev/null +++ b/usm-app/src/test/java/com/htfp/service/usm/app/UsmAppApplicationTests.java @@ -0,0 +1,13 @@ +package com.htfp.service.usm.app; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class UsmAppApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/usm-biz/pom.xml b/usm-biz/pom.xml new file mode 100644 index 0000000..f71587a --- /dev/null +++ b/usm-biz/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + com.htfp.service + usm + 0.0.1-SNAPSHOT + + + com.htfp.service + usm-biz + + + 8 + 8 + UTF-8 + + + + + com.htfp.service + usm-common + + + com.htfp.service + usm-dao + + + \ No newline at end of file diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/exception/BusinessException.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/exception/BusinessException.java new file mode 100644 index 0000000..77db7cc --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/exception/BusinessException.java @@ -0,0 +1,43 @@ +package com.htfp.service.usm.biz.exception; + +import com.htfp.service.usm.common.enums.ErrorCodeEnum; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 11:18 + **/ +public class BusinessException extends RuntimeException { + + private final ErrorCodeEnum errorCodeEnum; + private final String content; + + // 场景1:仅消息 + public BusinessException(String content) { + super(content); + this.content = content; + this.errorCodeEnum = ErrorCodeEnum.UNKNOWN_ERROR; + } + + // 场景2:仅枚举 + public BusinessException(ErrorCodeEnum errorCodeEnum) { + super(errorCodeEnum.getDesc()); + this.content = null; + this.errorCodeEnum = errorCodeEnum; + } + + // 场景3:枚举 + 自定义信息 + public BusinessException(ErrorCodeEnum errorCodeEnum, String content) { + super(content); + this.errorCodeEnum = errorCodeEnum; + this.content = content; + } + + public ErrorCodeEnum getErrorCodeEnum() { + return errorCodeEnum; + } + + public String getcontent() { + return content; + } +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/BatchDeleteLabelRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/BatchDeleteLabelRequest.java new file mode 100644 index 0000000..c0836d7 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/BatchDeleteLabelRequest.java @@ -0,0 +1,20 @@ +package com.htfp.service.usm.biz.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 09:04 + **/ +@Data +public class BatchDeleteLabelRequest { + @NotNull(message = "标签列表不能为空") + @Size(min = 1, message = "请选择要删除的标签") + private List labelIdList; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertLabelRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertLabelRequest.java new file mode 100644 index 0000000..090d94c --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertLabelRequest.java @@ -0,0 +1,18 @@ +package com.htfp.service.usm.biz.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 09:04 + **/ +@Data +public class InsertLabelRequest { + @NotBlank @Size(max = 16, message = "标签名称不能超过16个字符") + private String labelName; + private String labelInfo; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertUavInfoRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertUavInfoRequest.java new file mode 100644 index 0000000..c44eebf --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/InsertUavInfoRequest.java @@ -0,0 +1,101 @@ +package com.htfp.service.usm.biz.model.request; + + +import com.htfp.service.usm.biz.validator.ValidEnum; +import com.htfp.service.usm.common.enums.UavMarkerEnum; +import com.htfp.service.usm.common.enums.UavUsageStatusEnum; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-11 10:54 + **/ +@Data +public class InsertUavInfoRequest { + /** + * uavId, 主键 + */ + private Integer id; + + /** + * 无人机唯一识别码 + */ + @NotBlank(message = "无人机唯一识别码不能为空") + private String uavSn; + + /** + * 无人机编号, 例如1号机, 2号机... + */ + @NotNull(message = "无人机编号不能为空") + private Integer uavNumber; + + /** + * 无人机型号: enum + */ + @NotNull(message = "无人机型号不能为空") + private Integer uavModel; + + /** + * 无人机构型说明 + */ + private String configurationInfo; + + /** + * 无人机生产厂家 + */ + @NotBlank(message = "无人机生产厂家不能为空") + private String manufacturer; + + /** + * 无人机生产日期 + */ + @NotNull(message = "无人机生产日期不能为空") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate productionDate; + + /** + * 无人机生产地点 + */ + @NotBlank(message = "无人机生产地点不能为空") + private String productionSite; + + /** + * 无人机出厂批次 + */ + @NotNull(message = "无人机出厂批次不能为空") + private Integer productionBatch; + + /** + * 无人机涂装标识: enum + */ + @NotNull(message = "无人机涂装标识不能为空") + @ValidEnum(enumClass = UavMarkerEnum.class, message = "无人机涂装类型枚举错误") + private Integer paintMark; + + /** + * 无人机使用状态: 0-闲置, 1-维修, 2-任务中, 3-试验, 4-交付, 5-报废, 6-库房中 + */ + @NotNull(message = "无人机使用状态不能为空") + @ValidEnum(enumClass = UavUsageStatusEnum.class, message = "无人机使用类型枚举错误") + private Integer usageStatus; + + /** + * 无人机当前所在地 + */ + @NotBlank(message = "无人机当前所在地不能为空") + private String currentLocation; + + /** + * 无人机标签列表 + */ + private List labelIdList; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoByIdRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoByIdRequest.java new file mode 100644 index 0000000..3068f68 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoByIdRequest.java @@ -0,0 +1,16 @@ +package com.htfp.service.usm.biz.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-11 15:05 + **/ +@Data +public class QueryUavInfoByIdRequest { + @NotNull(message = "无人机id不能为空") + private Integer uavId; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoBySnRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoBySnRequest.java new file mode 100644 index 0000000..ab8e4d7 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/QueryUavInfoBySnRequest.java @@ -0,0 +1,16 @@ +package com.htfp.service.usm.biz.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-11 15:07 + **/ +@Data +public class QueryUavInfoBySnRequest { + @NotBlank(message = "无人机sn不能为空") + private String uavSn; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/UpdateLabelRequest.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/UpdateLabelRequest.java new file mode 100644 index 0000000..416aa86 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/request/UpdateLabelRequest.java @@ -0,0 +1,22 @@ +package com.htfp.service.usm.biz.model.request; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 10:33 + **/ +@Data +public class UpdateLabelRequest { + @NotNull(message = "标签id不能为空") + private Integer id; + @NotBlank + @Size(max = 16, message = "标签名称不能超过16个字符") + private String labelName; + private String labelInfo; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/model/response/LabelVO.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/response/LabelVO.java new file mode 100644 index 0000000..f91c0d1 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/model/response/LabelVO.java @@ -0,0 +1,17 @@ +package com.htfp.service.usm.biz.model.response; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author : shi_y + * @description : 返回给前端的数据模型 + * @createTime : 2025-06-12 10:20 + **/ +@Data @NoArgsConstructor @AllArgsConstructor +public class LabelVO { + private Long id; + private String labelName; + private String labelInfo; +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/ILabelService.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/ILabelService.java new file mode 100644 index 0000000..f410f4b --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/ILabelService.java @@ -0,0 +1,60 @@ +package com.htfp.service.usm.biz.service; + +import com.htfp.service.usm.biz.model.request.InsertLabelRequest; +import com.htfp.service.usm.biz.model.request.UpdateLabelRequest; +import com.htfp.service.usm.biz.model.response.LabelVO; +import com.htfp.service.usm.dao.model.entity.LabelDO; + +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 09:11 + **/ +public interface ILabelService { + + /** + * 新增标签 + * @param insertLabelRequest 标签信息 + * @return 数据库自增主键 + */ + Integer insertLabel(InsertLabelRequest insertLabelRequest); + + /** + * 查询所有标签 + * @return 标签列表 + */ + List queryAllLabels(); + + /** + * 查询所有标签id + * @return 标签列表 + */ + List queryAllLabelsId(); + /** + * 根据ID查询标签 + * @param id 标签ID + * @return 标签信息 + */ + LabelVO queryLabelById(Integer id); + + /** + * 根据名称查询标签 + * @param labelName 标签名称 + * @return 标签信息 + */ + LabelVO queryLabelByName(String labelName); + + /** + * 批量删除标签 + * @param ids 标签ID列表 + */ + void batchDeleteLabels(List ids); + + /** + * 更新标签信息 + * @param updateLabelRequest 标签更新信息 + */ + void updateLabel(UpdateLabelRequest updateLabelRequest); +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavInfoService.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavInfoService.java new file mode 100644 index 0000000..c464057 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavInfoService.java @@ -0,0 +1,50 @@ +package com.htfp.service.usm.biz.service; + +import com.htfp.service.usm.biz.model.request.InsertUavInfoRequest; +import com.htfp.service.usm.dao.model.entity.UavInfoDO; +import com.htfp.service.usm.dao.model.param.QueryUavInfoParam; + +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-10 17:33 + **/ +public interface IUavInfoService { + + /** + * 根据内部id查询无人机信息 + * @param uavId + * @return + */ + UavInfoDO queryUavInfoById(Integer uavId); + + /** + * 根据无人机sn查询无人机信息 + * @param uavSn + * @return + */ + UavInfoDO queryUavInfoBySn(String uavSn); + + /** + * 根据指定参数查询无人机信息 + * @param queryUavInfoParam 查询条件参数 + * @return List<UavInfoDO> 返回满足条件的数据列表 + */ + List queryUavInfoPageByCondition(QueryUavInfoParam queryUavInfoParam); + + /** + * 设置无人机标签 + * @param insertUavInfoRequest 插入数据参数 + * @return Integer 系统生成的id + */ + Integer insertUavInfo(InsertUavInfoRequest insertUavInfoRequest); + + /** + * 设置无人机标签 + * @param uavId 无人机id + * @param labelIdList 标签id列表 + */ + void setUavLabelMapping(Integer uavId, List labelIdList); +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavLabelMappingService.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavLabelMappingService.java new file mode 100644 index 0000000..e07b938 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/IUavLabelMappingService.java @@ -0,0 +1,17 @@ +package com.htfp.service.usm.biz.service; + +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 16:28 + **/ +public interface IUavLabelMappingService { + + int removeAllLabelsByUavId(Long uavId); + + int removeAllLabelsByLabelIds(List labelIdList); + + void addLabels(Long uavId, List labelIdList); +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/IUavLabelMappingServiceImpl.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/IUavLabelMappingServiceImpl.java new file mode 100644 index 0000000..8c99ae2 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/IUavLabelMappingServiceImpl.java @@ -0,0 +1,48 @@ +package com.htfp.service.usm.biz.service.impl; + +import com.htfp.service.usm.biz.service.IUavLabelMappingService; +import com.htfp.service.usm.dao.mapper.UavLabelMappingMapper; +import com.htfp.service.usm.dao.model.mapping.UavLabelMappingDO; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 16:29 + **/ +@Service +public class IUavLabelMappingServiceImpl implements IUavLabelMappingService { + + @Resource + UavLabelMappingMapper uavLabelMappingMapper; + + @Transactional + @Override + public int removeAllLabelsByUavId(Long uavId) { + return uavLabelMappingMapper.deleteByUavId(uavId); + } + + @Override + public int removeAllLabelsByLabelIds(List labelIdList) { + return uavLabelMappingMapper.deleteByLabelIds(labelIdList); + } + + @Transactional + @Override + public void addLabels(Long uavId, List labelIdList) { + List uavLabelMappingDOList = new ArrayList<>(); + for (Long labelId : labelIdList) { + UavLabelMappingDO uavLabelMappingDO = new UavLabelMappingDO(null, uavId, labelId, 0, LocalDateTime.now(), LocalDateTime.now()); + uavLabelMappingDOList.add(uavLabelMappingDO); + } + uavLabelMappingMapper.batchInsert(uavLabelMappingDOList); + } + + +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/LabelServiceImpl.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/LabelServiceImpl.java new file mode 100644 index 0000000..21d3579 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/LabelServiceImpl.java @@ -0,0 +1,98 @@ +package com.htfp.service.usm.biz.service.impl; + +import com.htfp.service.usm.biz.exception.BusinessException; +import com.htfp.service.usm.biz.model.request.InsertLabelRequest; +import com.htfp.service.usm.biz.model.request.UpdateLabelRequest; +import com.htfp.service.usm.biz.model.response.LabelVO; +import com.htfp.service.usm.biz.service.ILabelService; +import com.htfp.service.usm.biz.service.IUavLabelMappingService; +import com.htfp.service.usm.common.enums.ErrorCodeEnum; +import com.htfp.service.usm.dao.mapper.LabelMapper; +import com.htfp.service.usm.dao.model.entity.LabelDO; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 09:12 + **/ +@Service +public class LabelServiceImpl implements ILabelService { + @Resource + private LabelMapper labelMapper; + + @Resource + private IUavLabelMappingService uavLabelMappingService; + + /*InsertRequest -> 数据库DO + * 更新createTime 和 updateTime + */ + private LabelDO buildLabelDOFromInsertRequest(InsertLabelRequest insertLabelRequest) { + return new LabelDO(null, insertLabelRequest.getLabelName(), insertLabelRequest.getLabelInfo(), 0, LocalDateTime.now(), LocalDateTime.now()); + } + + /*UpdateRequest -> 数据库DO + * 更新updateTime + */ + private LabelDO buildLabelDOFromUpdateRequest(UpdateLabelRequest updateLabelRequest) { + return new LabelDO(Long.valueOf(updateLabelRequest.getId()), updateLabelRequest.getLabelName(), updateLabelRequest.getLabelInfo(), 0, null, LocalDateTime.now()); + } + + private LabelVO buildLabelVOFromDO(LabelDO labelDO) { + return new LabelVO(labelDO.getId(), labelDO.getLabelName(), labelDO.getLabelInfo()); + } + + @Override + public Integer insertLabel(InsertLabelRequest insertLabelRequest) { + String labelName = insertLabelRequest.getLabelName(); + if (labelMapper.selectLabelByName(labelName)!=null) { + throw new BusinessException(ErrorCodeEnum.DUPLICATE_ENTRY, "标签名称已存在"); + } + LabelDO labelDO = buildLabelDOFromInsertRequest(insertLabelRequest); + labelMapper.insertLabel(labelDO); + return labelDO.getId().intValue(); + } + + @Override + public List queryAllLabels() { + List labelDOList = labelMapper.selectAll(); + return labelDOList.stream().map(this::buildLabelVOFromDO).collect(Collectors.toList()); + } + + @Override + public List queryAllLabelsId() { + return labelMapper.selectAllIds(); + } + + @Override + public LabelVO queryLabelById(Integer id) { + LabelDO labelDO = labelMapper.selectLabelById(id); + return buildLabelVOFromDO(labelDO); + } + + @Override + public LabelVO queryLabelByName(String labelName) { + LabelDO labelDO = labelMapper.selectLabelByName(labelName); + return buildLabelVOFromDO(labelDO); + } + + @Override + public void batchDeleteLabels(List labelIdList) { + // 删除labelId对应的映射关系 + List labelIdListLong = labelIdList.stream().map(Long::valueOf).collect(Collectors.toList()); + uavLabelMappingService.removeAllLabelsByLabelIds(labelIdListLong); + + labelMapper.deleteLabels(labelIdList); + } + + @Override + public void updateLabel(UpdateLabelRequest updateLabelRequest) { + LabelDO labelDO = buildLabelDOFromUpdateRequest(updateLabelRequest); + labelMapper.updateLabel(labelDO); + } +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/UavInfoServiceImpl.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/UavInfoServiceImpl.java new file mode 100644 index 0000000..fda4cce --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/service/impl/UavInfoServiceImpl.java @@ -0,0 +1,94 @@ +package com.htfp.service.usm.biz.service.impl; + +import com.htfp.service.usm.biz.exception.BusinessException; +import com.htfp.service.usm.biz.service.ILabelService; +import com.htfp.service.usm.biz.service.IUavInfoService; +import com.htfp.service.usm.biz.model.request.InsertUavInfoRequest; +import com.htfp.service.usm.biz.service.IUavLabelMappingService; +import com.htfp.service.usm.common.enums.ErrorCodeEnum; +import com.htfp.service.usm.dao.mapper.UavInfoMapper; +import com.htfp.service.usm.dao.model.entity.UavInfoDO; +import com.htfp.service.usm.dao.model.param.QueryUavInfoParam; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import javax.annotation.Resource; +import javax.validation.constraints.NotEmpty; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-10 17:33 + **/ +@Service +public class UavInfoServiceImpl implements IUavInfoService { + + @Resource + UavInfoMapper uavInfoMapper; + @Resource + ILabelService labelService; + @Resource + IUavLabelMappingService uavLabelMappingService; + + @Override + public UavInfoDO queryUavInfoById(Integer uavId) { + return uavInfoMapper.selectByUavId(Long.valueOf(uavId)); + } + @Override + public UavInfoDO queryUavInfoBySn(String uavSn) { + return uavInfoMapper.selectByUavSn(uavSn); + } + @Override + public List queryUavInfoPageByCondition(QueryUavInfoParam queryUavInfoParam) { + return uavInfoMapper.selectByCondition(queryUavInfoParam); + } + + @Transactional + @Override + public Integer insertUavInfo(InsertUavInfoRequest insertUavInfoRequest) { + // TODO 2025/6/11: 校验相关数据是否已存在 + if (queryUavInfoBySn(insertUavInfoRequest.getUavSn()) != null) { + throw new BusinessException(ErrorCodeEnum.DUPLICATE_ENTRY, "无人机sn重复,请重新录入"); + } + UavInfoDO uavInfoDO = buildUavInfoDOFromInsertRequest(insertUavInfoRequest); + uavInfoDO.setCreateTime(LocalDateTime.now()); + uavInfoDO.setUpdateTime(LocalDateTime.now()); + uavInfoMapper.insertUavInfo(uavInfoDO); + int uavId = uavInfoDO.getId().intValue(); + List labelIdList = insertUavInfoRequest.getLabelIdList(); + if (!CollectionUtils.isEmpty(labelIdList)) { + setUavLabelMapping(uavId, labelIdList); + } + return uavId; + } + + /** 设置无人机标签*/ + @Override + public void setUavLabelMapping(Integer uavId, @NotEmpty List labelIdList) { + // Set existLabelIdList = uavLabelMappingMapper.selectLabelIdsByUavId(Long.valueOf(uavId)); + uavLabelMappingService.removeAllLabelsByUavId(Long.valueOf(uavId)); + List labelIdListLong = labelIdList.stream().map(Long::valueOf).collect(Collectors.toList()); + + // 筛选不存在的标签 + List allLabelsInDB = labelService.queryAllLabelsId(); + List labelIdNotExist = labelIdListLong.stream() + .filter(labelId -> !allLabelsInDB.contains((labelId))).collect(Collectors.toList()); + + if (!CollectionUtils.isEmpty(labelIdNotExist)) { + throw new BusinessException(ErrorCodeEnum.DATA_NOT_EXIST, "标签id="+labelIdNotExist.toString()+"不存在"); + } + uavLabelMappingService.addLabels(Long.valueOf(uavId), labelIdListLong); + } + + + private UavInfoDO buildUavInfoDOFromInsertRequest(InsertUavInfoRequest insertUavInfoRequest) { + return new UavInfoDO(null, insertUavInfoRequest.getUavSn(), insertUavInfoRequest.getUavNumber(), insertUavInfoRequest.getUavModel(), insertUavInfoRequest.getConfigurationInfo(), insertUavInfoRequest.getManufacturer(), insertUavInfoRequest.getProductionDate(), insertUavInfoRequest.getProductionSite(), insertUavInfoRequest.getProductionBatch(), insertUavInfoRequest.getPaintMark(), insertUavInfoRequest.getUsageStatus(), insertUavInfoRequest.getCurrentLocation(), 0, null, null); + } + + + +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/BaseValidate.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/BaseValidate.java new file mode 100644 index 0000000..928cbc0 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/BaseValidate.java @@ -0,0 +1,16 @@ +package com.htfp.service.usm.biz.validator; + +/** + * @Author sunjipeng + * @Date 2022-05-18 15:52 + * @Description 校验接口 + */ +public interface BaseValidate { + /** + * 参数校验 + * + * @param data + * @return + */ + R validate(T data); +} diff --git a/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/ValidEnum.java b/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/ValidEnum.java new file mode 100644 index 0000000..ca52bf1 --- /dev/null +++ b/usm-biz/src/main/java/com/htfp/service/usm/biz/validator/ValidEnum.java @@ -0,0 +1,43 @@ +package com.htfp.service.usm.biz.validator; + +import javax.validation.Constraint; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import javax.validation.Payload; +import java.lang.annotation.*; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.List; + +@Documented +@Constraint(validatedBy = EnumValueValidator.class) +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ValidEnum { + String message() default "Invalid enum value"; + Class[] groups() default {}; + Class[] payload() default {}; + + Class> enumClass(); +} + +class EnumValueValidator implements ConstraintValidator { + + private List enumValues; + + @Override + public void initialize(ValidEnum annotation) { + try { + Method method = annotation.enumClass().getMethod("values"); + enumValues = Arrays.asList((Enum[]) method.invoke(null)); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to initialize enum validator."); + } + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + if (value == null) return true; + return enumValues.stream().anyMatch(v -> v.toString().equals(value.toString())); + } +} \ No newline at end of file diff --git a/usm-biz/src/test/java/com/htfp/service/usm/biz/service/impl/LabelServiceImplTest.java b/usm-biz/src/test/java/com/htfp/service/usm/biz/service/impl/LabelServiceImplTest.java new file mode 100644 index 0000000..9687d93 --- /dev/null +++ b/usm-biz/src/test/java/com/htfp/service/usm/biz/service/impl/LabelServiceImplTest.java @@ -0,0 +1,26 @@ +package com.htfp.service.usm.biz.service.impl; + +import com.htfp.service.usm.dao.mapper.LabelMapper; +import org.junit.jupiter.api.Test; + +import javax.annotation.Resource; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 13:42 + **/ + +class LabelServiceImplTest { + @Resource + private LabelMapper labelMapper; + @Test + void queryLabelById() { + + } + + @Test + void queryLabelByName() { + + } +} \ No newline at end of file diff --git a/usm-common/pom.xml b/usm-common/pom.xml new file mode 100644 index 0000000..035ec91 --- /dev/null +++ b/usm-common/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + com.htfp.service + usm + 0.0.1-SNAPSHOT + + + usm-common + + + 8 + 8 + UTF-8 + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + javax.validation + validation-api + + + + \ No newline at end of file diff --git a/usm-common/src/main/java/com/htfp/service/usm/common/enums/ErrorCodeEnum.java b/usm-common/src/main/java/com/htfp/service/usm/common/enums/ErrorCodeEnum.java new file mode 100644 index 0000000..8543c4b --- /dev/null +++ b/usm-common/src/main/java/com/htfp/service/usm/common/enums/ErrorCodeEnum.java @@ -0,0 +1,48 @@ +package com.htfp.service.usm.common.enums; + +/** + * @Author sunjipeng + * @Date 2022-05-18 16:39 + * @Description 返回体失败类型枚举 + */ +public enum ErrorCodeEnum { + SUCCESS(0, "成功"), + // 系统错误 + SYSTEM_ERROR(500, "系统异常"), + + // 业务错误 + // 校验错误 + PARAM_VALIDATION_ERROR(1001, "参数校验失败"), + SQL_ERROR(3000, "数据库错误"), + DUPLICATE_ENTRY(3001, "数据重复"), + DATA_NOT_EXIST(3002, "数据不存在"), + + UNKNOWN_ERROR(9999, "未知错误"), + ; + + + public final Integer code; + public final String desc; + + ErrorCodeEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + public Integer getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public static ErrorCodeEnum getFromCode(Integer code) { + for (ErrorCodeEnum errorCodeEnum : values()) { + if (errorCodeEnum.code.equals(code)) { + return errorCodeEnum; + } + } + return null; + } +} diff --git a/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavMarkerEnum.java b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavMarkerEnum.java new file mode 100644 index 0000000..083e379 --- /dev/null +++ b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavMarkerEnum.java @@ -0,0 +1,38 @@ +package com.htfp.service.usm.common.enums; + +/** + * @author : shi_y + * @description : 无人机涂装标识枚举 + * @createTime : 2025-06-11 10:58 + **/ +public enum UavMarkerEnum { + + MARKER1(0, "涂装标识1"), + OTHERS(99, "其他"), + ; + + public final Integer code; + public final String desc; + + UavMarkerEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + public Integer getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public static UavMarkerEnum getFromCode(Integer code) { + for (UavMarkerEnum enumItem : values()) { + if (enumItem.code.equals(code)) { + return enumItem; + } + } + return null; + } +} diff --git a/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavModelEnum.java b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavModelEnum.java new file mode 100644 index 0000000..ebfa707 --- /dev/null +++ b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavModelEnum.java @@ -0,0 +1,38 @@ +package com.htfp.service.usm.common.enums; + +/** + * @author : shi_y + * @description : 无人机型号枚举 + * @createTime : 2025-06-11 10:58 + **/ +public enum UavModelEnum { + + FP98(0, "FP98"), + OTHERS(99, "其他"), + ; + + public final Integer code; + public final String desc; + + UavModelEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + public Integer getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public static UavModelEnum getFromCode(Integer code) { + for (UavModelEnum enumItem : values()) { + if (enumItem.code.equals(code)) { + return enumItem; + } + } + return null; + } +} diff --git a/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavUsageStatusEnum.java b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavUsageStatusEnum.java new file mode 100644 index 0000000..f2dc56d --- /dev/null +++ b/usm-common/src/main/java/com/htfp/service/usm/common/enums/UavUsageStatusEnum.java @@ -0,0 +1,44 @@ +package com.htfp.service.usm.common.enums; + +/** + * @author : shi_y + * @description : 无人机使用状态枚举 + * @createTime : 2025-06-11 10:58 + **/ +public enum UavUsageStatusEnum { + // 0-闲置, 1-维修, 2-任务中, 3-试验, 4-交付, 5-报废, 6-库房中 + IDLE(0, "闲置"), + REPAIRING(1, "维修"), + IN_MISSION(2, "任务中"), + TESTING(3, "试验"), + DELIVERED(4, "交付"), + SCRAPED(5, "报废"), + IN_STORAGE(6, "库房中"), + OTHERS(99, "其他"), + ; + + public final Integer code; + public final String desc; + + UavUsageStatusEnum(Integer code, String desc) { + this.code = code; + this.desc = desc; + } + + public Integer getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public static UavUsageStatusEnum getFromCode(Integer code) { + for (UavUsageStatusEnum enumItem : values()) { + if (enumItem.code.equals(code)) { + return enumItem; + } + } + return null; + } +} diff --git a/usm-common/src/main/java/com/htfp/service/usm/common/utils/JsonUtils.java b/usm-common/src/main/java/com/htfp/service/usm/common/utils/JsonUtils.java new file mode 100644 index 0000000..77f588b --- /dev/null +++ b/usm-common/src/main/java/com/htfp/service/usm/common/utils/JsonUtils.java @@ -0,0 +1,215 @@ +package com.htfp.service.usm.common.utils; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.*; +import javax.validation.constraints.NotNull; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * JSON 工具类,封装 Jackson 对象序列化/反序列化,支持类型泛化。 + */ +public class JsonUtils { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + // 默认配置 + static { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 是否忽略未知字段 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 序列化时忽略null字段 + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 输出带格式的JSON + objectMapper.enable(SerializationFeature.FAIL_ON_SELF_REFERENCES); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + // objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + } + + private JsonUtils() {} + + /** + * 获取 ObjectMapper单例 + */ + public static ObjectMapper getInstance() { + return objectMapper; + } + + + /** + * 将对象序列化为 JSON 字符串。 + * + * @param obj 要序列化的对象 + * @return JSON 字符串;若对象为 null 返回 null + * @throws JsonSerializeException 序列化失败 + */ + public static String obj2json(@NotNull Object obj) { + if (obj == null) return null; + if (obj instanceof Map && mapSelfContain((Map) obj)){ + // 循环检测 + throw new JsonSerializeException("对象序列化失败,对象中包含自身引用"); + } + try { + return objectMapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + throw new JsonSerializeException("对象序列化为 JSON 字符串失败", e); + } + } + + private static boolean mapSelfContain(Map obj) { + return obj.containsValue(obj); + } + + /** + * 将 JSON 字符串反序列化为对象。 + * + * @param jsonStr JSON 字符串 + * @param clazz 类型 + * @param 泛型 + * @return 反序列化对象;若 jsonStr 为空返回 null + * @throws IllegalArgumentException 参数为空 + * @throws JsonDeserializeException 解析失败 + */ + public static T json2obj(@NotNull String jsonStr, @NotNull Class clazz) { + if (clazz == null) throw new IllegalArgumentException("参数 clazz 不能为空"); + if (jsonStr == null || jsonStr.trim().isEmpty()) return null; + try { + return objectMapper.readValue(jsonStr, clazz); + } catch (IOException e) { + throw new JsonDeserializeException("JSON 字符串转对象失败: " + clazz.getSimpleName(), e); + } + } + + /** + * 将 JSON 字符串反序列化为泛型对象。 + * + * @param jsonStr JSON 字符串 + * @param typeReference 泛型引用 + * @param 泛型 + * @return 泛型对象;若 jsonStr 为空返回 null + * @throws IllegalArgumentException 参数为空 + * @throws JsonDeserializeException 解析失败 + */ + public static T json2obj(@NotNull String jsonStr, @NotNull TypeReference typeReference) { + if (typeReference == null) throw new IllegalArgumentException("参数 typeReference 不能为空"); + if (jsonStr == null || jsonStr.trim().isEmpty()) return null; + try { + return objectMapper.readValue(jsonStr, typeReference); + } catch (IOException e) { + throw new JsonDeserializeException("JSON 字符串转泛型对象失败", e); + } + } + + /** + * 将 JSON 字符串转换为 Map。 + * + * @param jsonStr JSON 字符串 + * @return Map;若 jsonStr 为空返回 null + * @throws JsonDeserializeException 解析失败 + */ + public static Map json2map(@NotNull String jsonStr) { + return json2obj(jsonStr, new TypeReference>() {}); + } + + /** + * 将 JSON 字符串转换为 Map。 + * + * @param jsonStr JSON 字符串 + * @param clazz 值类型 + * @param 泛型 + * @return Map;若 jsonStr 为空返回 null + * @throws IllegalArgumentException 参数为空 + * @throws JsonDeserializeException 解析失败 + */ + public static Map json2map(@NotNull String jsonStr, @NotNull Class clazz) { + if (clazz == null) throw new IllegalArgumentException("参数 clazz 不能为空"); + if (jsonStr == null || jsonStr.trim().isEmpty()) return null; + try { + JavaType type = objectMapper.getTypeFactory().constructMapType(Map.class, String.class, clazz); + return objectMapper.readValue(jsonStr, type); + } catch (IOException e) { + throw new JsonDeserializeException("JSON 字符串转 Map 失败", e); + } + } + + /** + * 将 JSON 数组字符串转换为 List。 + * + * @param jsonArrayStr JSON 数组字符串 + * @param clazz 元素类型 + * @param 泛型 + * @return List;若为空返回 null + * @throws IllegalArgumentException 参数为空 + * @throws JsonDeserializeException 解析失败 + */ + public static List json2list(@NotNull String jsonArrayStr, @NotNull Class clazz) { + if (clazz == null) throw new IllegalArgumentException("参数 clazz 不能为空"); + if (jsonArrayStr == null || jsonArrayStr.trim().isEmpty()) return null; + try { + JavaType type = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz); + return objectMapper.readValue(jsonArrayStr, type); + } catch (IOException e) { + throw new JsonDeserializeException("JSON 数组转 List<" + clazz.getSimpleName() + "> 失败", e); + } + } + + /** + * 将 Map 转换为对象。 + * + * @param map 原始 Map + * @param clazz 目标类型 + * @param 泛型 + * @return 实例;若 map 为 null 返回 null + * @throws IllegalArgumentException 参数为空 + */ + public static T map2obj(@NotNull Map map, @NotNull Class clazz) { + if (map == null) return null; + if (clazz == null) throw new IllegalArgumentException("参数 clazz 不能为空"); + return objectMapper.convertValue(map, clazz); + } + + /** + * 将对象输出为格式化 JSON 写入文件。 + * + * @param obj 要写入的对象 + * @param filePath 目标文件路径 + * @throws IllegalArgumentException 参数为空 + * @throws JsonSerializeException 写入失败 + */ + public static void obj2jsonFile(@NotNull Object obj, @NotNull String filePath) { + if (obj == null) throw new IllegalArgumentException("obj 不能为空"); + if (filePath == null || filePath.trim().isEmpty()) { + throw new IllegalArgumentException("filePath 不能为空"); + } + try { + objectMapper.writeValue(new File(filePath), obj); + } catch (IOException e) { + throw new JsonSerializeException("对象写入 JSON 文件失败: " + filePath, e); + } + } + + /** + * JSON 序列化异常(运行时) + */ + public static class JsonSerializeException extends RuntimeException { + public JsonSerializeException(String msg, Throwable cause) { + super(msg, cause); + } + public JsonSerializeException(String msg) { + super(msg); + } + } + + /** + * JSON 反序列化异常(运行时) + */ + public static class JsonDeserializeException extends RuntimeException { + public JsonDeserializeException(String msg, Throwable cause) { + super(msg, cause); + } + public JsonDeserializeException(String msg) { + super(msg); + } + } +} diff --git a/usm-common/src/test/java/com/htfp/service/usm/common/utils/JsonUtilsTest.java b/usm-common/src/test/java/com/htfp/service/usm/common/utils/JsonUtilsTest.java new file mode 100644 index 0000000..57fa91f --- /dev/null +++ b/usm-common/src/test/java/com/htfp/service/usm/common/utils/JsonUtilsTest.java @@ -0,0 +1,277 @@ +package com.htfp.service.usm.common.utils; + +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.core.type.TypeReference; +import com.htfp.service.usm.common.utils.JsonUtils.JsonDeserializeException; +import com.htfp.service.usm.common.utils.JsonUtils.JsonSerializeException; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +class JsonUtilsTest { + + @Data @NoArgsConstructor@AllArgsConstructor + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) + private static class TestBean { + private String name; + private int age; + // 省略 getter/setter 以保持示例简洁 + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TestBean testBean = (TestBean) o; + + if (age != testBean.age) return false; + return Objects.equals(name, testBean.name); + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + age; + return result; + } + } + + @Data + private static class TestBeanWithList { + private String name; + private int age; + private List hobbies; + // 省略 getter/setter 以保持示例简洁 + } + + // 测试泛型结构 + @Data + private static class TestBeanWithGeneric { + private K key; + // 省略 getter/setter 以保持示例简洁 + } + + // 测试循环引用 + @Data + private static class CircularReference { + private CircularReference self; + // 省略 getter/setter 以保持示例简洁 + } + + @Data @NoArgsConstructor @AllArgsConstructor + private static class TestChildBeanA extends TestBean { + private String fieldChildA; + } + @Data @NoArgsConstructor @AllArgsConstructor + private static class TestChildBeanB extends TestBean { + private String fieldChildB; + } + // 测试 obj2json 正常序列化 + @Test + void testObj2json_Normal() { + TestBean bean = new TestBean("Alice", 30); + String json = JsonUtils.obj2json(bean); + assertNotNull(json); + assertTrue(json.contains("name") && json.contains("age")); + } + + // 测试 obj2json 对 null 的处理 + @Test + void testObj2json_Null() { + assertNull(JsonUtils.obj2json(null)); + } + + // 测试 obj2json 抛出异常(当输入对象包含循环引用时) + @Test + void testObj2json_Exception() { + // 创建一个带有循环引用的对象 + Map map = new HashMap<>(); + map.put("map", map); // 循环引用 + + assertThrows(JsonSerializeException.class, () -> JsonUtils.obj2json(map)); + } + + // 测试继承关系序列化 + @Test + void testObj2json_ParentChild() { + TestChildBeanA childA = new TestChildBeanA(); + childA.setName("childA"); + childA.setAge(40); + childA.setFieldChildA("fieldChildA"); + + TestChildBeanB childB = new TestChildBeanB(); + childB.setName("childB"); + childB.setAge(30); + childB.setFieldChildB("fieldChildB"); + + List beanList = Arrays.asList(childA, childB); + String json = JsonUtils.obj2json(beanList); + System.out.println(json); + assertNotNull(json); + assertTrue(json.contains("childA") && json.contains("childB")); + assertTrue(json.contains("fieldChildA") && json.contains("fieldChildB")); + } + + // 测试继承关系反序列化 + // @Test + // void testJson2obj_ParentChild() { + // String json = "[{\"name\":\"childA\",\"age\":40,\"fieldChildA\":\"fieldChildA\"},{\"name\":\"childB\",\"age\":30,\"fieldChildB\":\"fieldChildB\"}]"; + // + // List beanList = JsonUtils.json2list(json, TestBean.class); + // assertNotNull(beanList); + // assertEquals(2, beanList.size()); + // assertEquals("childA", beanList.get(0).getName()); + // assertEquals(40, beanList.get(0).getAge()); + // assertEquals("fieldChildA", ((TestChildBeanA) beanList.get(0)).getFieldChildA()); + // assertEquals("childB", beanList.get(1).getName()); + // } + + + @Test + void testObj2json_SelfReference() { + // 创建一个带有循环引用的对象 + CircularReference circularReference = new CircularReference(); + circularReference.self = circularReference; + assertThrows(JsonSerializeException.class, () -> JsonUtils.obj2json(circularReference)); + } + + + // 测试 json2obj 正常反序列化 + @Test + void testJson2obj_StringClass_Normal() { + String json = "{\"name\":\"Bob\",\"age\":25}"; + TestBean bean = JsonUtils.json2obj(json, TestBean.class); + assertNotNull(bean); + assertEquals("Bob", bean.name); + assertEquals(25, bean.age); + } + + // 测试 json2obj 对空字符串的处理 + @Test + void testJson2obj_StringClass_EmptyString() { + assertNull(JsonUtils.json2obj("", TestBean.class)); + } + + // 测试 json2obj 对 null 的处理 + @Test + void testJson2obj_StringClass_Null() { + assertNull(JsonUtils.json2obj(null, TestBean.class)); + } + + // 测试 json2obj 泛型版本正常反序列化 + @Test + void testJson2obj_TypeReference_Normal() { + String json = "{\"name\":\"Charlie\",\"age\":40}"; + TestBean bean = JsonUtils.json2obj(json, new TypeReference() {}); + assertNotNull(bean); + assertEquals("Charlie", bean.name); + assertEquals(40, bean.age); + } + + // 测试 json2obj 泛型版本对嵌套结构的处理 + @Test + void testJson2obj_TypeReference_Nested() { + String jsonString = "{\"key\":\"ok\"}"; + TestBeanWithGeneric bean = JsonUtils.json2obj(jsonString, new TypeReference>() {}); + assertNotNull(bean); + assertEquals("ok", bean.key); + + String jsonInteger = "{\"key\":10}"; + TestBeanWithGeneric beanWithInt = JsonUtils.json2obj(jsonInteger, new TypeReference>() {}); + assertNotNull(beanWithInt); + } + + // 测试 json2map 反序列化 + @Test + void testJson2map() { + String json = "{\"key1\":\"value1\",\"key2\":\"value2\"}"; + Map map = JsonUtils.json2map(json); + assertNotNull(map); + assertEquals(2, map.size()); + assertEquals("value1", map.get("key1")); + assertEquals("value2", map.get("key2")); + } + + // 测试 json2map 带类型参数 + @Test + void testJson2map_Class() { + String json = "{\"key1\":20,\"key2\":30}"; + Map map = JsonUtils.json2map(json, Integer.class); + assertNotNull(map); + assertEquals(2, map.size()); + assertEquals(Integer.valueOf(20), map.get("key1")); + assertEquals(Integer.valueOf(30), map.get("key2")); + } + + // 测试 json2list 反序列化 + @Test + void testJson2list() { + String json = "[\"item1\",\"item2\",\"item3\"]"; + List list = JsonUtils.json2list(json, String.class); + assertNotNull(list); + assertEquals(3, list.size()); + assertEquals("item1", list.get(0)); + assertEquals("item2", list.get(1)); + assertEquals("item3", list.get(2)); + } + + // 测试objList反序列化 + @Test + void testJson2objList() { + // List + String json = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]"; + List list = JsonUtils.json2list(json, TestBean.class); + assertNotNull(list); + assertEquals(2, list.size()); + assertEquals("Alice", list.get(0).name); + assertEquals(30, list.get(0).age); + assertEquals("Bob", list.get(1).name); + assertEquals(25, list.get(1).age); + } + @Test + void testJson2objListUseTypeReference() { + // List + String json = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]"; + List list = JsonUtils.json2obj(json, new TypeReference>() {}); + assertNotNull(list); + assertEquals(2, list.size()); + assertEquals("Alice", list.get(0).name); + assertEquals(30, list.get(0).age); + assertEquals("Bob", list.get(1).name); + assertEquals(25, list.get(1).age); + } + + // 测试 map2obj 转换 + @Test + void testMap2obj() { + Map map = new HashMap<>(); + map.put("name", "David"); + map.put("age", 35); + + TestBean bean = JsonUtils.map2obj(map, TestBean.class); + assertNotNull(bean); + assertEquals("David", bean.name); + assertEquals(35, bean.age); + } + + // 测试 map2obj 对 null 的处理 + @Test + void testMap2obj_NullMap() { + assertNull(JsonUtils.map2obj(null, TestBean.class)); + } + + // 测试 map2obj 对 null 类的处理 + @Test + void testMap2obj_NullClass() { + assertThrows(IllegalArgumentException.class, () -> { + JsonUtils.map2obj(new HashMap<>(), null); + }); + } +} \ No newline at end of file diff --git a/usm-dao/pom.xml b/usm-dao/pom.xml new file mode 100644 index 0000000..afdd3da --- /dev/null +++ b/usm-dao/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + com.htfp.service + usm + 0.0.1-SNAPSHOT + + + com.htfp.service + usm-dao + + + 8 + 8 + UTF-8 + + + + + com.mysql + mysql-connector-j + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + org.mybatis.spring.boot + mybatis-spring-boot-starter-test + 2.3.0 + test + + + \ No newline at end of file diff --git a/usm-dao/sql/bak/uav_device_list.sql b/usm-dao/sql/bak/uav_device_list.sql new file mode 100644 index 0000000..0e8d7f2 --- /dev/null +++ b/usm-dao/sql/bak/uav_device_list.sql @@ -0,0 +1,23 @@ +# 设备清单主表 +create table uav_device_list +( + id int primary key auto_increment comment '主键id', + device_sn varchar(64) not null comment '设备唯一识别码, 对外使用, 由业务员录入', + uav_id int not null comment '无人机id', + subsystem int not null comment '所属子系统, enum: 0-飞行器平台子系统, 1-动力子系统, 2-飞行控制子系统, 3-电气子系统, 4-机载数据链子系统', + device_type_id int not null comment '设备类型id', + device_name varchar(30) not null comment '设备名, 同一类设备可能有多个, 可用别名区分', + device_model varchar(30) comment '型号', + manufacturer varchar(100) comment '生产厂家', + install_date date not null comment '装机日期', + utilized_time int not null default 0 comment '已使用时间 (小时)', + expected_life int comment '预计寿命(年)', + status tinyint not null comment '设备状态, enum: 0-停用, 1-在用', + note text comment '备注', + create_time datetime, + update_time datetime, + key idx_uav_id (uav_id), + key idx_subsystem (subsystem), + unique key uk_uav_device (uav_id, device_sn) comment '同一飞机的设备sn不能重复', + unique key uk_device_status (device_sn, status) comment '一个设备只能处于一个状态' +) comment '无人机设备清单表'; \ No newline at end of file diff --git a/usm-dao/sql/动态信息/uav_label_mapping.sql b/usm-dao/sql/动态信息/uav_label_mapping.sql new file mode 100644 index 0000000..35224df --- /dev/null +++ b/usm-dao/sql/动态信息/uav_label_mapping.sql @@ -0,0 +1,14 @@ +# 无人机与标签的映射表 +drop table if exists uav_label_mapping; +create table if not exists uav_label_mapping +( + id bigint unsigned not null primary key auto_increment comment '主键id', + uav_id bigint unsigned not null comment '无人机id', + label_id bigint unsigned not null comment '标签id', + is_delete tinyint not null default 0 comment '是否删除, 0-否, 1-是', + create_time datetime comment '打标签时间', + update_time datetime comment '更新时间', +# foreign key (uav_basic_info_id) references uav_basic_info (id), # TODO : 删除 +# foreign key (label_id) references label (id), # TODO : 删除 + unique key unique_uav_label (uav_id, label_id, is_delete) +) comment '无人机与标签的映射表'; \ No newline at end of file diff --git a/usm-dao/sql/基础信息/device_info.sql b/usm-dao/sql/基础信息/device_info.sql new file mode 100644 index 0000000..416bfda --- /dev/null +++ b/usm-dao/sql/基础信息/device_info.sql @@ -0,0 +1,16 @@ +# 设备信息主表 +create table device_info +( + id int primary key auto_increment comment '主键id', + device_sn varchar(64) not null comment '设备唯一识别码, 对外使用, 由业务员录入', + device_type_id int not null comment '设备类型id', + device_name varchar(30) not null comment '设备名, 同一类设备可能有多个, 可用别名区分', + device_model varchar(30) comment '型号', + manufacturer varchar(100) comment '生产厂家', + install_date date not null comment '装机日期', + total_utilized_time int not null default 0 comment '累计已使用时间 (小时)', + expected_life int comment '预计寿命(年)', + note text comment '备注', + create_time datetime, + update_time datetime +) comment '无人机设备信息表'; \ No newline at end of file diff --git a/usm-dao/sql/基础信息/device_type.sql b/usm-dao/sql/基础信息/device_type.sql new file mode 100644 index 0000000..ca5c8f0 --- /dev/null +++ b/usm-dao/sql/基础信息/device_type.sql @@ -0,0 +1,10 @@ +# 无人机设备类型定义 +create table device_type ( + id int primary key auto_increment comment '主键id', + uav_model int not null comment '无人机型号: enum', + subsystem tinyint not null comment '所属子系统: enum', + name varchar(20) not null comment '设备类型名称', + key idx_uav_model (uav_model), + key idx_subsystem (subsystem), + unique key uk_uav_model_subsystem_name (uav_model, subsystem, name) +) comment '无人机设备类型表'; \ No newline at end of file diff --git a/usm-dao/sql/基础信息/label.sql b/usm-dao/sql/基础信息/label.sql new file mode 100644 index 0000000..69e7de9 --- /dev/null +++ b/usm-dao/sql/基础信息/label.sql @@ -0,0 +1,11 @@ +# 标签表 +create table if not exists label +( + id bigint unsigned not null primary key auto_increment comment 'Id,主键', + label_name varchar(16) unique not null comment '标签名称', + label_info varchar(128) comment '标签描述', + is_delete tinyint not null default 0 comment '是否删除,0:未删除,1:已删除', + create_time datetime comment '创建时间', + update_time datetime comment '更新时间', + unique key uk_label_name (label_name, is_delete) +) comment '标签表'; \ No newline at end of file diff --git a/usm-dao/sql/基础信息/uav_info.sql b/usm-dao/sql/基础信息/uav_info.sql new file mode 100644 index 0000000..3210c26 --- /dev/null +++ b/usm-dao/sql/基础信息/uav_info.sql @@ -0,0 +1,23 @@ +# 无人机基本信息表 +create table if not exists uav_info +( + id bigint unsigned not null primary key auto_increment comment 'uavId, 主键', + uav_sn varchar(64) not null comment '无人机唯一识别码', + uav_number int not null comment '无人机编号, 例如1号机, 2号机...', + uav_model int not null comment '无人机型号: enum', + configuration_info varchar(128) comment '无人机构型说明', + manufacturer varchar(64) comment '无人机生产厂家', + production_date date comment '无人机生产日期', + production_site varchar(64) comment '无人机生产地点', + production_batch tinyint comment '无人机出厂批次', + paint_mark tinyint comment '无人机涂装标识: enum', + usage_status tinyint not null comment '无人机使用状态: 0-闲置, 1-维修, 2-任务中, 3-试验, 4-交付, 5-报废, 6-库房中', + current_location varchar(64) comment '无人机当前所在地', + is_delete tinyint not null default 0 comment '是否删除,0:未删除,1:已删除', + create_time datetime comment '创建时间', + update_time datetime comment '更新时间', + unique key uniq_sn_active (uav_sn, is_delete) +# foreign key (label_id) references label (uavId) +) comment '无人机基础信息表' +; + diff --git a/usm-dao/sql/维保/device_mount_record.sql b/usm-dao/sql/维保/device_mount_record.sql new file mode 100644 index 0000000..c5a01d4 --- /dev/null +++ b/usm-dao/sql/维保/device_mount_record.sql @@ -0,0 +1,16 @@ +# 设备拆装记录 +create table device_mount_record +( + id int primary key auto_increment comment '主键id', + device_id varchar(64) not null comment '设备id', + uav_id bigint not null comment '无人机id', + mount_date date not null comment '装机日期', + unmount_date date comment '拆卸日期', + utilized_time int not null default 0 comment '已使用时间 (小时)', + expected_life int comment '预计寿命(年)', + record_status tinyint not null comment '设备状态, enum: 0-失效, 1-生效', + note text comment '备注', + create_time datetime, + update_time datetime, + index idx_uav_status (uav_id, record_status) comment '无人机所有的在用设备' +) comment '无人机设备清单表'; \ No newline at end of file diff --git a/usm-dao/sql/维保/device_replace_record.sql b/usm-dao/sql/维保/device_replace_record.sql new file mode 100644 index 0000000..c880d33 --- /dev/null +++ b/usm-dao/sql/维保/device_replace_record.sql @@ -0,0 +1,18 @@ +# 无人机维修设备更换记录 +create table uav_device_replace_record +( + id int primary key auto_increment comment '主键id', + repair_record_id int not null comment '维修记录id', + old_device_id int not null comment '旧设备id', + new_device_id int not null comment '新设备id', + is_replace tinyint not null comment '是否更换设备: 0-否, 1-是', + create_time datetime, + update_time datetime, + + key idx_repair_id (repair_record_id), + + # // TODO 2025/6/4: 删除物理外键 + foreign key (repair_record_id) references device_repair_record (id), + foreign key (old_device_id) references device_info (id), + foreign key (new_device_id) references device_info (id) +) comment '维修更换设备记录表'; \ No newline at end of file diff --git a/usm-dao/sql/维保/uav_repair_attachment.sql b/usm-dao/sql/维保/uav_repair_attachment.sql new file mode 100644 index 0000000..b97e486 --- /dev/null +++ b/usm-dao/sql/维保/uav_repair_attachment.sql @@ -0,0 +1,16 @@ +# 维修记录附件表 +create table uav_repair_attachment +( + id int primary key auto_increment comment '主键id', + repair_uni_id int not null comment '维修记录工单号', + attachment_type tinyint unsigned not null comment '附件类型, enum: 0-维修现场照片, 1-更换部件信息图片, 2-维修测试报告, 3-纸质维修记录表单图片, 255-其他', + file_name varchar(128) not null comment '文件名', + file_download_path varchar(200) not null comment '文件路径', + file_size int comment '文件大小(字节)', + upload_time datetime not null comment '上传时间', + note varchar(200) comment '备注', + create_time datetime, + update_time datetime, + index idx_repair_id (repair_uni_id), + foreign key (repair_uni_id) references uav_repair_record (id) +) comment '维修记录附件表'; \ No newline at end of file diff --git a/usm-dao/sql/维保/uav_repair_record.sql b/usm-dao/sql/维保/uav_repair_record.sql new file mode 100644 index 0000000..b630a24 --- /dev/null +++ b/usm-dao/sql/维保/uav_repair_record.sql @@ -0,0 +1,28 @@ +# 维修记录主表, 关联设备更换记录表 +create table uav_maintenance_recordrepair_record +( + id int primary key auto_increment comment '主键id', + uniId varchar(32) not null comment '工单号', + uav_id int not null comment '无人机id', + uav_sn varchar(32) not null comment '飞机唯一识别码', + uav_model int not null comment '飞机型号', + repair_date date not null comment '维修日期', + repair_location varchar(64) comment '维修地点', + repair_type tinyint unsigned not null comment '维修类型, enum: 0-计划性维修, 2-非计划性维修, 3-缺陷修复, 255-其他', + support_doc tinyint unsigned not null comment '依据文件, enum: 0-问题报告单, 1-偏离单, 255-其他', + fault_description varchar(255) not null comment '故障/缺陷描述', + repair_measures varchar(255) not null comment '维修措施', + test_result tinyint unsigned not null comment '测试结果, enum: 0-未通过, 1-已通过, 2-待检验', + repair_person varchar(50) not null comment '维修负责人员', + quality_inspector varchar(50) not null comment '质检人员', + authorized_release_person varchar(50) not null comment '授权放行人员', + status tinyint not null default 'draft' comment '工单状态, enum: 0-草稿, 1-已提交, 2-已撤销, 3-已关闭', + create_time datetime, + update_time datetime, +# create_by varchar(50), +# update_by varchar(50), +# is_deleted tinyint(1) default 0, + unique key uk_uni_id (uniId), + index idx_uav_id (uav_id), + foreign key (uav_id) references uav_basic_info (id) # todo 记得删除 +) comment '维修记录主表'; \ No newline at end of file diff --git a/usm-dao/sql/飞行记录/uav_flight_record.sql b/usm-dao/sql/飞行记录/uav_flight_record.sql new file mode 100644 index 0000000..a1687f4 --- /dev/null +++ b/usm-dao/sql/飞行记录/uav_flight_record.sql @@ -0,0 +1,51 @@ +# 飞行记录单主表 +create table uav_flight_record +( + id int not null auto_increment primary key comment 'uavId, 主键', + task_uni_id varchar(64) not null unique comment '飞行记录唯一识别码', + task_name varchar(128) not null comment '任务名称', + pilot_name varchar(128) not null comment '执飞人员列表', # 是否需要管理飞手 + uav_sn varchar(64) not null unique comment '无人机唯一识别码', + uav_id int not null comment '无人机信息id, uav_basic_info.uavId', + flight_date date not null comment '飞行日期', + + start_time time not null comment '开始时间', + end_time time not null comment '结束时间', + + flight_location varchar(128) comment '飞行地点', + flight_distance int comment '飞行距离(km)', + flight_mileage int comment '飞行里程(km)', + flight_duration int comment '飞行时长(秒)', + + flight_altitude int comment '平均飞行高度(米)', + flight_speed_avg int comment '平均飞行速度(m/s)', + + takeoff_airport_id int comment '起飞机场id', + landing_airport_id int comment '降落机场id', + + takeoff_airport_temperature int comment '起飞机场温度(°c)', + landing_airport_temperature int comment '降落机场温度(°c)', + + takeoff_wind_speed int comment '起飞风速(m/s), 1位小数', + takeoff_wind_direction int comment '起飞风向(°), 整数', + landing_wind_speed int comment '降落风速(m/s), 1位小数', + landing_wind_direction int comment '降落风向(°), 整数', + + accumulation_flight_time int comment '累计飞行时长(秒)', + accumulation_flight_count int comment '累计飞行次数', + + raw_data_form_id varchar(64) comment '原始数据表单号', + + telemetry_data_path varchar(256) comment '遥测 dat 文件路径', + telemetry_command_path varchar(256) comment '遥控指令 dat 文件路径', + flight_param_path varchar(256) comment '飞参 txt 文件路径', + + record_by varchar(32) comment '记录人', + + create_time datetime comment '创建时间', + update_time datetime comment '更新时间', +# create_by varchar(32) comment '创建人', +# update_by varchar(32) comment '更新人', + + foreign key (uav_id) references uav_basic_info (id) # todo 记得删除 +) comment '无人机飞行任务记录表'; diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/constant/TableName.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/constant/TableName.java new file mode 100644 index 0000000..73d0738 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/constant/TableName.java @@ -0,0 +1,12 @@ +package com.htfp.service.usm.dao.constant; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-11 17:03 + **/ +public final class TableName { + public static final String UAV_INFO = "uav_info"; + public static final String LABEL = "label"; + public static final String UAV_LABEL_MAPPING = "uav_label_mapping"; +} diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/LabelMapper.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/LabelMapper.java new file mode 100644 index 0000000..20bb507 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/LabelMapper.java @@ -0,0 +1,56 @@ +package com.htfp.service.usm.dao.mapper; + +import com.htfp.service.usm.dao.constant.TableName; +import com.htfp.service.usm.dao.model.entity.LabelDO; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +/** +* @author shi_y +* @description 针对表【label(标签表)】的数据库操作Mapper +* @createDate 2025-06-12 08:59:49 +* @Entity com.htfp.service.usm.dao.model.entity.LabelDO +*/ +@Mapper +public interface LabelMapper { + String TABLE_NAME = TableName.LABEL; + + /**插入标签*/ + @Insert("insert into "+TABLE_NAME+ "(id, label_name, label_info, is_delete, create_time, update_time) values (#{id}, #{labelName}, #{labelInfo}, #{isDelete}, #{createTime}, #{updateTime})") + @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") + void insertLabel(LabelDO labelDO); + + /**根据id查询标签*/ + @Select("select * from " + TABLE_NAME + " where id=#{id} and is_delete=0") + LabelDO selectLabelById(@Param("id") Integer id); + + /**根据标签名称精确查询标签*/ + @Select("select * from " + TABLE_NAME + " where label_name=#{labelName} and is_delete=0") + LabelDO selectLabelByName(@Param("labelName") String labelName); + + /**查询所有标签*/ + @Select("select * from "+TABLE_NAME+" where is_delete=0") + List selectAll(); + + /**查询所有标签id*/ + @Select("select id from " + TABLE_NAME + " where is_delete=0") + List selectAllIds(); + /**批量删除标签*/ + @Update("") + void deleteLabels(List ids); + + /**更新标签*/ + @Update("update "+TABLE_NAME+" set label_name=#{labelName}, label_info=#{labelInfo}, update_time=#{updateTime} where id=#{id} and is_delete=0") + void updateLabel(LabelDO labelDO); + + +} + + + + diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavInfoMapper.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavInfoMapper.java new file mode 100644 index 0000000..17daca0 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavInfoMapper.java @@ -0,0 +1,47 @@ +package com.htfp.service.usm.dao.mapper; + +import com.htfp.service.usm.dao.constant.TableName; +import com.htfp.service.usm.dao.model.entity.UavInfoDO; +import com.htfp.service.usm.dao.model.param.QueryUavInfoParam; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +/** +* @author shi_y +* @description 针对表【uav_info(无人机基础信息表)】的数据库操作Mapper +* @createDate 2025-06-11 16:59:09 +* @Entity com.htfp.service.usm.dao.model.entity.UavInfoDO +*/ +@Mapper +public interface UavInfoMapper { + String TABLE_NAME = TableName.UAV_INFO; + + /**根据id查询UavInfo*/ + @Select("select * from "+TABLE_NAME+" where id=#{id} and is_delete=0") + UavInfoDO selectByUavId(@Param("id") Long id); + + /**根据sn查询UavInfo*/ + @Select("select * from "+TABLE_NAME+" where uav_sn=#{uavSn} and is_delete=0") + UavInfoDO selectByUavSn(@Param("uavSn") String uavSn); + + /**根据条件查询UavInfo*/ + List selectByCondition(QueryUavInfoParam queryUavInfoParam); + + /**插入UavInfo*/ + @Insert("insert into " + TABLE_NAME + + " (uav_sn, uav_number, uav_model, configuration_info, manufacturer, production_date, production_site," + + " production_batch, paint_mark, usage_status, current_location, is_delete, create_time, update_time)" + + " values (#{uavSn}, #{uavNumber}, #{uavModel}, #{configurationInfo}, #{manufacturer}," + + " #{productionDate}, #{productionSite}, #{productionBatch}, #{paintMark}, #{usageStatus}, #{currentLocation}," + + " #{isDelete}, #{createTime}, #{updateTime})" + ) + @Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id") + Long insertUavInfo(UavInfoDO uavInfoDO); + + +} + + + + diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.java new file mode 100644 index 0000000..04edfec --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.java @@ -0,0 +1,60 @@ +package com.htfp.service.usm.dao.mapper; + +import com.htfp.service.usm.dao.constant.TableName; +import com.htfp.service.usm.dao.model.mapping.UavLabelMappingDO; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +import java.util.List; +import java.util.Set; + +/** + * @author shi_y + * @description 针对表【uav_label_mapping(无人机与标签的映射表)】的数据库操作Mapper + * @createDate 2025-06-12 11:00:52 + * @Entity com.htfp.service.usm.dao.model.mapping.UavLabelMappingDO + */ +@Mapper +public interface UavLabelMappingMapper { + String TABLE_NAME = TableName.UAV_LABEL_MAPPING; + + @Insert("") + int batchInsert(List uavLabelMappingDOList); + + @Insert("select id from uav_label_mapping where uav_id=#{uavId} and is_delete=0") + Set selectLabelIdsByUavId(@Param("uavId") Long uavId); + + + /**删除uavId对应的所有标签*/ + @Update("update " + TABLE_NAME + " set is_delete = 1, update_time = NOW() where uav_id = #{uavId} and is_delete = 0") + int deleteByUavId(Long uavId); + + /**删除指定标签*/ + @Update("" + ) + int deleteByLabelIds(List labelIdList); + + /**删除uavId的指定标签*/ + @Update("") + int deleteLabelMapping(Long uavId, List labelIdList); + +} + + + + diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/LabelDO.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/LabelDO.java new file mode 100644 index 0000000..0858ec8 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/LabelDO.java @@ -0,0 +1,45 @@ +package com.htfp.service.usm.dao.model.entity; + +import java.time.LocalDateTime; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 标签表 + * @TableName label + */ +@Data @NoArgsConstructor @AllArgsConstructor +public class LabelDO { + /** + * Id,主键 + */ + private Long id; + + /** + * 标签名称 + */ + private String labelName; + + /** + * 标签描述 + */ + private String labelInfo; + + /** + * 是否删除,0:未删除,1:已删除 + */ + private Integer isDelete; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/UavInfoDO.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/UavInfoDO.java new file mode 100644 index 0000000..9d62a5b --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/entity/UavInfoDO.java @@ -0,0 +1,91 @@ +package com.htfp.service.usm.dao.model.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 无人机基础信息表 + * @TableName uav_info + */ +@Data @NoArgsConstructor @AllArgsConstructor +public class UavInfoDO { + /** + * uavId, 主键 + */ + private Long id; + + /** + * 无人机唯一识别码 + */ + private String uavSn; + + /** + * 无人机编号, 例如1号机, 2号机... + */ + private Integer uavNumber; + + /** + * 无人机型号: enum + */ + private Integer uavModel; + + /** + * 无人机构型说明 + */ + private String configurationInfo; + + /** + * 无人机生产厂家 + */ + private String manufacturer; + + /** + * 无人机生产日期 + */ + private LocalDate productionDate; + + /** + * 无人机生产地点 + */ + private String productionSite; + + /** + * 无人机出厂批次 + */ + private Integer productionBatch; + + /** + * 无人机涂装标识: enum + */ + private Integer paintMark; + + /** + * 无人机使用状态: 0-闲置, 1-维修, 2-任务中, 3-试验, 4-交付, 5-报废, 6-库房中 + */ + private Integer usageStatus; + + /** + * 无人机当前所在地 + */ + private String currentLocation; + + /** + * 是否删除,0:未删除,1:已删除 + */ + private Integer isDelete; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/model/mapping/UavLabelMappingDO.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/mapping/UavLabelMappingDO.java new file mode 100644 index 0000000..f2b9db3 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/mapping/UavLabelMappingDO.java @@ -0,0 +1,44 @@ +package com.htfp.service.usm.dao.model.mapping; + +import java.time.LocalDateTime; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 无人机与标签的映射表 + * @TableName uav_label_mapping + */ +@Data @AllArgsConstructor @NoArgsConstructor +public class UavLabelMappingDO { + /** + * 主键id + */ + private Long id; + + /** + * 无人机id + */ + private Long uavId; + + /** + * 标签id + */ + private Long labelId; + + /** + * 是否删除, 0-否, 1-是 + */ + private Integer isDelete; + + /** + * 打标签时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryPageInfoParam.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryPageInfoParam.java new file mode 100644 index 0000000..ebc9530 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryPageInfoParam.java @@ -0,0 +1,20 @@ +package com.htfp.service.usm.dao.model.param; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author shi_y + * @createDate 2023/9/7 + * @description 分页查询参数 + */ +@Data +public class QueryPageInfoParam { + private Integer pageNum; // 当前页码 + private Integer pageSize; // 每页数量 + private LocalDateTime createStartTime; + private LocalDateTime createEndTime; + private Integer type; + private Integer status; +} diff --git a/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryUavInfoParam.java b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryUavInfoParam.java new file mode 100644 index 0000000..2e5a479 --- /dev/null +++ b/usm-dao/src/main/java/com/htfp/service/usm/dao/model/param/QueryUavInfoParam.java @@ -0,0 +1,84 @@ +package com.htfp.service.usm.dao.model.param; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * @author : shi_y + * @description : 无人机信息查询参数 + * @createTime : 2025-06-11 16:02 + **/ + +@EqualsAndHashCode(callSuper = true) +@Data @NoArgsConstructor @AllArgsConstructor +public class QueryUavInfoParam extends QueryPageInfoParam { + /** + * id, 主键 + */ + private Integer id; + + /** + * 无人机唯一识别码 + */ + private String uavSn; + + /** + * 无人机编号, 例如1号机, 2号机... + */ + private Integer uavNumber; + + /** + * 无人机型号: enum + */ + private Integer uavModel; + + /** + * 无人机构型说明 + */ + private String configurationInfo; + + /** + * 无人机生产厂家 + */ + private String manufacturer; + + /** + * 无人机生产日期 + */ + private LocalDate productionDate; + + /** + * 无人机生产地点 + */ + private String productionSite; + + /** + * 无人机出厂批次 + */ + private Integer productionBatch; + + /** + * 无人机涂装标识: enum + */ + private Integer paintMark; + + /** + * 无人机使用状态: 0-闲置, 1-维修, 2-任务中, 3-试验, 4-交付, 5-报废, 6-库房中 + */ + private Integer usageStatus; + + /** + * 无人机当前所在地 + */ + private String currentLocation; + + /** + * 是否删除,0:未删除,1:已删除 + */ + private Integer isDelete = 0; // 默认查询未删除参数 +} diff --git a/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/LabelMapper.xml b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/LabelMapper.xml new file mode 100644 index 0000000..d09d827 --- /dev/null +++ b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/LabelMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + id,label_name,label_info,is_delete,create_time,update_time + + diff --git a/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavInfoMapper.xml b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavInfoMapper.xml new file mode 100644 index 0000000..1200d69 --- /dev/null +++ b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavInfoMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + id,uav_sn,uav_number,uav_model,configuration_info,manufacturer, + production_date,production_site,production_batch,paint_mark,usage_status, + current_location,is_delete,create_time,update_time + + + + diff --git a/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.xml b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.xml new file mode 100644 index 0000000..50d41b5 --- /dev/null +++ b/usm-dao/src/main/resources/com/htfp/service/usm/dao/mapper/UavLabelMappingMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + id,uav_id,label_id,is_deleted,create_time,update_time + + diff --git a/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/LabelMapperTest.java b/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/LabelMapperTest.java new file mode 100644 index 0000000..8813163 --- /dev/null +++ b/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/LabelMapperTest.java @@ -0,0 +1,41 @@ +package com.htfp.service.usm.dao.mapper; + +import com.htfp.service.usm.dao.model.entity.LabelDO; +import org.junit.jupiter.api.Test; +import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 14:00 + **/ +@MybatisTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(classes = TestConfig.class) // 加载指定的配置类 +// @TestPropertySource("classpath:application-test.yml") :@TestPropertySource 默认只支持 .properties 文件。如果使用 .yml,需要结合 @ContextConfiguration + 自定义加载器,较为复杂。 +@ActiveProfiles("test") +class LabelMapperTest { + + @Autowired + LabelMapper labelMapper; + @Test + void verifyDriver() throws Exception { + Class.forName("com.mysql.cj.jdbc.Driver"); + } + @Test + void selectLabelById() { + Object labelDO = labelMapper.selectLabelById(5); + } + + @Test + void selectLabelByName() { + } +} \ No newline at end of file diff --git a/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/TestConfig.java b/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/TestConfig.java new file mode 100644 index 0000000..20239ac --- /dev/null +++ b/usm-dao/src/test/java/com/htfp/service/usm/dao/mapper/TestConfig.java @@ -0,0 +1,14 @@ +package com.htfp.service.usm.dao.mapper; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Configuration; + +/** + * @author : shi_y + * @description : + * @createTime : 2025-06-12 14:04 + **/ +@Configuration +@MapperScan("com.htfp.service.usm.dao.mapper") +public class TestConfig { +} diff --git a/usm-dao/src/test/resources/application-test.yml b/usm-dao/src/test/resources/application-test.yml new file mode 100644 index 0000000..8b6e3aa --- /dev/null +++ b/usm-dao/src/test/resources/application-test.yml @@ -0,0 +1,16 @@ +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/usm?characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true + username: root + password: 1234 + driver-class-name: com.mysql.cj.jdbc.Driver +mybatis: + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + mapper-locations: + - classpath*:com/htfp/service/dao/mapper/*.xml + type-aliases-package: com.htfp.service.usm.dao.model +logging: + level: + org.springframework.jdbc.support.JdbcTransactionManager: debug \ No newline at end of file