diff --git a/2025-07-29/.jpg/001/row7/column8/15/143153-C2-iieee.jpg b/2025-07-29/.jpg/001/row7/column8/15/143153-C2-iieee.jpg deleted file mode 100644 index 3118b7b..0000000 Binary files a/2025-07-29/.jpg/001/row7/column8/15/143153-C2-iieee.jpg and /dev/null differ diff --git a/2025-07-29/.jpg/001/row7/column8/15/143159-C3-ahidb.jpg b/2025-07-29/.jpg/001/row7/column8/15/143159-C3-ahidb.jpg deleted file mode 100644 index 4d46368..0000000 Binary files a/2025-07-29/.jpg/001/row7/column8/15/143159-C3-ahidb.jpg and /dev/null differ diff --git a/2025-07-29/.jpg/001/row7/column8/15/143204-C4-heagg.jpg b/2025-07-29/.jpg/001/row7/column8/15/143204-C4-heagg.jpg deleted file mode 100644 index 78cd7bb..0000000 Binary files a/2025-07-29/.jpg/001/row7/column8/15/143204-C4-heagg.jpg and /dev/null differ diff --git a/2025-07-29/.jpg/001/row7/column8/15/144201-C4-dejbd.jpg b/2025-07-29/.jpg/001/row7/column8/15/144201-C4-dejbd.jpg deleted file mode 100644 index b0292b5..0000000 Binary files a/2025-07-29/.jpg/001/row7/column8/15/144201-C4-dejbd.jpg and /dev/null differ diff --git a/libs/code_scan/BarcodeDetectorJNI.dll b/libs/code_scan/BarcodeDetectorJNI.dll deleted file mode 100644 index 360865b..0000000 Binary files a/libs/code_scan/BarcodeDetectorJNI.dll and /dev/null differ diff --git a/libs/code_scan/BarcodeDetectorJNI_bak.dll b/libs/code_scan/BarcodeDetectorJNI_bak.dll deleted file mode 100644 index 24507ff..0000000 Binary files a/libs/code_scan/BarcodeDetectorJNI_bak.dll and /dev/null differ diff --git a/libs/code_scan/libCyclops.dll b/libs/code_scan/libCyclops.dll deleted file mode 100644 index 64c0c4e..0000000 Binary files a/libs/code_scan/libCyclops.dll and /dev/null differ diff --git a/libs/code_scan/libiconv.dll b/libs/code_scan/libiconv.dll deleted file mode 100644 index a31664d..0000000 Binary files a/libs/code_scan/libiconv.dll and /dev/null differ diff --git a/libs/code_scan/libnlopt-0.dll b/libs/code_scan/libnlopt-0.dll deleted file mode 100644 index beaff3a..0000000 Binary files a/libs/code_scan/libnlopt-0.dll and /dev/null differ diff --git a/libs/code_scan/lpv.dll b/libs/code_scan/lpv.dll deleted file mode 100644 index cb088b5..0000000 Binary files a/libs/code_scan/lpv.dll and /dev/null differ diff --git a/libs/code_scan/opencv_world341.dll b/libs/code_scan/opencv_world341.dll deleted file mode 100644 index 06cac75..0000000 Binary files a/libs/code_scan/opencv_world341.dll and /dev/null differ diff --git a/pom.xml b/pom.xml index 95a6dfd..f730dd0 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ yudao-module-infra yudao-module-logistics yudao-module-camera + yudao-module-annotation diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java index bc7ff8a..1adbfc0 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/TokenAuthenticationFilter.java @@ -63,7 +63,6 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter { return; } } - // 继续过滤链 chain.doFilter(request, response); } diff --git a/yudao-module-annotation/pom.xml b/yudao-module-annotation/pom.xml new file mode 100644 index 0000000..ecce719 --- /dev/null +++ b/yudao-module-annotation/pom.xml @@ -0,0 +1,23 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-module-annotation-biz + yudao-module-annotation-api + + yudao-module-annotation + pom + + ${project.artifactId} + + 注解模块 + + + diff --git a/yudao-module-annotation/yudao-module-annotation-api/pom.xml b/yudao-module-annotation/yudao-module-annotation-api/pom.xml new file mode 100644 index 0000000..2121374 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.boot + yudao-module-annotation + ${revision} + + 4.0.0 + yudao-module-annotation-api + jar + + ${project.artifactId} + + system 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + diff --git a/yudao-module-annotation/yudao-module-annotation-api/src/main/java/cn/iocoder/yudao/module/annotation/enums/ErrorCodeConstants_手动操作.java b/yudao-module-annotation/yudao-module-annotation-api/src/main/java/cn/iocoder/yudao/module/annotation/enums/ErrorCodeConstants_手动操作.java new file mode 100644 index 0000000..196b3aa --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-api/src/main/java/cn/iocoder/yudao/module/annotation/enums/ErrorCodeConstants_手动操作.java @@ -0,0 +1,3 @@ +// TODO 待办:请将下面的错误码复制到 yudao-module-annotation-api 模块的 ErrorCodeConstants 类中。注意,请给“TODO 补充编号”设置一个错误码编号!!! +// ========== 类别 TODO 补充编号 ========== +//ErrorCode TYPES_NOT_EXISTS = new ErrorCode(TODO 补充编号, "类别不存在"); diff --git a/yudao-module-annotation/yudao-module-annotation-biz/pom.xml b/yudao-module-annotation/yudao-module-annotation-biz/pom.xml new file mode 100644 index 0000000..b337793 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/pom.xml @@ -0,0 +1,163 @@ + + + + cn.iocoder.boot + yudao-module-annotation + ${revision} + + 4.0.0 + yudao-module-annotation-biz + jar + + ${project.artifactId} + + system 模块 API,暴露给其它模块调用 + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + + cn.iocoder.boot + yudao-module-infra-api + ${revision} + + + + + net.java.dev.jna + jna + 5.13.0 + + + net.java.dev.jna + jna-platform + 5.13.0 + + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-data-permission + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + org.springframework.boot + spring-boot-starter-validation + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-job + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mq + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + + org.springframework.boot + spring-boot-starter-mail + + + + + com.xingyuv + spring-boot-starter-justauth + + + + com.github.binarywang + wx-java-mp-spring-boot-starter + + + com.github.binarywang + wx-java-miniapp-spring-boot-starter + + + + com.aliyun + aliyun-java-sdk-core + + + com.aliyun + aliyun-java-sdk-dysmsapi + + + com.tencentcloudapi + tencentcloud-sdk-java-sms + + + + com.xingyuv + spring-boot-starter-captcha-plus + + + + org.dromara.hutool + hutool-extra + + + cn.iocoder.boot + yudao-module-system-biz + 2.0.1-snapshot + compile + + + + cn.iocoder.boot + yudao-module-camera-api + 2.0.1-snapshot + compile + + + + + diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/config/AnnotationWebConfiguration.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/config/AnnotationWebConfiguration.java new file mode 100644 index 0000000..829cd85 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/config/AnnotationWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.annotation.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * infra 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class AnnotationWebConfiguration { + + /** + * infra 模块的 API 分组 + */ + @Bean + public GroupedOpenApi AnnotationGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("annotation"); + } + +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/DatasController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/DatasController.java new file mode 100644 index 0000000..fe83678 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/DatasController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.datas; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasRespVO; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.datas.DatasDO; +import cn.iocoder.yudao.module.annotation.service.datas.DatasService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 数据集管理") +@RestController +@RequestMapping("/annotation/datas") +@Validated +public class DatasController { + + @Resource + private DatasService datasService; + + @PostMapping("/create") + @Operation(summary = "创建数据集管理") + @PreAuthorize("@ss.hasPermission('annotation:datas:create')") + public CommonResult createDatas(@Valid @RequestBody DatasSaveReqVO createReqVO) { + return success(datasService.createDatas(createReqVO)); + } + + + @PutMapping("/update") + @Operation(summary = "更新数据集管理") + @PreAuthorize("@ss.hasPermission('annotation:datas:update')") + public CommonResult updateDatas(@Valid @RequestBody DatasSaveReqVO updateReqVO) { + datasService.updateDatas(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除数据集管理") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:datas:delete')") + public CommonResult deleteDatas(@RequestParam("id") Integer id) { + datasService.deleteDatas(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得数据集管理") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult getDatas(@RequestParam("id") Integer id) { + DatasDO datas = datasService.getDatas(id); + return success(BeanUtils.toBean(datas, DatasRespVO.class)); + } + + @PostMapping("/list") + @Operation(summary = "获得数据集管理列表") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult> list() { + List result = datasService.list(); + return success(result); + } + + @GetMapping("/page") + @Operation(summary = "获得数据集管理分页") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult> getDatasPage(@Valid DatasPageReqVO pageReqVO) { + PageResult pageResult = datasService.getDatasPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DatasRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出数据集管理 Excel") + @PreAuthorize("@ss.hasPermission('annotation:datas:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportDatasExcel(@Valid DatasPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = datasService.getDatasPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "数据集管理.xls", "数据", DatasRespVO.class, + BeanUtils.toBean(list, DatasRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasPageReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasPageReqVO.java new file mode 100644 index 0000000..2e03a45 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasPageReqVO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.datas.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 数据集管理分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class DatasPageReqVO extends PageParam { + + @Schema(description = "项目名称", example = "芋艿") + private String name; + + @Schema(description = "描述", example = "你猜") + private String description; + + @Schema(description = "类型,还未标注,正在标注,正在训练,训练完成", example = "1") + private String status; + + @Schema(description = "路径") + private String path; + + @Schema(description = "图片总数", example = "4380") + private Long count; + + @Schema(description = "识别类型", example = "2") + private String type; + + @Schema(description = "进度") + private Integer progress; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasRespVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasRespVO.java new file mode 100644 index 0000000..e025682 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasRespVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.datas.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 数据集管理 Response VO") +@Data +@ExcelIgnoreUnannotated +public class DatasRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "4113") + @ExcelProperty("id") + private Integer id; + + @Schema(description = "项目名称", example = "芋艿") + @ExcelProperty("项目名称") + private String name; + + @Schema(description = "描述", example = "你猜") + @ExcelProperty("描述") + private String description; + + @Schema(description = "类型,还未标注,正在标注,正在训练,训练完成", example = "1") + @ExcelProperty("类型,还未标注,正在标注,正在训练,训练完成") + private String status; + + @Schema(description = "路径") + @ExcelProperty("路径") + private String path; + + @Schema(description = "图片总数", example = "4380") + @ExcelProperty("图片总数") + private Long count; + + @Schema(description = "识别类型", example = "2") + @ExcelProperty("识别类型") + private String type; + + @Schema(description = "进度") + @ExcelProperty("进度") + private Integer progress; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasSaveReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasSaveReqVO.java new file mode 100644 index 0000000..6ffa994 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/datas/vo/DatasSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.datas.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 数据集管理新增/修改 Request VO") +@Data +public class DatasSaveReqVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "4113") + private Integer id; + + @Schema(description = "项目名称", example = "芋艿") + private String name; + + @Schema(description = "描述", example = "你猜") + private String description; + + @Schema(description = "类型,还未标注,正在标注,正在训练,训练完成", example = "1") + private String status; + + @Schema(description = "路径") + private String path; + + @Schema(description = "图片总数", example = "4380") + private Long count; + + @Schema(description = "识别类型", example = "2") + private String type; + + @Schema(description = "进度") + private Integer progress; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkController.java new file mode 100644 index 0000000..096141a --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkController.java @@ -0,0 +1,109 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.mark; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkRespVO; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkDO; +import cn.iocoder.yudao.module.annotation.service.mark.MarkService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 标注") +@RestController +@RequestMapping("/annotation/mark") +@Validated +public class MarkController { + + @Resource + private MarkService markService; + + @PostMapping("/create") + @Operation(summary = "创建标注") + @PreAuthorize("@ss.hasPermission('annotation:mark:create')") + public CommonResult createMark(@Valid @RequestBody MarkSaveReqVO createReqVO) { + return success(markService.createMark(createReqVO)); + } + + @PutMapping("/update-status") + @Operation(summary = "更新类别") + @PreAuthorize("@ss.hasPermission('annotation:types:update')") + public CommonResult updateStatus(@Valid @RequestBody MarkSaveReqVO updateReqVO) { + markService.updateMark(updateReqVO); + return success(true); + } + + @PostMapping("/list") + @Operation(summary = "获得图片列表") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult> list(@Valid @RequestBody MarkSaveReqVO createReqVO) { + List result = markService.list(new QueryWrapper().eq("data_id",createReqVO.getDataId())); + return success(result); + } + @PutMapping("/update") + @Operation(summary = "更新标注") + @PreAuthorize("@ss.hasPermission('annotation:mark:update')") + public CommonResult updateMark(@Valid @RequestBody MarkSaveReqVO updateReqVO) { + markService.updateMark(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除标注") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:mark:delete')") + public CommonResult deleteMark(@RequestParam("id") Integer id) { + markService.deleteMark(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得标注") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('annotation:mark:query')") + public CommonResult getMark(@RequestParam("id") Integer id) { + MarkDO mark = markService.getMark(id); + return success(BeanUtils.toBean(mark, MarkRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得标注分页") + @PreAuthorize("@ss.hasPermission('annotation:mark:query')") + public CommonResult> getMarkPage(@Valid MarkPageReqVO pageReqVO) { + PageResult pageResult = markService.getMarkPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MarkRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出标注 Excel") + @PreAuthorize("@ss.hasPermission('annotation:mark:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportMarkExcel(@Valid MarkPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = markService.getMarkPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "标注.xls", "数据", MarkRespVO.class, + BeanUtils.toBean(list, MarkRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkInfoController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkInfoController.java new file mode 100644 index 0000000..4bb33c3 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/MarkInfoController.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.mark; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkInfoDO; +import cn.iocoder.yudao.module.annotation.service.MarkInfo.MarkInfoService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 标注详情") +@RestController +@RequestMapping("/annotation/markInfo") +@Validated +public class MarkInfoController { + + @Resource + private MarkInfoService markService; + + @PostMapping("/create") + @Operation(summary = "创建标注详情") + @PreAuthorize("@ss.hasPermission('annotation:mark:create')") + public CommonResult createMark(@Valid @RequestBody List createReqVO) { + for (MarkInfoDO markInfoDO : createReqVO){ + markInfoDO.setAnnotationDataString(markInfoDO.getAnnotationData().toString()); + markService.saveOrUpdate(markInfoDO); + } + return success(1); + } + + @PostMapping("/list") + @Operation(summary = "获得标注详情列表") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult> list(@RequestParam("markId") Integer markId) { + List result = markService.list(new QueryWrapper() + .eq("mark_id",markId)); + return success(result); + } + + + @DeleteMapping("/delete") + @Operation(summary = "删除标注详情") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:mark:delete')") + public CommonResult deleteMark(@RequestParam("id") Integer id) { + markService.deleteMarkInfo(id); + return success(true); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkPageReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkPageReqVO.java new file mode 100644 index 0000000..0b0e14e --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.mark.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 标注分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MarkPageReqVO extends PageParam { + + @Schema(description = "项目id", example = "4064") + private Integer dataId; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkRespVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkRespVO.java new file mode 100644 index 0000000..6a4bb8e --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkRespVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.mark.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 标注 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MarkRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "15739") + @ExcelProperty("id") + private Integer id; + + @Schema(description = "path") + @ExcelProperty("path") + private String path; + + @Schema(description = "项目id", example = "4064") + @ExcelProperty("项目id") + private Integer dataId; + + @Schema(description = "标注,类型是[{对象}],class_id,center_x,center_y,width,height,polygon_points,angle") + @ExcelProperty("标注,类型是[{对象}],class_id,center_x,center_y,width,height,polygon_points,angle") + private String annotation; + + @Schema(description = "1.标注完成,0,未标注", example = "1") + @ExcelProperty("1.标注完成,0,未标注") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkSaveReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkSaveReqVO.java new file mode 100644 index 0000000..8dd9cca --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/mark/vo/MarkSaveReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.mark.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 标注新增/修改 Request VO") +@Data +public class MarkSaveReqVO { + private Integer dataId; + private Integer id; + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/TrainController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/TrainController.java new file mode 100644 index 0000000..d0dcef1 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/TrainController.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.train; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.annotation.controller.admin.train.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.train.TrainDO; +import cn.iocoder.yudao.module.annotation.service.train.TrainService; + +@Tag(name = "管理后台 - 训练") +@RestController +@RequestMapping("/annotation/train") +@Validated +public class TrainController { + + @Resource + private TrainService trainService; + + @PostMapping("/create") + @Operation(summary = "创建训练") + @PreAuthorize("@ss.hasPermission('annotation:train:create')") + public CommonResult createTrain(@Valid @RequestBody TrainSaveReqVO createReqVO) { + return success(trainService.createTrain(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新训练") + @PreAuthorize("@ss.hasPermission('annotation:train:update')") + public CommonResult updateTrain(@Valid @RequestBody TrainSaveReqVO updateReqVO) { + trainService.updateTrain(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除训练") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:train:delete')") + public CommonResult deleteTrain(@RequestParam("id") Integer id) { + trainService.deleteTrain(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得训练") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('annotation:train:query')") + public CommonResult getTrain(@RequestParam("id") Integer id) { + TrainDO train = trainService.getTrain(id); + return success(BeanUtils.toBean(train, TrainRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得训练分页") + @PreAuthorize("@ss.hasPermission('annotation:train:query')") + public CommonResult> getTrainPage(@Valid TrainPageReqVO pageReqVO) { + PageResult pageResult = trainService.getTrainPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TrainRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出训练 Excel") + @PreAuthorize("@ss.hasPermission('annotation:train:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTrainExcel(@Valid TrainPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = trainService.getTrainPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "训练.xls", "数据", TrainRespVO.class, + BeanUtils.toBean(list, TrainRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainPageReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainPageReqVO.java new file mode 100644 index 0000000..09efe8a --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainPageReqVO.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.train.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 训练分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TrainPageReqVO extends PageParam { + + @Schema(description = "项目id", example = "14776") + private Integer dataId; + + @Schema(description = "训练集比例") + private Integer train; + + @Schema(description = "验证图像比例") + private Integer val; + + @Schema(description = "测试图像比例") + private Integer test; + + @Schema(description = "轮次") + private Integer round; + + @Schema(description = "批次大小") + private Integer size; + + @Schema(description = "图片大小(正方向,大于这个值进行缩放,小于这个值进行放大,不是正方形将图片周围涂黑)") + private Integer imageSize; + + @Schema(description = "预选训练模型") + private String modelPath; + + @Schema(description = "训练图片路径") + private String path; + + @Schema(description = "类型,使用哪个gpu", example = "1") + private Integer trainType; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainRespVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainRespVO.java new file mode 100644 index 0000000..8dddbda --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.train.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 训练 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TrainRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32206") + @ExcelProperty("id") + private Integer id; + + @Schema(description = "项目id", example = "14776") + @ExcelProperty("项目id") + private Integer dataId; + + @Schema(description = "训练集比例") + @ExcelProperty("训练集比例") + private Integer train; + + @Schema(description = "验证图像比例") + @ExcelProperty("验证图像比例") + private Integer val; + + @Schema(description = "测试图像比例") + @ExcelProperty("测试图像比例") + private Integer test; + + @Schema(description = "轮次") + @ExcelProperty("轮次") + private Integer round; + + @Schema(description = "批次大小") + @ExcelProperty("批次大小") + private Integer size; + + @Schema(description = "图片大小(正方向,大于这个值进行缩放,小于这个值进行放大,不是正方形将图片周围涂黑)") + @ExcelProperty("图片大小(正方向,大于这个值进行缩放,小于这个值进行放大,不是正方形将图片周围涂黑)") + private Integer imageSize; + + @Schema(description = "预选训练模型") + @ExcelProperty("预选训练模型") + private String modelPath; + + @Schema(description = "训练图片路径") + @ExcelProperty("训练图片路径") + private String path; + + @Schema(description = "类型,使用哪个gpu", example = "1") + @ExcelProperty("类型,使用哪个gpu") + private Integer trainType; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainSaveReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainSaveReqVO.java new file mode 100644 index 0000000..a42b4f4 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/train/vo/TrainSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.train.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 训练新增/修改 Request VO") +@Data +public class TrainSaveReqVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "32206") + private Integer id; + + @Schema(description = "项目id", example = "14776") + private Integer dataId; + + @Schema(description = "训练集比例") + private Integer train; + + @Schema(description = "验证图像比例") + private Integer val; + + @Schema(description = "测试图像比例") + private Integer test; + + @Schema(description = "轮次") + private Integer round; + + @Schema(description = "批次大小") + private Integer size; + + @Schema(description = "图片大小(正方向,大于这个值进行缩放,小于这个值进行放大,不是正方形将图片周围涂黑)") + private Integer imageSize; + + @Schema(description = "预选训练模型") + private String modelPath; + + @Schema(description = "训练图片路径") + private String path; + + @Schema(description = "类型,使用哪个gpu", example = "1") + private Integer trainType; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/TrainResultController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/TrainResultController.java new file mode 100644 index 0000000..13e9efe --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/TrainResultController.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.trainresult; + +import org.springframework.web.bind.annotation.*; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.security.access.prepost.PreAuthorize; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Operation; + +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; +import java.util.*; +import java.io.IOException; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; + +import cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.trainresult.TrainResultDO; +import cn.iocoder.yudao.module.annotation.service.trainresult.TrainResultService; + +@Tag(name = "管理后台 - 识别结果") +@RestController +@RequestMapping("/annotation/train-result") +@Validated +public class TrainResultController { + + @Resource + private TrainResultService trainResultService; + + @PostMapping("/create") + @Operation(summary = "创建识别结果") + @PreAuthorize("@ss.hasPermission('annotation:train-result:create')") + public CommonResult createTrainResult(@Valid @RequestBody TrainResultSaveReqVO createReqVO) { + return success(trainResultService.createTrainResult(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新识别结果") + @PreAuthorize("@ss.hasPermission('annotation:train-result:update')") + public CommonResult updateTrainResult(@Valid @RequestBody TrainResultSaveReqVO updateReqVO) { + trainResultService.updateTrainResult(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除识别结果") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:train-result:delete')") + public CommonResult deleteTrainResult(@RequestParam("id") Integer id) { + trainResultService.deleteTrainResult(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得识别结果") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('annotation:train-result:query')") + public CommonResult getTrainResult(@RequestParam("id") Integer id) { + TrainResultDO trainResult = trainResultService.getTrainResult(id); + return success(BeanUtils.toBean(trainResult, TrainResultRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得识别结果分页") + @PreAuthorize("@ss.hasPermission('annotation:train-result:query')") + public CommonResult> getTrainResultPage(@Valid TrainResultPageReqVO pageReqVO) { + PageResult pageResult = trainResultService.getTrainResultPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TrainResultRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出识别结果 Excel") + @PreAuthorize("@ss.hasPermission('annotation:train-result:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTrainResultExcel(@Valid TrainResultPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = trainResultService.getTrainResultPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "识别结果.xls", "数据", TrainResultRespVO.class, + BeanUtils.toBean(list, TrainResultRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultPageReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultPageReqVO.java new file mode 100644 index 0000000..9184cdf --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 识别结果分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TrainResultPageReqVO extends PageParam { + + @Schema(description = "数据集", example = "196") + private Integer dataId; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultRespVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultRespVO.java new file mode 100644 index 0000000..f335dd8 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultRespVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 识别结果 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TrainResultRespVO { + + @Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "15312") + @ExcelProperty("id") + private Integer id; + + @Schema(description = "训练id", example = "27530") + @ExcelProperty("训练id") + private Integer trainId; + + @Schema(description = "输出路径") + @ExcelProperty("输出路径") + private String path; + + @Schema(description = "识别结果rate") + @ExcelProperty("识别结果rate") + private String rate; + + @Schema(description = "修改时间") + @ExcelProperty("修改时间") + private LocalDateTime updateTime; + + @Schema(description = "数据集", example = "196") + @ExcelProperty("数据集") + private Integer dataId; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultSaveReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultSaveReqVO.java new file mode 100644 index 0000000..c62fdaf --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/trainresult/vo/TrainResultSaveReqVO.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; + +@Schema(description = "管理后台 - 识别结果新增/修改 Request VO") +@Data +public class TrainResultSaveReqVO { + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/TypesController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/TypesController.java new file mode 100644 index 0000000..c4dc231 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/TypesController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.types; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkSaveReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesRespVO; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.types.TypesDO; +import cn.iocoder.yudao.module.annotation.service.types.TypesService; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 类别") +@RestController +@RequestMapping("/annotation/types") +@Validated +public class TypesController { + + @Resource + private TypesService typesService; + + @PostMapping("/create") + @Operation(summary = "创建类别") + @PreAuthorize("@ss.hasPermission('annotation:types:create')") + public CommonResult createTypes(@Valid @RequestBody TypesSaveReqVO createReqVO) { + return success(typesService.createTypes(createReqVO)); + } + + @PostMapping("/list") + @Operation(summary = "获得类别列表") + @PreAuthorize("@ss.hasPermission('annotation:datas:query')") + public CommonResult> list(@Valid @RequestBody MarkSaveReqVO createReqVO) { + List result = typesService.list(new QueryWrapper().eq("data_id",createReqVO.getDataId())); + return success(result); + } + @PutMapping("/update") + @Operation(summary = "更新类别") + @PreAuthorize("@ss.hasPermission('annotation:types:update')") + public CommonResult updateTypes(@Valid @RequestBody TypesSaveReqVO updateReqVO) { + typesService.updateTypes(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除类别") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('annotation:types:delete')") + public CommonResult deleteTypes(@RequestParam("id") Integer id) { + typesService.deleteTypes(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得类别") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('annotation:types:query')") + public CommonResult getTypes(@RequestParam("id") Integer id) { + TypesDO types = typesService.getTypes(id); + return success(BeanUtils.toBean(types, TypesRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得类别分页") + @PreAuthorize("@ss.hasPermission('annotation:types:query')") + public CommonResult> getTypesPage(@Valid TypesPageReqVO pageReqVO) { + PageResult pageResult = typesService.getTypesPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, TypesRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出类别 Excel") + @PreAuthorize("@ss.hasPermission('annotation:types:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportTypesExcel(@Valid TypesPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = typesService.getTypesPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "类别.xls", "数据", TypesRespVO.class, + BeanUtils.toBean(list, TypesRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesPageReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesPageReqVO.java new file mode 100644 index 0000000..bfa6ba5 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesPageReqVO.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.types.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 类别分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class TypesPageReqVO extends PageParam { + + @Schema(description = "名称", example = "李四") + private String name; + + @Schema(description = "项目id", example = "1481") + private Integer dataId; + + @Schema(description = "index") + private Integer index; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + + @Schema(description = "颜色") + private String color; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesRespVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesRespVO.java new file mode 100644 index 0000000..bf26733 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesRespVO.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.types.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; + +@Schema(description = "管理后台 - 类别 Response VO") +@Data +@ExcelIgnoreUnannotated +public class TypesRespVO { + + @Schema(description = "id", example = "9740") + @ExcelProperty("id") + private Integer id; + + @Schema(description = "名称", example = "李四") + @ExcelProperty("名称") + private String name; + + @Schema(description = "项目id", example = "1481") + @ExcelProperty("项目id") + private Integer dataId; + + @Schema(description = "index") + @ExcelProperty("index") + private Integer index; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "颜色") + @ExcelProperty("颜色") + private String color; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesSaveReqVO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesSaveReqVO.java new file mode 100644 index 0000000..d5e8d7d --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/types/vo/TypesSaveReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.types.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 类别新增/修改 Request VO") +@Data +public class TypesSaveReqVO { + + @Schema(description = "id", example = "9740") + private Integer id; + + @Schema(description = "名称", example = "李四") + private String name; + + @Schema(description = "项目id", example = "1481") + private Integer dataId; + + @Schema(description = "index") + private Integer index; + @Schema(description = "index") + private Integer status; + + @Schema(description = "颜色") + private String color; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/yolo/YoloController.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/yolo/YoloController.java new file mode 100644 index 0000000..75de0ac --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/controller/admin/yolo/YoloController.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.controller.admin.yolo; + +import cn.iocoder.yudao.module.annotation.dal.yolo.ExportResult; +import cn.iocoder.yudao.module.annotation.dal.yolo.PredictionResult; +import cn.iocoder.yudao.module.annotation.dal.yolo.ValidationResult; +import cn.iocoder.yudao.module.annotation.dal.yolo.YoloConfig; +import cn.iocoder.yudao.module.annotation.service.yolo.AsyncYoloService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.concurrent.CompletableFuture; + +// YoloController.java +@RestController +@RequestMapping("/api/yolo") +public class YoloController { + + private final AsyncYoloService yoloService; + + public YoloController(AsyncYoloService yoloService) { + this.yoloService = yoloService; + } + + @PostMapping("/train") + public ResponseEntity trainAsync(@RequestBody YoloConfig config) { + yoloService.trainAsync(config) + .thenAccept(result -> { + if (result.isSuccess()) { + System.out.println("Training completed successfully"); + } else { + System.err.println("Training failed: " + result.getMessage()); + } + }); + return ResponseEntity.ok("Training started asynchronously"); + } + + @PostMapping("/validate") + public CompletableFuture validateAsync(@RequestBody YoloConfig config) { + return yoloService.validateAsync(config); + } + + @PostMapping("/predict") + public CompletableFuture predictAsync( + @RequestBody YoloConfig config, + @RequestParam String imagePath) { + return yoloService.predictAsync(config, imagePath); + } + + @PostMapping("/export") + public CompletableFuture exportAsync( + @RequestBody YoloConfig config, + @RequestParam String format) { + return yoloService.exportAsync(config, format); + } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/datas/DatasDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/datas/DatasDO.java new file mode 100644 index 0000000..73ea825 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/datas/DatasDO.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.datas; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 数据集管理 DO + * + * @author 管理员 + */ +@TableName("annotation_datas") +@KeySequence("annotation_datas_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DatasDO extends BaseDO { + + /** + * id + */ + @TableId + private Integer id; + /** + * 项目名称 + */ + private String name; + /** + * 描述 + */ + private String description; + /** + * 类型,还未标注,正在标注,正在训练,训练完成 + */ + private String status; + /** + * 路径 + */ + private String path; + /** + * 图片总数 + */ + private Long count; + /** + * 识别类型 + */ + private String type; + /** + * 进度 + */ + private double progress; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/AnnotationItem.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/AnnotationItem.java new file mode 100644 index 0000000..4b3664e --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/AnnotationItem.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.mark; + +import lombok.Data; + +@Data +public class AnnotationItem { + private Integer class_id; + private Double center_x; + private Double center_y; + private Double width; + private Double height; + private String polygon_points; + private String angle; +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkDO.java new file mode 100644 index 0000000..9d15685 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkDO.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.mark; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.util.List; + +/** + * 标注 DO + * + * @author 管理员 + */ +@TableName("annotation_mark") +@KeySequence("annotation_mark_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MarkDO extends BaseDO { + + /** + * id + */ + @TableId + private Integer id; + /** + * path + */ + private String path; + /** + * 项目id + */ + private Integer dataId; + /** + * 标注,类型是[{对象}],class_id,center_x,center_y,width,height,polygon_points,angle + */ + +// 在 MarkDO 中使用 + /** + * 标注,类型是[{对象}],class_id,center_x,center_y,width,height,polygon_points,angle + */ + @TableField(typeHandler = com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler.class) + private List annotation; + /** + * 1.标注完成,0,未标注 + */ + private Integer status =0; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkInfoDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkInfoDO.java new file mode 100644 index 0000000..4ebfdfc --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/mark/MarkInfoDO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.mark; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.annotation.service.MarkInfo.AnnotationData; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 标注 DO + * + * @author 管理员 + */ +@TableName(value = "annotation_mark_info",autoResultMap = true) +@KeySequence("annotation_mark_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MarkInfoDO extends BaseDO { + private Long id; + private Integer classId; + @TableField(exist = false) + private Integer className; + private Integer markId; + private Double centerX; + private Double centerY; + private Double width; + private Double height; + private Integer polygon_points; + private Double anagle; + private Integer dataId; + + @TableField(value = "annotation_data_string") + private String annotationDataString; + + @TableField(exist = false) + private AnnotationData annotationData; + + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/train/TrainDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/train/TrainDO.java new file mode 100644 index 0000000..1837d82 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/train/TrainDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.train; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 训练 DO + * + * @author 管理员 + */ +@TableName("annotation_train") +@KeySequence("annotation_train_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TrainDO extends BaseDO { + + /** + * id + */ + @TableId + private Integer id; + /** + * 项目id + */ + private Integer dataId; + /** + * 训练集比例 + */ + private Integer train; + /** + * 验证图像比例 + */ + private Integer val; + /** + * 测试图像比例 + */ + private Integer test; + /** + * 轮次 + */ + private Integer round; + /** + * 批次大小 + */ + private Integer size; + /** + * 图片大小(正方向,大于这个值进行缩放,小于这个值进行放大,不是正方形将图片周围涂黑) + */ + private Integer imageSize; + /** + * 预选训练模型 + */ + private String modelPath; + /** + * 训练图片路径 + */ + private String path; + /** + * 类型,使用哪个gpu + */ + private Integer trainType; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/trainresult/TrainResultDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/trainresult/TrainResultDO.java new file mode 100644 index 0000000..842d220 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/trainresult/TrainResultDO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.trainresult; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * 识别结果 DO + * + * @author 管理员 + */ +@TableName("annotation_train_result") +@KeySequence("annotation_train_result_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TrainResultDO extends BaseDO { + + /** + * id + */ + @TableId + private Integer id; + /** + * 训练id + */ + private Integer trainId; + /** + * 输出路径 + */ + private String path; + /** + * 识别结果rate + */ + private String rate; + /** + * 数据集 + */ + private Integer dataId; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/types/TypesDO.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/types/TypesDO.java new file mode 100644 index 0000000..37262f6 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/dataobject/types/TypesDO.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.annotation.dal.dataobject.types; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.*; +import lombok.*; + +/** + * 类别 DO + * + * @author 管理员 + */ +@TableName("annotation_types") +@KeySequence("annotation_types_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TypesDO extends BaseDO { + + /** + * id + */ + @TableId + private Integer id; + /** + * 名称 + */ + @TableField(value = "`name`") + private String name; + /** + * 项目id + */ + private Integer dataId; + /** + * index + */ + @TableField(value = "`index`") + private Integer index; + /** + * 颜色 + */ + private String color; + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/datas/DatasMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/datas/DatasMapper.java new file mode 100644 index 0000000..6a97999 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/datas/DatasMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.datas; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.datas.DatasDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.*; + +/** + * 数据集管理 Mapper + * + * @author 管理员 + */ +@Mapper +public interface DatasMapper extends BaseMapperX { + + default PageResult selectPage(DatasPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(DatasDO::getName, reqVO.getName()) + .eqIfPresent(DatasDO::getDescription, reqVO.getDescription()) + .eqIfPresent(DatasDO::getStatus, reqVO.getStatus()) + .eqIfPresent(DatasDO::getPath, reqVO.getPath()) + .eqIfPresent(DatasDO::getCount, reqVO.getCount()) + .eqIfPresent(DatasDO::getType, reqVO.getType()) + .eqIfPresent(DatasDO::getProgress, reqVO.getProgress()) + .betweenIfPresent(DatasDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(DatasDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkInfoMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkInfoMapper.java new file mode 100644 index 0000000..452d77b --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkInfoMapper.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.mark; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkInfoDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 标注 Mapper + * + * @author 管理员 + */ +@Mapper +public interface MarkInfoMapper extends BaseMapperX { + + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkMapper.java new file mode 100644 index 0000000..3e0e753 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/mark/MarkMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.mark; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.*; + +/** + * 标注 Mapper + * + * @author 管理员 + */ +@Mapper +public interface MarkMapper extends BaseMapperX { + + default PageResult selectPage(MarkPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MarkDO::getDataId, reqVO.getDataId()) + .orderByDesc(MarkDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/train/TrainMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/train/TrainMapper.java new file mode 100644 index 0000000..733af2c --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/train/TrainMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.train; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.train.TrainDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.annotation.controller.admin.train.vo.*; + +/** + * 训练 Mapper + * + * @author 管理员 + */ +@Mapper +public interface TrainMapper extends BaseMapperX { + + default PageResult selectPage(TrainPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TrainDO::getDataId, reqVO.getDataId()) + .eqIfPresent(TrainDO::getTrain, reqVO.getTrain()) + .eqIfPresent(TrainDO::getVal, reqVO.getVal()) + .eqIfPresent(TrainDO::getTest, reqVO.getTest()) + .eqIfPresent(TrainDO::getRound, reqVO.getRound()) + .eqIfPresent(TrainDO::getSize, reqVO.getSize()) + .eqIfPresent(TrainDO::getImageSize, reqVO.getImageSize()) + .eqIfPresent(TrainDO::getModelPath, reqVO.getModelPath()) + .eqIfPresent(TrainDO::getPath, reqVO.getPath()) + .eqIfPresent(TrainDO::getTrainType, reqVO.getTrainType()) + .betweenIfPresent(TrainDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(TrainDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/trainresult/TrainResultMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/trainresult/TrainResultMapper.java new file mode 100644 index 0000000..2da256f --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/trainresult/TrainResultMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.trainresult; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.trainresult.TrainResultDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo.*; + +/** + * 识别结果 Mapper + * + * @author 管理员 + */ +@Mapper +public interface TrainResultMapper extends BaseMapperX { + + default PageResult selectPage(TrainResultPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(TrainResultDO::getDataId, reqVO.getDataId()) + .orderByDesc(TrainResultDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/types/TypesMapper.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/types/TypesMapper.java new file mode 100644 index 0000000..2664080 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/mysql/types/TypesMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.annotation.dal.mysql.types; + +import java.util.*; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.annotation.dal.dataobject.types.TypesDO; +import org.apache.ibatis.annotations.Mapper; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.*; + +/** + * 类别 Mapper + * + * @author 管理员 + */ +@Mapper +public interface TypesMapper extends BaseMapperX { + + default PageResult selectPage(TypesPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(TypesDO::getName, reqVO.getName()) + .eqIfPresent(TypesDO::getDataId, reqVO.getDataId()) + .eqIfPresent(TypesDO::getIndex, reqVO.getIndex()) + .betweenIfPresent(TypesDO::getCreateTime, reqVO.getCreateTime()) + .eqIfPresent(TypesDO::getColor, reqVO.getColor()) + .orderByDesc(TypesDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ExportResult.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ExportResult.java new file mode 100644 index 0000000..f242918 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ExportResult.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo; +// ExportResult.java +public class ExportResult { + private boolean success; + private String output; + private String format; + + public ExportResult(boolean success, String output, String format) { + this.success = success; + this.output = output; + this.format = format; + } + + // Getters + public boolean isSuccess() { return success; } + public String getOutput() { return output; } + public String getFormat() { return format; } +} + diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/PredictionResult.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/PredictionResult.java new file mode 100644 index 0000000..bdc5e6d --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/PredictionResult.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo; +// PredictionResult.java +public class PredictionResult { + private boolean success; + private String output; + private String imagePath; + + public PredictionResult(boolean success, String output, String imagePath) { + this.success = success; + this.output = output; + this.imagePath = imagePath; + } + + // Getters + public boolean isSuccess() { return success; } + public String getOutput() { return output; } + public String getImagePath() { return imagePath; } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/TrainingResult.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/TrainingResult.java new file mode 100644 index 0000000..79feaf1 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/TrainingResult.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo; + +import lombok.Data; + +// TrainingResult.java +@Data +public class TrainingResult { + private boolean success; + private String message; + private String output; + + public TrainingResult(boolean success, String message, String output) { + this.success = success; + this.message = message; + this.output = output; + } + + // Getters + public boolean isSuccess() { return success; } + public String getMessage() { return message; } + public String getOutput() { return output; } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ValidationResult.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ValidationResult.java new file mode 100644 index 0000000..5d87a73 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/ValidationResult.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo; +// ValidationResult.java +public class ValidationResult { + private boolean success; + private String output; + + public ValidationResult(boolean success, String output) { + this.success = success; + this.output = output; + } + + // Getters + public boolean isSuccess() { return success; } + public String getOutput() { return output; } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloConfig.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloConfig.java new file mode 100644 index 0000000..fad86a3 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloConfig.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo; + +import lombok.Data; + +// YoloConfig.java +@Data +public class YoloConfig { + private String modelPath; + private String datasetPath; + private String outputPath; + private int epochs = 100; + private int batchSize = 16; + private double learningRate = 0.01; + private String device = "cpu"; // or "cuda" + private boolean pretrained = true; +} + diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloProgress.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloProgress.java new file mode 100644 index 0000000..78bce07 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/dal/yolo/YoloProgress.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.annotation.dal.yolo;// YoloProgress.java + + +public class YoloProgress { + private int currentEpoch; + private int totalEpochs; + private double progress; // 0-100 + private int processedItems; + private int totalItems; + private String statusMessage; + private boolean completed; + private boolean success; + + public YoloProgress() { + this.currentEpoch = 0; + this.totalEpochs = 0; + this.progress = 0.0; + this.processedItems = 0; + this.totalItems = 0; + this.statusMessage = "Initializing..."; + this.completed = false; + this.success = false; + } + + // Getters and Setters + public int getCurrentEpoch() { return currentEpoch; } + public void setCurrentEpoch(int currentEpoch) { this.currentEpoch = currentEpoch; } + + public int getTotalEpochs() { return totalEpochs; } + public void setTotalEpochs(int totalEpochs) { this.totalEpochs = totalEpochs; } + + public double getProgress() { return progress; } + public void setProgress(double progress) { this.progress = progress; } + + public int getProcessedItems() { return processedItems; } + public void setProcessedItems(int processedItems) { this.processedItems = processedItems; } + + public int getTotalItems() { return totalItems; } + public void setTotalItems(int totalItems) { this.totalItems = totalItems; } + + public String getStatusMessage() { return statusMessage; } + public void setStatusMessage(String statusMessage) { this.statusMessage = statusMessage; } + + public boolean isCompleted() { return completed; } + public void setCompleted(boolean completed) { this.completed = completed; } + + public boolean isSuccess() { return success; } + public void setSuccess(boolean success) { this.success = success; } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/AnnotationData.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/AnnotationData.java new file mode 100644 index 0000000..864fc70 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/AnnotationData.java @@ -0,0 +1,62 @@ +// AnnotationData.java +package cn.iocoder.yudao.module.annotation.service.MarkInfo; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未知属性 +@NoArgsConstructor +@AllArgsConstructor +public class AnnotationData { + private String id; + private List bodies; + private Target target; + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Target { + private String annotation; + private Selector selector; + private Creator creator; + private String created; + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Selector { + private String type; + private Geometry geometry; + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Geometry { + private Bounds bounds; + private Double x; + private Double y; + private Double w; + private Double h; + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Bounds { + private Double minX; + private Double minY; + private Double maxX; + private Double maxY; + } + } + } + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Creator { + private Boolean isGuest; + private String id; + } + } + +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoService.java new file mode 100644 index 0000000..474a90f --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.annotation.service.MarkInfo; + +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkInfoDO; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * 标注 Service 接口 + * + * @author 管理员 + */ +public interface MarkInfoService extends IService { + + /** + * 创建标注 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createMarkInfo(@Valid MarkInfoDO createReqVO); + + /** + * 更新标注 + * + * @param updateReqVO 更新信息 + */ + void updateMarkInfo(@Valid MarkInfoDO updateReqVO); + + /** + * 删除标注 + * + * @param id 编号 + */ + void deleteMarkInfo(Integer id); + + /** + * 获得标注 + * + * @param id 编号 + * @return 标注 + */ + MarkInfoDO getMarkInfo(Integer id); + + /** + * 获得标注分页 + * + * @param pageReqVO 分页查询 + * @return 标注分页 + */ + List getMarkList(MarkInfoDO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoServiceImpl.java new file mode 100644 index 0000000..e25601f --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/MarkInfo/MarkInfoServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.annotation.service.MarkInfo; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkInfoDO; +import cn.iocoder.yudao.module.annotation.dal.mysql.mark.MarkInfoMapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 标注 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class MarkInfoServiceImpl extends ServiceImpl implements MarkInfoService { + + @Resource + private MarkInfoMapper MarkInfoMapper; + + @Override + public Long createMarkInfo(MarkInfoDO markInfoDO) { + // 插入 + + +// MarkInfoDO MarkInfo = BeanUtils.toBean(createReqVO, MarkInfoDO.class); + MarkInfoMapper.insert(markInfoDO); + // 返回 + return markInfoDO.getId(); + } + + @Override + public void updateMarkInfo(MarkInfoDO updateReqVO) { + // 校验存在 +// validateMarkInfoExists(updateReqVO.getId()); + // 更新 + MarkInfoDO updateObj = BeanUtils.toBean(updateReqVO, MarkInfoDO.class); + MarkInfoMapper.updateById(updateObj); + } + + @Override + public void deleteMarkInfo(Integer id) { + // 校验存在 + validateMarkInfoExists(id); + // 删除 + MarkInfoMapper.deleteById(id); + } + + private void validateMarkInfoExists(Integer id) { + if (MarkInfoMapper.selectById(id) == null) { +// throw exception(MarkInfo_NOT_EXISTS); + } + } + + @Override + public MarkInfoDO getMarkInfo(Integer id) { + return MarkInfoMapper.selectById(id); + } + + @Override + public List getMarkList(MarkInfoDO pageReqVO) { + + return MarkInfoMapper.selectList(new QueryWrapper() + .eq(pageReqVO.getMarkId() != null,"mark_id", pageReqVO.getMarkId())); + } + + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasService.java new file mode 100644 index 0000000..2671f8f --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.service.datas; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.datas.DatasDO; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +/** + * 数据集管理 Service 接口 + * + * @author 管理员 + */ +public interface DatasService extends IService { + + /** + * 创建数据集管理 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createDatas(@Valid DatasSaveReqVO createReqVO); + + /** + * 更新数据集管理 + * + * @param updateReqVO 更新信息 + */ + void updateDatas(@Valid DatasSaveReqVO updateReqVO); + + /** + * 删除数据集管理 + * + * @param id 编号 + */ + void deleteDatas(Integer id); + + /** + * 获得数据集管理 + * + * @param id 编号 + * @return 数据集管理 + */ + DatasDO getDatas(Integer id); + + /** + * 获得数据集管理分页 + * + * @param pageReqVO 分页查询 + * @return 数据集管理分页 + */ + PageResult getDatasPage(DatasPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasServiceImpl.java new file mode 100644 index 0000000..df8ffed --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/datas/DatasServiceImpl.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.annotation.service.datas; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.datas.vo.DatasSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.datas.DatasDO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkDO; +import cn.iocoder.yudao.module.annotation.dal.mysql.datas.DatasMapper; +import cn.iocoder.yudao.module.annotation.dal.mysql.mark.MarkMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 数据集管理 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class DatasServiceImpl extends ServiceImpl implements DatasService{ + + @Resource + private DatasMapper datasMapper; + + @Resource + private MarkMapper markMapper; + + /** + * 检查路径是否存在,并获取其中所有图片文件名称 + * @param path 要检查的路径字符串 + * @return 图片文件名称列表 + */ + public List getImageNamesFromPath(String path) { + List imageNames = new ArrayList<>(); + + // 检查路径是否为空 + if (path == null || path.isEmpty()) { + return imageNames; + } + + File directory = new File(path); + + // 检查路径是否存在且为目录 + if (!directory.exists() || !directory.isDirectory()) { + return imageNames; + } + + // 获取目录中的所有文件 + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (isImageFile(file)) { + imageNames.add(file.getName()); + } + } + } + + return imageNames; + } + + /** + * 判断文件是否为图片文件 + * @param file 要判断的文件 + * @return 是否为图片文件 + */ + private boolean isImageFile(File file) { + if (!file.isFile()) { + return false; + } + + String fileName = file.getName().toLowerCase(); + return fileName.endsWith(".jpg") || + fileName.endsWith(".jpeg") || + fileName.endsWith(".png") || + fileName.endsWith(".gif") || + fileName.endsWith(".bmp") || + fileName.endsWith(".webp"); + } + @Override + public Integer createDatas(DatasSaveReqVO createReqVO) { + // 插入 + DatasDO datas = BeanUtils.toBean(createReqVO, DatasDO.class); +// 查看数据集是否存在判断路径是否存在 + List imageNames = getImageNamesFromPath(createReqVO.getPath()); +//默认类型为正在标注 + datas.setStatus("1"); + datas.setCount((long) imageNames.size()); + datas.setProgress(0.0); + for (String imageName : imageNames){ + markMapper.insert(new MarkDO() + .setDataId(datas.getId()) + .setPath(imageName) + .setAnnotation( new ArrayList<>())); + } + datasMapper.insert(datas); + // 返回 + return datas.getId(); + } + + @Override + public void updateDatas(DatasSaveReqVO updateReqVO) { + // 校验存在 + validateDatasExists(updateReqVO.getId()); + // 更新 + DatasDO updateObj = BeanUtils.toBean(updateReqVO, DatasDO.class); + datasMapper.updateById(updateObj); + } + + @Override + public void deleteDatas(Integer id) { + // 校验存在 + validateDatasExists(id); + // 删除 + datasMapper.deleteById(id); + } + + private void validateDatasExists(Integer id) { + if (datasMapper.selectById(id) == null) { +// throw exception(); + } + } + + @Override + public DatasDO getDatas(Integer id) { + return datasMapper.selectById(id); + } + + @Override + public PageResult getDatasPage(DatasPageReqVO pageReqVO) { + return datasMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkService.java new file mode 100644 index 0000000..bcec137 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.service.mark; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkDO; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +/** + * 标注 Service 接口 + * + * @author 管理员 + */ +public interface MarkService extends IService { + + /** + * 创建标注 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createMark(@Valid MarkSaveReqVO createReqVO); + + /** + * 更新标注 + * + * @param updateReqVO 更新信息 + */ + void updateMark(@Valid MarkSaveReqVO updateReqVO); + + /** + * 删除标注 + * + * @param id 编号 + */ + void deleteMark(Integer id); + + /** + * 获得标注 + * + * @param id 编号 + * @return 标注 + */ + MarkDO getMark(Integer id); + + /** + * 获得标注分页 + * + * @param pageReqVO 分页查询 + * @return 标注分页 + */ + PageResult getMarkPage(MarkPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkServiceImpl.java new file mode 100644 index 0000000..dfac620 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/mark/MarkServiceImpl.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.annotation.service.mark; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.mark.vo.MarkSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.mark.MarkDO; +import cn.iocoder.yudao.module.annotation.dal.mysql.mark.MarkMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 标注 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class MarkServiceImpl extends ServiceImpl implements MarkService { + + @Resource + private MarkMapper markMapper; + + @Override + public Integer createMark(MarkSaveReqVO createReqVO) { + // 插入 + MarkDO mark = BeanUtils.toBean(createReqVO, MarkDO.class); + markMapper.insert(mark); + // 返回 + return mark.getId(); + } + + @Override + public void updateMark(MarkSaveReqVO updateReqVO) { + // 校验存在 +// validateMarkExists(updateReqVO.getId()); + // 更新 + MarkDO updateObj = BeanUtils.toBean(updateReqVO, MarkDO.class); + markMapper.updateById(updateObj); + } + + @Override + public void deleteMark(Integer id) { + // 校验存在 + validateMarkExists(id); + // 删除 + markMapper.deleteById(id); + } + + private void validateMarkExists(Integer id) { + if (markMapper.selectById(id) == null) { +// throw exception(MARK_NOT_EXISTS); + } + } + + @Override + public MarkDO getMark(Integer id) { + return markMapper.selectById(id); + } + + @Override + public PageResult getMarkPage(MarkPageReqVO pageReqVO) { + return markMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainService.java new file mode 100644 index 0000000..e548cd1 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.service.train; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.annotation.controller.admin.train.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.train.TrainDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 训练 Service 接口 + * + * @author 管理员 + */ +public interface TrainService { + + /** + * 创建训练 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createTrain(@Valid TrainSaveReqVO createReqVO); + + /** + * 更新训练 + * + * @param updateReqVO 更新信息 + */ + void updateTrain(@Valid TrainSaveReqVO updateReqVO); + + /** + * 删除训练 + * + * @param id 编号 + */ + void deleteTrain(Integer id); + + /** + * 获得训练 + * + * @param id 编号 + * @return 训练 + */ + TrainDO getTrain(Integer id); + + /** + * 获得训练分页 + * + * @param pageReqVO 分页查询 + * @return 训练分页 + */ + PageResult getTrainPage(TrainPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainServiceImpl.java new file mode 100644 index 0000000..f5af9d2 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/train/TrainServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.annotation.service.train; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.annotation.controller.admin.train.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.train.TrainDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.annotation.dal.mysql.train.TrainMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 训练 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class TrainServiceImpl implements TrainService { + + @Resource + private TrainMapper trainMapper; + + @Override + public Integer createTrain(TrainSaveReqVO createReqVO) { + // 插入 + TrainDO train = BeanUtils.toBean(createReqVO, TrainDO.class); + trainMapper.insert(train); + // 返回 + return train.getId(); + } + + @Override + public void updateTrain(TrainSaveReqVO updateReqVO) { + // 校验存在 + validateTrainExists(updateReqVO.getId()); + // 更新 + TrainDO updateObj = BeanUtils.toBean(updateReqVO, TrainDO.class); + trainMapper.updateById(updateObj); + } + + @Override + public void deleteTrain(Integer id) { + // 校验存在 + validateTrainExists(id); + // 删除 + trainMapper.deleteById(id); + } + + private void validateTrainExists(Integer id) { + if (trainMapper.selectById(id) == null) { +// throw exception(TRAIN_NOT_EXISTS); + } + } + + @Override + public TrainDO getTrain(Integer id) { + return trainMapper.selectById(id); + } + + @Override + public PageResult getTrainPage(TrainPageReqVO pageReqVO) { + return trainMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultService.java new file mode 100644 index 0000000..aea2d27 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.service.trainresult; + +import java.util.*; +import jakarta.validation.*; +import cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.trainresult.TrainResultDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +/** + * 识别结果 Service 接口 + * + * @author 管理员 + */ +public interface TrainResultService { + + /** + * 创建识别结果 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createTrainResult(@Valid TrainResultSaveReqVO createReqVO); + + /** + * 更新识别结果 + * + * @param updateReqVO 更新信息 + */ + void updateTrainResult(@Valid TrainResultSaveReqVO updateReqVO); + + /** + * 删除识别结果 + * + * @param id 编号 + */ + void deleteTrainResult(Integer id); + + /** + * 获得识别结果 + * + * @param id 编号 + * @return 识别结果 + */ + TrainResultDO getTrainResult(Integer id); + + /** + * 获得识别结果分页 + * + * @param pageReqVO 分页查询 + * @return 识别结果分页 + */ + PageResult getTrainResultPage(TrainResultPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultServiceImpl.java new file mode 100644 index 0000000..51609a1 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/trainresult/TrainResultServiceImpl.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.annotation.service.trainresult; + +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import cn.iocoder.yudao.module.annotation.controller.admin.trainresult.vo.*; +import cn.iocoder.yudao.module.annotation.dal.dataobject.trainresult.TrainResultDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.annotation.dal.mysql.trainresult.TrainResultMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 识别结果 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class TrainResultServiceImpl implements TrainResultService { + + @Resource + private TrainResultMapper trainResultMapper; + + @Override + public Integer createTrainResult(TrainResultSaveReqVO createReqVO) { + // 插入 + TrainResultDO trainResult = BeanUtils.toBean(createReqVO, TrainResultDO.class); + trainResultMapper.insert(trainResult); + // 返回 + return trainResult.getId(); + } + + @Override + public void updateTrainResult(TrainResultSaveReqVO updateReqVO) { + // 校验存在 +// validateTrainResultExists(updateReqVO.getId()); + // 更新 + TrainResultDO updateObj = BeanUtils.toBean(updateReqVO, TrainResultDO.class); + trainResultMapper.updateById(updateObj); + } + + @Override + public void deleteTrainResult(Integer id) { + // 校验存在 + validateTrainResultExists(id); + // 删除 + trainResultMapper.deleteById(id); + } + + private void validateTrainResultExists(Integer id) { + if (trainResultMapper.selectById(id) == null) { +// throw exception(TRAIN_RESULT_NOT_EXISTS); + } + } + + @Override + public TrainResultDO getTrainResult(Integer id) { + return trainResultMapper.selectById(id); + } + + @Override + public PageResult getTrainResultPage(TrainResultPageReqVO pageReqVO) { + return trainResultMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesService.java new file mode 100644 index 0000000..614a910 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.annotation.service.types; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.types.TypesDO; +import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.validation.Valid; + +/** + * 类别 Service 接口 + * + * @author 管理员 + */ +public interface TypesService extends IService { + + /** + * 创建类别 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createTypes(@Valid TypesSaveReqVO createReqVO); + + /** + * 更新类别 + * + * @param updateReqVO 更新信息 + */ + void updateTypes(@Valid TypesSaveReqVO updateReqVO); + + /** + * 删除类别 + * + * @param id 编号 + */ + void deleteTypes(Integer id); + + /** + * 获得类别 + * + * @param id 编号 + * @return 类别 + */ + TypesDO getTypes(Integer id); + + /** + * 获得类别分页 + * + * @param pageReqVO 分页查询 + * @return 类别分页 + */ + PageResult getTypesPage(TypesPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesServiceImpl.java new file mode 100644 index 0000000..5ef0ca1 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/types/TypesServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.annotation.service.types; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesPageReqVO; +import cn.iocoder.yudao.module.annotation.controller.admin.types.vo.TypesSaveReqVO; +import cn.iocoder.yudao.module.annotation.dal.dataobject.types.TypesDO; +import cn.iocoder.yudao.module.annotation.dal.mysql.types.TypesMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; +//import static cn.iocoder.yudao.module.annotation.enums.ErrorCodeConstants.*; + +/** + * 类别 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class TypesServiceImpl extends ServiceImpl implements TypesService { + + @Resource + private TypesMapper typesMapper; + + @Override + public Integer createTypes(TypesSaveReqVO createReqVO) { + // 插入 +// 在这里不添加index 在生成的时候添加 + TypesDO types = BeanUtils.toBean(createReqVO, TypesDO.class); + typesMapper.insert(types); + // 返回 + return types.getId(); + } + + @Override + public void updateTypes(TypesSaveReqVO updateReqVO) { + // 校验存在 + validateTypesExists(updateReqVO.getId()); + // 更新 + TypesDO updateObj = BeanUtils.toBean(updateReqVO, TypesDO.class); + typesMapper.updateById(updateObj); + } + + @Override + public void deleteTypes(Integer id) { + // 校验存在 + validateTypesExists(id); + // 删除 + typesMapper.deleteById(id); + } + + private void validateTypesExists(Integer id) { + if (typesMapper.selectById(id) == null) { +// throw exception(TYPES_NOT_EXISTS); + } + } + + @Override + public TypesDO getTypes(Integer id) { + return typesMapper.selectById(id); + } + + @Override + public PageResult getTypesPage(TypesPageReqVO pageReqVO) { + return typesMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloService.java new file mode 100644 index 0000000..24ced04 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloService.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.annotation.service.yolo; +// AsyncYoloService.java + +import cn.iocoder.yudao.module.annotation.dal.yolo.*; + +import java.util.concurrent.CompletableFuture; + +public interface AsyncYoloService extends YoloService { + CompletableFuture trainAsync(YoloConfig config); + CompletableFuture validateAsync(YoloConfig config); + CompletableFuture predictAsync(YoloConfig config, String imagePath); + CompletableFuture exportAsync(YoloConfig config, String format); +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloServiceImpl.java new file mode 100644 index 0000000..86baa9a --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/AsyncYoloServiceImpl.java @@ -0,0 +1,205 @@ +// AsyncYoloServiceImpl.java +package cn.iocoder.yudao.module.annotation.service.yolo; + +import cn.iocoder.yudao.module.annotation.dal.yolo.*; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.concurrent.CompletableFuture; + +@Service +public class AsyncYoloServiceImpl implements AsyncYoloService { + + @Override + @Async("yoloTaskExecutor") + public CompletableFuture trainAsync(YoloConfig config) { + return CompletableFuture.supplyAsync(() -> { + try { + ProcessBuilder pb = buildTrainCommand(config); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + System.out.println(line); // 可用于日志记录 + } + + int exitCode = process.waitFor(); + if (exitCode == 0) { + return new TrainingResult(true, "Training completed successfully", output.toString()); + } else { + return new TrainingResult(false, "Training failed with exit code: " + exitCode, output.toString()); + } + } catch (Exception e) { + return new TrainingResult(false, "Training error: " + e.getMessage(), ""); + } + }); + } + + @Override + @Async("yoloTaskExecutor") + public CompletableFuture validateAsync(YoloConfig config) { + return CompletableFuture.supplyAsync(() -> { + try { + ProcessBuilder pb = buildValidateCommand(config); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new ValidationResult(exitCode == 0, output.toString()); + } catch (Exception e) { + return new ValidationResult(false, "Validation error: " + e.getMessage()); + } + }); + } + + @Override + @Async("yoloTaskExecutor") + public CompletableFuture predictAsync(YoloConfig config, String imagePath) { + return CompletableFuture.supplyAsync(() -> { + try { + ProcessBuilder pb = buildPredictCommand(config, imagePath); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new PredictionResult(exitCode == 0, output.toString(), imagePath); + } catch (Exception e) { + return new PredictionResult(false, "Prediction error: " + e.getMessage(), imagePath); + } + }); + } + + @Override + @Async("yoloTaskExecutor") + public CompletableFuture exportAsync(YoloConfig config, String format) { + return CompletableFuture.supplyAsync(() -> { + try { + ProcessBuilder pb = buildExportCommand(config, format); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new ExportResult(exitCode == 0, output.toString(), format); + } catch (Exception e) { + return new ExportResult(false, "Export error: " + e.getMessage(), format); + } + }); + } + + // 同步方法实现(可选) + @Override + public TrainingResult train(YoloConfig config) { + return trainAsync(config).join(); + } + + @Override + public ValidationResult validate(YoloConfig config) { + return validateAsync(config).join(); + } + + @Override + public PredictionResult predict(YoloConfig config, String imagePath) { + return predictAsync(config, imagePath).join(); + } + + @Override + public ExportResult export(YoloConfig config, String format) { + return exportAsync(config, format).join(); + } + + private ProcessBuilder buildTrainCommand(YoloConfig config) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "train", + "--model", config.getModelPath(), + "--data", config.getDatasetPath(), + "--epochs", String.valueOf(config.getEpochs()), + "--batch", String.valueOf(config.getBatchSize()), + "--lr", String.valueOf(config.getLearningRate()), + "--device", config.getDevice(), + "--project", config.getOutputPath() + ); + + if (config.isPretrained()) { + pb.command().add("--pretrained"); + pb.command().add("True"); + } + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildValidateCommand(YoloConfig config) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "val", + "--model", config.getModelPath(), + "--data", config.getDatasetPath(), + "--device", config.getDevice() + ); + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildPredictCommand(YoloConfig config, String imagePath) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "predict", + "--model", config.getModelPath(), + "--source", imagePath, + "--device", config.getDevice(), + "--project", config.getOutputPath() + ); + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildExportCommand(YoloConfig config, String format) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "export", + "--model", config.getModelPath(), + "--format", format + ); + + pb.redirectErrorStream(true); + return pb; + } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressListener.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressListener.java new file mode 100644 index 0000000..8ddc181 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressListener.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.annotation.service.yolo; + +import cn.iocoder.yudao.module.annotation.dal.yolo.YoloProgress; + +public interface YoloProgressListener { + void onProgressUpdate(YoloProgress progress); + void onComplete(YoloProgress finalProgress); + void onError(Exception e); +} \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressParser.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressParser.java new file mode 100644 index 0000000..219f74b --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloProgressParser.java @@ -0,0 +1,60 @@ +// YoloProgressParser.java +package cn.iocoder.yudao.module.annotation.service.yolo; + +import cn.iocoder.yudao.module.annotation.dal.yolo.YoloProgress; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class YoloProgressParser { + + // 匹配训练进度的正则表达式 + private static final Pattern EPOCH_PATTERN = Pattern.compile("Epoch\\s+(\\d+)/(\\d+)"); + private static final Pattern PROGRESS_PATTERN = Pattern.compile("(\\d+)/(\\d+)\\s+\\[.*?([0-9.]+)%.*?\\]"); + private static final Pattern LOSS_PATTERN = Pattern.compile("loss:\\s*([0-9.]+)"); + + public static YoloProgress parseLine(String line, YoloProgress currentProgress) { + if (currentProgress == null) { + currentProgress = new YoloProgress(); + } + + // 解析Epoch信息 + Matcher epochMatcher = EPOCH_PATTERN.matcher(line); + if (epochMatcher.find()) { + currentProgress.setCurrentEpoch(Integer.parseInt(epochMatcher.group(1))); + currentProgress.setTotalEpochs(Integer.parseInt(epochMatcher.group(2))); + currentProgress.setStatusMessage("Training epoch " + + currentProgress.getCurrentEpoch() + "/" + currentProgress.getTotalEpochs()); + } + + // 解析进度条信息 + Matcher progressMatcher = PROGRESS_PATTERN.matcher(line); + if (progressMatcher.find()) { + currentProgress.setProcessedItems(Integer.parseInt(progressMatcher.group(1))); + currentProgress.setTotalItems(Integer.parseInt(progressMatcher.group(2))); + currentProgress.setProgress(Double.parseDouble(progressMatcher.group(3))); + } + + // 解析Loss信息 + Matcher lossMatcher = LOSS_PATTERN.matcher(line); + if (lossMatcher.find()) { + currentProgress.setStatusMessage(currentProgress.getStatusMessage() + + " | Loss: " + lossMatcher.group(1)); + } + + return currentProgress; + } + + public static boolean isCompletionIndicator(String line) { + return line.contains("Training completed") || + line.contains("completed successfully") || + line.contains("finished"); + } + + public static boolean isErrorIndicator(String line) { + return line.contains("error") || + line.contains("failed") || + line.contains("exception") || + line.contains("Error"); + } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloService.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloService.java new file mode 100644 index 0000000..06db26f --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloService.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.annotation.service.yolo; + +import cn.iocoder.yudao.module.annotation.dal.yolo.*; + +// YoloService.java +public interface YoloService { + /** + * 训练模型 + */ + TrainingResult train(YoloConfig config); + + /** + * 验证模型 + */ + ValidationResult validate(YoloConfig config); + + /** + * 进行预测 + */ + PredictionResult predict(YoloConfig config, String imagePath); + + /** + * 导出模型 + */ + ExportResult export(YoloConfig config, String format); +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloServiceImpl.java b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloServiceImpl.java new file mode 100644 index 0000000..93fa5c0 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/java/cn/iocoder/yudao/module/annotation/service/yolo/YoloServiceImpl.java @@ -0,0 +1,172 @@ +package cn.iocoder.yudao.module.annotation.service.yolo; +// YoloServiceImpl.java + +import cn.iocoder.yudao.module.annotation.dal.yolo.*; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +public class YoloServiceImpl implements YoloService { + + @Override + public TrainingResult train(YoloConfig config) { + try { + // 构建训练命令 + ProcessBuilder pb = buildTrainCommand(config); + Process process = pb.start(); + + // 读取输出 + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + // 可以在这里解析训练进度 + System.out.println(line); + } + + int exitCode = process.waitFor(); + if (exitCode == 0) { + return new TrainingResult(true, "Training completed successfully", output.toString()); + } else { + return new TrainingResult(false, "Training failed with exit code: " + exitCode, output.toString()); + } + } catch (Exception e) { + return new TrainingResult(false, "Training error: " + e.getMessage(), ""); + } + } + + @Override + public ValidationResult validate(YoloConfig config) { + try { + ProcessBuilder pb = buildValidateCommand(config); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new ValidationResult(exitCode == 0, output.toString()); + } catch (Exception e) { + return new ValidationResult(false, "Validation error: " + e.getMessage()); + } + } + + @Override + public PredictionResult predict(YoloConfig config, String imagePath) { + try { + ProcessBuilder pb = buildPredictCommand(config, imagePath); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new PredictionResult(exitCode == 0, output.toString(), imagePath); + } catch (Exception e) { + return new PredictionResult(false, "Prediction error: " + e.getMessage(), imagePath); + } + } + + @Override + public ExportResult export(YoloConfig config, String format) { + try { + ProcessBuilder pb = buildExportCommand(config, format); + Process process = pb.start(); + + StringBuilder output = new StringBuilder(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(process.getInputStream()) + ); + + String line; + while ((line = reader.readLine()) != null) { + output.append(line).append("\n"); + } + + int exitCode = process.waitFor(); + return new ExportResult(exitCode == 0, output.toString(), format); + } catch (Exception e) { + return new ExportResult(false, "Export error: " + e.getMessage(), format); + } + } + + private ProcessBuilder buildTrainCommand(YoloConfig config) { + // 假设使用Python脚本调用YOLO + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "train", + "--model", config.getModelPath(), + "--data", config.getDatasetPath(), + "--epochs", String.valueOf(config.getEpochs()), + "--batch", String.valueOf(config.getBatchSize()), + "--lr", String.valueOf(config.getLearningRate()), + "--device", config.getDevice(), + "--project", config.getOutputPath() + ); + + if (config.isPretrained()) { + pb.command().add("--pretrained"); + pb.command().add("True"); + } + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildValidateCommand(YoloConfig config) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "val", + "--model", config.getModelPath(), + "--data", config.getDatasetPath(), + "--device", config.getDevice() + ); + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildPredictCommand(YoloConfig config, String imagePath) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "predict", + "--model", config.getModelPath(), + "--source", imagePath, + "--device", config.getDevice(), + "--project", config.getOutputPath() + ); + + pb.redirectErrorStream(true); + return pb; + } + + private ProcessBuilder buildExportCommand(YoloConfig config, String format) { + ProcessBuilder pb = new ProcessBuilder(); + pb.command( + "python", "-m", "ultralytics", "export", + "--model", config.getModelPath(), + "--format", format + ); + + pb.redirectErrorStream(true); + return pb; + } +} diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/datas/DatasMapper.xml b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/datas/DatasMapper.xml new file mode 100644 index 0000000..c07eb6a --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/datas/DatasMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/mark/MarkMapper.xml b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/mark/MarkMapper.xml new file mode 100644 index 0000000..2050639 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/mark/MarkMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/train/TrainMapper.xml b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/train/TrainMapper.xml new file mode 100644 index 0000000..c323079 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/train/TrainMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/trainresult/TrainResultMapper.xml b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/trainresult/TrainResultMapper.xml new file mode 100644 index 0000000..91e11fc --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/trainresult/TrainResultMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/types/TypesMapper.xml b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/types/TypesMapper.xml new file mode 100644 index 0000000..f8c1127 --- /dev/null +++ b/yudao-module-annotation/yudao-module-annotation-biz/src/main/resources/mapper/types/TypesMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java index 77c20d9..fedcd83 100644 --- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java +++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/conf/MyInitializer.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.camera.service.camera.CameraService; import cn.iocoder.yudao.module.camera.service.channel.CameraChannel; import cn.iocoder.yudao.module.system.service.dict.DictDataService; import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import jakarta.annotation.Resource; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; @@ -23,6 +24,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; @Component public class MyInitializer { @@ -38,7 +41,8 @@ public class MyInitializer { @Resource private CameraService cameraService; - + // 创建线程池用于处理摄像头配置和登录 + private ExecutorService executorService = Executors.newFixedThreadPool(20); @Scheduled(fixedRate = 30000) // 每分钟执行一次 @@ -59,27 +63,43 @@ public class MyInitializer { e.printStackTrace(); } } + + @PreDestroy + public void destroy() { + // 关闭线程池 + if (executorService != null && !executorService.isShutdown()) { + executorService.shutdown(); + } + } @Resource CameraModFactory cameraModFactory; private void cameraLogin(List list) { - for (CameraDO camera : list) { - if (Objects.equals(camera.getType(), CameraType.hik.getType())){ - if (CameraConnMap.getConnId(camera.getId())==null - || !Objects.requireNonNull(cameraModFactory.get(camera.getType())).connectStatus(CameraConnMap.getConnId(camera.getId()))){ - cameraModFactory.get(camera.getType()).login(camera.getId(),camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword()); - } - }else - if (Objects.equals(camera.getType(), CameraType.dh.getType())){ -// 大华相机会自动去重连 - if (CameraConnMap.getConnIdDh(camera.getId())==null){ - Objects.requireNonNull(cameraModFactory.get(camera.getType())).login(camera.getId(),camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword()); + // 提交摄像头登录任务,不等待完成 + list.forEach(camera -> { + executorService.submit(() -> { + try { + if (Objects.equals(camera.getType(), CameraType.hik.getType())){ + if (CameraConnMap.getConnId(camera.getId())==null + || !Objects.requireNonNull(cameraModFactory.get(camera.getType())).connectStatus(CameraConnMap.getConnId(camera.getId()))){ + cameraModFactory.get(camera.getType()).login(camera.getId(),camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword()); + } + }else if (Objects.equals(camera.getType(), CameraType.dh.getType())){ + // 大华相机会自动去重连 + if (CameraConnMap.getConnIdDh(camera.getId())==null){ + Objects.requireNonNull(cameraModFactory.get(camera.getType())).login(camera.getId(),camera.getIp(),camera.getPort(),camera.getUser(),camera.getPassword()); + } + } + } catch (Exception e) { + System.err.println("摄像头登录失败: " + camera.getId() + ", 错误: " + e.getMessage()); + e.printStackTrace(); } - } - } + }); + }); } private void zlmConf( List list) { + executorService.submit(() -> { String zlmApiUrl = dictDataService.parseDictData("ZLMediaKit_conf", "Apiurl").getValue(); String zlmApiSecret = dictDataService.parseDictData("ZLMediaKit_conf", "secret").getValue(); try { @@ -89,31 +109,32 @@ public class MyInitializer { String queryUrl = buildUrl(zlmApiUrl +"getMediaList",null , queryParams); String response = get(queryUrl); RtspSessionResponse rtspSessionResponse = JsonUtils.parseObject(response, RtspSessionResponse.class); - // 检查并添加缺失的RTSP代理 - for (CameraDO entry : list) { + // 提交RTSP代理添加任务,不等待完成 + list.forEach(camera -> { boolean isRtspProxyExists = false; if (rtspSessionResponse != null && rtspSessionResponse.getData()!=null && rtspSessionResponse.getData().size()>0) { for (RtspSessionResponse.RtspSession rtspSession : rtspSessionResponse.getData()){ - if (rtspSession.getApp().equals("live")&&rtspSession.getStream().equals("camera"+entry.getId())){ + if (rtspSession.getApp().equals("live")&&rtspSession.getStream().equals("camera"+camera.getId())){ isRtspProxyExists = true; break; } } } - //不存在则重新注入 + // 不存在则重新注入 if (!isRtspProxyExists){ - try { - - addRtspProxy(entry, zlmApiUrl, zlmApiSecret); - }catch (Exception e){ - e.printStackTrace(); + try { + addRtspProxy(camera, zlmApiUrl, zlmApiSecret); + } catch (Exception e) { + System.err.println("添加RTSP代理失败: " + camera.getId() + ", 错误: " + e.getMessage()); + e.printStackTrace(); + } } - } - - } + }); } catch (Exception e) { e.printStackTrace(); } + + }); } private boolean isRtspProxyExists(String response, String rtspUrl) { @@ -152,4 +173,4 @@ public class MyInitializer { return response.body().string(); } } -} +} \ No newline at end of file diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/dh/netsdk/lib/LibraryLoad.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/dh/netsdk/lib/LibraryLoad.java index 760b94e..d9bd6cc 100644 --- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/dh/netsdk/lib/LibraryLoad.java +++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/dh/netsdk/lib/LibraryLoad.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.camera.lib.camera.dh.netsdk.lib; import com.sun.jna.Platform; import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.util.Strings; import java.io.*; @@ -67,7 +68,8 @@ public class LibraryLoad { } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("mac")) { if (arch.contains("64")) { // Linux 64位 - libName = libName + "/linux64/"+type + "/lib" + sdkName; +// 小写命名 + libName = "/lib/libs/linux64/"+type + "/lib" + Strings.toLowerCase(sdkName)+".so"; } else { // Linux 32位 log.error("该系统采用未支持的32位系统"); @@ -79,26 +81,6 @@ public class LibraryLoad { return libName; } - public static String getLoadLibrary(String library) { - - String loadLibrary = ""; - String osPrefix = getOsPrefix(); - if(osPrefix.toLowerCase().startsWith("win32-x86")) { - loadLibrary = "./libs/win32/"; - } else if(osPrefix.toLowerCase().startsWith("win32-amd64") ) { - loadLibrary = ".\\libs\\win64\\"; - - } else if(osPrefix.toLowerCase().startsWith("linux-i386")) { - loadLibrary = "/libs/linux64/lib"; - library = library+".so"; - }else if(osPrefix.toLowerCase().startsWith("linux-amd64")) { - loadLibrary = "/lib/javaLibs/hikLinux/lib"; - library = library.toLowerCase()+".so"; - } - System.out.printf("[Load %s Path : %s]\n", library, loadLibrary + library); - return loadLibrary + library; - } - // 获取操作平台信息 public static String getOsPrefix() { String arch = System.getProperty("os.arch").toLowerCase(); diff --git a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/hik/HikControlModuleImpl.java b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/hik/HikControlModuleImpl.java index 01a5d8c..109aeb0 100644 --- a/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/hik/HikControlModuleImpl.java +++ b/yudao-module-camera/yudao-module-camera-biz/src/main/java/cn/iocoder/yudao/module/camera/lib/camera/hik/HikControlModuleImpl.java @@ -601,8 +601,11 @@ public class HikControlModuleImpl implements CameraModule { //检测球机连接状态 public Boolean connectStatus(Integer userId){ + if (CameraConnMap.getConnId(userId) == null){ + return false; + } - return hcNetsdk.NET_DVR_RemoteControl(userId,20005,null,0); + return hcNetsdk.NET_DVR_RemoteControl(CameraConnMap.getConnId(userId),20005,null,0); } /** @@ -644,16 +647,16 @@ public class HikControlModuleImpl implements CameraModule { //byStartDChan为IP通道起始通道号, 预览回放NVR的IP通道时需要根据起始通道号进行取值 int tryTimes = 0; - while(m_lUserID < 0 && tryTimes < MAX_RECONNET_TIME){ - log.error("hik login error,ip:{},port:{},errorCode:{}",m_strIp,m_nPort,hcNetsdk.NET_DVR_GetLastError()); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - m_lUserID = hcNetsdk.NET_DVR_Login_V40(m_strLoginInfo,m_strDeviceInfo); - tryTimes ++; - } +// while(m_lUserID < 0 && tryTimes < MAX_RECONNET_TIME){ +// log.error("hik login error,ip:{},port:{},errorCode:{}",m_strIp,m_nPort,hcNetsdk.NET_DVR_GetLastError()); +// try { +// Thread.sleep(500); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// m_lUserID = hcNetsdk.NET_DVR_Login_V40(m_strLoginInfo,m_strDeviceInfo); +// tryTimes ++; +// } CameraConnMap.conn(cameraId,m_lUserID); if(m_lUserID >= 0){ diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index e87605e..1df763c 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -18,11 +18,14 @@ public interface ErrorCodeConstants { // ========== 参数配置 1-001-000-000 ========== ErrorCode CAMERA_IO_NOT_EXISTS = new ErrorCode(1_001_000_001, "相机预置点位不存在"); ErrorCode RFID_LIVE_NOT_EXISTS = new ErrorCode(1_001_000_001, "rfid当前记录情况不存在"); + ErrorCode WARN_NOT_EXISTS = new ErrorCode(1_001_000_001, "报警不存在"); ErrorCode CAMERA_IO_CONFIG_NOT_EXISTS = new ErrorCode(1_001_000_001, "相机不存在"); ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(1_001_000_001, "相机不存在"); ErrorCode LIGHT_SOURCE_NOT_EXISTS = new ErrorCode( 1_001_000_001, "光源不存在"); ErrorCode RFID_NOT_EXISTS = new ErrorCode(1_001_000_001, "RFID不存在"); + ErrorCode SPECIFICATION_CONF_NOT_EXISTS = new ErrorCode(1_001_000_001, "配置不存在"); + ErrorCode SENSOR_GUN_NOT_EXISTS = new ErrorCode(1_001_000_001, "扫码枪不存在"); ErrorCode STOCK_LOG_NOT_EXISTS = new ErrorCode(1_001_000_001, "货位历史不存在"); ErrorCode ORDER_NOT_EXISTS = new ErrorCode(1_001_000_001, "随行记录不存在"); diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java index a934031..8fcc835 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/Hik3D/Hik3DController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.camera.controller.admin.Hik3D; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; import cn.iocoder.yudao.module.camera.dal.entity.HikPythonEntity; import cn.iocoder.yudao.module.camera.service.Hik3D.HikFlaskApiService; import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService; @@ -42,7 +43,7 @@ public class Hik3DController { @Operation(summary = "updateConfig") @ResponseBody @PermitAll - public HikPythonEntity addTemplate(@RequestBody HikPythonEntity hikPythonEntity){ + public HikPythonEntity addTemplate(@RequestBody SpecificationConfDO hikPythonEntity){ String baseUrl = "http://127.0.0.1:5000"; try { return hikFlaskApiService.addTemplate(hikPythonEntity.getType(), hikPythonEntity,baseUrl); diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/kesc/StockControlController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/kesc/StockControlController.java index 5838ee2..d0525e5 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/kesc/StockControlController.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/kesc/StockControlController.java @@ -12,6 +12,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + @Tag(name = "管理后台 - 随行盘点") @RestController @RequestMapping("/logistics/StockController") @@ -24,6 +27,10 @@ public class StockControlController { @Resource SseClient sseClient; + // 创建一个固定大小的线程池用于异步执行PLC操作 + private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + + @PostMapping("/openCamera") @Operation(summary = "随行盘点开始任务") @@ -44,7 +51,54 @@ public class StockControlController { } - @PostMapping("/updateResult") + @PostMapping("/monitorMode") + @Operation(summary = "随行开始任务") + @ResponseBody + @PermitAll + public CommonResult monitorMode(@RequestBody KsecDataInfo kescEntity){ + log.info("随行开始任务:{}",kescEntity); +// kescEntity = kescEntity.fromBySRMNumber(kescEntity); + + // 随行开始 + if (kescEntity.getCmdName().equals("start")){ + plcService.orderStart(kescEntity); + }else if (kescEntity.getCmdName().contains("load")){ +// 随行正在进行 + plcService.action(kescEntity.getTaskId(),kescEntity.getCmdName()); + }else if (kescEntity.getCmdName().contains("finish")){ +// 随行结束 + plcService.orderStop(kescEntity.getTaskId()); + } + + return CommonResult.success("","OK"); + } + + + @PostMapping("/inventory") + @Operation(summary = "盘点任务") + @ResponseBody + @PermitAll + public CommonResult inventory(@RequestBody KsecDataInfo kescEntity){ + log.info("盘点任务:{}",kescEntity); +// kescEntity = kescEntity.fromBySRMNumber(kescEntity); + + executorService.submit(() -> { + // 移动盘点 + if (kescEntity.getCmdName().equals("inventoryArrived")){ + plcService.checkStart(kescEntity); + plcService.check(kescEntity.getTaskId(),kescEntity.getCmdName()); + }else if (kescEntity.getCmdName().contains("inventoryLoad")){ +// 到位盘点 + plcService.check(kescEntity.getTaskId(),kescEntity.getCmdName()); + + plcService.checkStop(kescEntity.getTaskId()); + } + }); + + return CommonResult.success("","OK"); + } + + @PostMapping("/inventoryEndReport") @Operation(summary = "模拟随行盘点结果返回状态") @ResponseBody @PermitAll @@ -54,7 +108,7 @@ public class StockControlController { } - @PostMapping("/setUpdateStatus") + @PostMapping("/resultReport") @Operation(summary = "随行盘点更新状态") @ResponseBody @PermitAll diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java index 4c7b96d..2ca57ae 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/OrderController.java @@ -11,10 +11,12 @@ import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderRespVO; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderSaveReqVO; import cn.iocoder.yudao.module.camera.controller.admin.order.vo.OrderStatistics; import cn.iocoder.yudao.module.camera.dal.dataobject.order.OrderDO; +import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; import cn.iocoder.yudao.module.camera.dal.entity.echarts.EChartsOption; import cn.iocoder.yudao.module.camera.service.checklog.CheckLogService; import cn.iocoder.yudao.module.camera.service.order.OrderService; import cn.iocoder.yudao.module.camera.service.stock.StockService; +import cn.iocoder.yudao.module.camera.service.street.StreetService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -31,6 +33,8 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -120,13 +124,21 @@ public class OrderController { OrderDO order = orderService.getOrder(id); return success(BeanUtils.toBean(order, OrderRespVO.class)); } + @Resource + StreetService streetService; @GetMapping("/page") @Operation(summary = "获得随行记录分页") @PreAuthorize("@ss.hasPermission('logistics:order:query')") public CommonResult> getOrderPage(@Valid OrderPageReqVO pageReqVO) { PageResult pageResult = orderService.getOrderPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, OrderRespVO.class)); + PageResult pageResultVo = BeanUtils.toBean(pageResult, OrderRespVO.class); + List streetList = streetService.list(); + Map streetMap = streetList.stream().collect(Collectors.toMap(StreetDO::getPlcId, StreetDO::getName, (key1, key2) -> key1)); + pageResultVo.getList().forEach(orderRespVO -> { + orderRespVO.setStreetName(streetMap.get(orderRespVO.getSrmNumber())); + }); + return success(pageResultVo); } @GetMapping("/export-excel") diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderRespVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderRespVO.java index 0741a31..f5551dc 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderRespVO.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/order/vo/OrderRespVO.java @@ -29,6 +29,10 @@ public class OrderRespVO { @ExcelProperty("巷道id") private String srmNumber; + @Schema(description = "巷道名") + @ExcelProperty("巷道名") + private String streetName; + @Schema(description = "随行工单号", example = "26503") @ExcelProperty("随行工单号") private String taskId; diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/SpecificationConfController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/SpecificationConfController.java new file mode 100644 index 0000000..a5a4620 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/SpecificationConfController.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.camera.controller.admin.specificationConf; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfRespVO; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; +import cn.iocoder.yudao.module.camera.service.specificationConf.SpecificationConfService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管理后台 - 品规配置") +@RestController +@RequestMapping("/logistics/specification-conf") +@Validated +public class SpecificationConfController { + + @Resource + private SpecificationConfService specificationConfService; + + @PostMapping("/create") + @Operation(summary = "创建品规配置") + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:create')") + public CommonResult createSpecificationConf(@Valid @RequestBody SpecificationConfSaveReqVO createReqVO) { + return success(specificationConfService.createSpecificationConf(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新品规配置") + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:update')") + public CommonResult updateSpecificationConf(@Valid @RequestBody SpecificationConfSaveReqVO updateReqVO) { + specificationConfService.updateSpecificationConf(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除品规配置") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:delete')") + public CommonResult deleteSpecificationConf(@RequestParam("id") Integer id) { + specificationConfService.deleteSpecificationConf(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得品规配置") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:query')") + public CommonResult getSpecificationConf(@RequestParam("id") Integer id) { + SpecificationConfDO specificationConf = specificationConfService.getSpecificationConf(id); + return success(BeanUtils.toBean(specificationConf, SpecificationConfRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得品规配置分页") + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:query')") + public CommonResult> getSpecificationConfPage(@Valid SpecificationConfPageReqVO pageReqVO) { + PageResult pageResult = specificationConfService.getSpecificationConfPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, SpecificationConfRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出品规配置 Excel") + @PreAuthorize("@ss.hasPermission('logistics:specification-conf:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportSpecificationConfExcel(@Valid SpecificationConfPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = specificationConfService.getSpecificationConfPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "品规配置.xls", "数据", SpecificationConfRespVO.class, + BeanUtils.toBean(list, SpecificationConfRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfPageReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfPageReqVO.java new file mode 100644 index 0000000..19ee115 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfPageReqVO.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; + +@Schema(description = "管理后台 - 品规配置分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SpecificationConfPageReqVO extends PageParam { + + @Schema(description = "宽度单位mm") + private Integer width; + + @Schema(description = "长度单位mm") + private Integer length; + + @Schema(description = "整堆高度单位mm") + private Integer height; + + @Schema(description = "最小面积") + private Integer minArea; + + @Schema(description = "截取高度") + private Integer tolerance; + + @Schema(description = "名称", example = "张三") + private String name; + + @Schema(description = "类型", example = "1") + private String type; + + @Schema(description = "高度单位mm") + private Integer high; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfRespVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfRespVO.java new file mode 100644 index 0000000..97000fb --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfRespVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 品规配置 Response VO") +@Data +@ExcelIgnoreUnannotated +public class SpecificationConfRespVO { + + @Schema(description = "id") + @ExcelProperty("id") + private Integer id; + @Schema(description = "宽度单位mm") + @ExcelProperty("宽度单位mm") + private Integer width; + + @Schema(description = "长度单位mm") + @ExcelProperty("长度单位mm") + private Integer length; + + @Schema(description = "整堆高度单位mm") + @ExcelProperty("整堆高度单位mm") + private Integer height; + + @Schema(description = "最小面积") + @ExcelProperty("最小面积") + private Integer minArea; + + @Schema(description = "截取高度") + @ExcelProperty("截取高度") + private Integer tolerance; + + @Schema(description = "名称", example = "张三") + @ExcelProperty("名称") + private String name; + + @Schema(description = "类型", example = "1") + @ExcelProperty("类型") + private String type; + + @Schema(description = "高度单位mm") + @ExcelProperty("高度单位mm") + private Integer high; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfSaveReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfSaveReqVO.java new file mode 100644 index 0000000..e54e727 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/specificationConf/vo/SpecificationConfSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 品规配置新增/修改 Request VO") +@Data +public class SpecificationConfSaveReqVO { + + @Schema(description = "宽度单位mm") + private Integer width; + + @Schema(description = "长度单位mm") + private Integer length; + + @Schema(description = "整堆高度单位mm") + private Integer height; + + @Schema(description = "最小面积") + private Integer minArea; + + @Schema(description = "截取高度") + private Integer tolerance; + + @Schema(description = "名称", example = "张三") + private String name; + + @Schema(description = "类型", example = "1") + private String type; + + @Schema(description = "高度单位mm") + private Integer high; + @Schema(description = "高度单位mm") + private Integer id; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/WarnController.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/WarnController.java new file mode 100644 index 0000000..48f92e3 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/WarnController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.camera.controller.admin.warn; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnRespVO; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.warn.WarnDO; +import cn.iocoder.yudao.module.camera.service.warn.WarnService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 报警信息") +@RestController +@RequestMapping("/logistics/warn") +@Validated +public class WarnController { + + @Resource + private WarnService warnService; + + @PostMapping("/create") + @Operation(summary = "创建报警信息") + @PreAuthorize("@ss.hasPermission('logistics:warn:create')") + public CommonResult createWarn(@Valid @RequestBody WarnSaveReqVO createReqVO) { + return success(warnService.createWarn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新报警信息") + @PreAuthorize("@ss.hasPermission('logistics:warn:update')") + public CommonResult updateWarn(@Valid @RequestBody WarnSaveReqVO updateReqVO) { + warnService.updateWarn(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除报警信息") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('logistics:warn:delete')") + public CommonResult deleteWarn(@RequestParam("id") Long id) { + warnService.deleteWarn(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得报警信息") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('logistics:warn:query')") + public CommonResult getWarn(@RequestParam("id") Long id) { + WarnDO warn = warnService.getWarn(id); + return success(BeanUtils.toBean(warn, WarnRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得报警信息分页") + @PreAuthorize("@ss.hasPermission('logistics:warn:query')") + public CommonResult> getWarnPage(@Valid WarnPageReqVO pageReqVO) { + PageResult pageResult = warnService.getWarnPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, WarnRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出报警信息 Excel") + @PreAuthorize("@ss.hasPermission('logistics:warn:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportWarnExcel(@Valid WarnPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = warnService.getWarnPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "报警信息.xls", "数据", WarnRespVO.class, + BeanUtils.toBean(list, WarnRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnPageReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnPageReqVO.java new file mode 100644 index 0000000..6d6cfe9 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.camera.controller.admin.warn.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 报警信息分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class WarnPageReqVO extends PageParam { + + @Schema(description = "巷道标识", example = "19536") + private Integer streetId; + + @Schema(description = "开始时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] startTime; + + @Schema(description = "位置") + private String location; + + @Schema(description = "报警信号") + private String signal; + + @Schema(description = "左右") + private Integer direction; + + @Schema(description = "内外") + private Integer side; + + @Schema(description = "层") + private Integer row; + + @Schema(description = "列") + private Integer column; + + @Schema(description = "uuid", example = "8373") + private String uuid; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnRespVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnRespVO.java new file mode 100644 index 0000000..30bfb17 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.camera.controller.admin.warn.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 报警信息 Response VO") +@Data +@ExcelIgnoreUnannotated +public class WarnRespVO { + + @Schema(description = "巷道标识", example = "19536") + @ExcelProperty("巷道标识") + private Integer streetId; + + @Schema(description = "开始时间") + @ExcelProperty("开始时间") + private LocalDateTime startTime; + + @Schema(description = "位置") + @ExcelProperty("位置") + private String location; + + @Schema(description = "报警信号") + @ExcelProperty("报警信号") + private String signal; + + @Schema(description = "左右") + @ExcelProperty("左右") + private Integer direction; + + @Schema(description = "内外") + @ExcelProperty("内外") + private Integer side; + + @Schema(description = "层") + @ExcelProperty("层") + private Integer row; + + @Schema(description = "列") + @ExcelProperty("列") + private Integer column; + + @Schema(description = "uuid", example = "8373") + @ExcelProperty("uuid") + private String uuid; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnSaveReqVO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnSaveReqVO.java new file mode 100644 index 0000000..a30016e --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/controller/admin/warn/vo/WarnSaveReqVO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.camera.controller.admin.warn.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 报警信息新增/修改 Request VO") +@Data +public class WarnSaveReqVO { + + @Schema(description = "uuid", example = "8373") + private String uuid; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/specificationConf/SpecificationConfDO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/specificationConf/SpecificationConfDO.java new file mode 100644 index 0000000..a9dcf8d --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/specificationConf/SpecificationConfDO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 品规配置 DO + * + * @author 管理员 + */ +@TableName("logistics_specification_conf") +@KeySequence("logistics_specification_conf_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SpecificationConfDO extends BaseDO { + + /** + * 宽度单位mm + */ + private Integer width; + /** + * 长度单位mm + */ + private Integer length; + /** + * 整堆高度单位mm + */ + private Integer height; + /** + * 最小面积 + */ + private Integer minArea; + /** + * 截取高度 + */ + private Integer tolerance; + /** + * 名称 + */ + private String name; + /** + * 类型 + */ + private String type; + /** + * 高度单位mm + */ + private Integer high; + private Integer id; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/warn/WarnDO.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/warn/WarnDO.java new file mode 100644 index 0000000..d63edca --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/dataobject/warn/WarnDO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.camera.dal.dataobject.warn; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; + +/** + * 报警信息 DO + * + * @author 管理员 + */ +@TableName("logistics_warn") +@KeySequence("logistics_warn_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class WarnDO extends BaseDO { + + /** + * id + */ + @TableId + private Long id; + /** + * 巷道标识 + */ + private Integer streetId; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 结束时间 + */ + private LocalDateTime endTime; + /** + * 视频1 + */ + private String videoPath1; + /** + * 视频2 + */ + private String videoPath2; + /** + * 位置 + */ + private String location; + /** + * 报警信号 + */ + private String signal; + /** + * 发生告警打断的工单id order.id + */ + private Long orderId; + /** + * 左右 + */ + private Integer direction; + /** + * 内外 + */ + private Integer side; + /** + * 层 + */ + private Integer row; + /** + * 列 + */ + private Integer column; + /** + * uuid + */ + private String uuid; + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/specificationConf/SpecificationConfMapper.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/specificationConf/SpecificationConfMapper.java new file mode 100644 index 0000000..399e73f --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/specificationConf/SpecificationConfMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.camera.dal.mysql.specificationConf; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfPageReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 品规配置 Mapper + * + * @author 管理员 + */ +@Mapper +public interface SpecificationConfMapper extends BaseMapperX { + + default PageResult selectPage(SpecificationConfPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(SpecificationConfDO::getWidth, reqVO.getWidth()) + .eqIfPresent(SpecificationConfDO::getLength, reqVO.getLength()) + .eqIfPresent(SpecificationConfDO::getHeight, reqVO.getHeight()) + .eqIfPresent(SpecificationConfDO::getMinArea, reqVO.getMinArea()) + .eqIfPresent(SpecificationConfDO::getTolerance, reqVO.getTolerance()) + .likeIfPresent(SpecificationConfDO::getName, reqVO.getName()) + .eqIfPresent(SpecificationConfDO::getType, reqVO.getType()) + .eqIfPresent(SpecificationConfDO::getHigh, reqVO.getHigh()) + .orderByDesc(SpecificationConfDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/warn/WarnMapper.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/warn/WarnMapper.java new file mode 100644 index 0000000..cd0d5fc --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/dal/mysql/warn/WarnMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.camera.dal.mysql.warn; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnPageReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.warn.WarnDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 报警信息 Mapper + * + * @author 管理员 + */ +@Mapper +public interface WarnMapper extends BaseMapperX { + + default PageResult selectPage(WarnPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(WarnDO::getStreetId, reqVO.getStreetId()) + .betweenIfPresent(WarnDO::getStartTime, reqVO.getStartTime()) + .eqIfPresent(WarnDO::getLocation, reqVO.getLocation()) + .eqIfPresent(WarnDO::getSignal, reqVO.getSignal()) + .eqIfPresent(WarnDO::getDirection, reqVO.getDirection()) + .eqIfPresent(WarnDO::getSide, reqVO.getSide()) + .eqIfPresent(WarnDO::getRow, reqVO.getRow()) + .eqIfPresent(WarnDO::getColumn, reqVO.getColumn()) + .eqIfPresent(WarnDO::getUuid, reqVO.getUuid()) + .orderByDesc(WarnDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/ExtendInfo.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/ExtendInfo.java new file mode 100644 index 0000000..8e10242 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/ExtendInfo.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.camera.framework.netty.ksec; + +import lombok.Data; + +@Data +public class ExtendInfo { +// "batchNumber": "盘点批次", +// "itemCode": "品规码", +// "countNumber": "盘点数量" + private String batchNumber; + private String itemCode; + private String countNumber; +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/KsecDataInfo.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/KsecDataInfo.java index f77ca1f..d319fb5 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/KsecDataInfo.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/framework/netty/ksec/KsecDataInfo.java @@ -7,7 +7,7 @@ import lombok.Data; public class KsecDataInfo { - @JsonProperty("SRMNumber") + @JsonProperty("srmNumber") private String SRMNumber; private String cmdName; @@ -80,6 +80,7 @@ public class KsecDataInfo { * 盘点批次号 */ private String batchNumber; + private ExtendInfo extendInfo; diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java index 1f487d5..620453f 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/Hik3D/HikFlaskApiService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.camera.service.Hik3D; import cn.iocoder.yudao.module.camera.dal.dataobject.resources.URLResourcesDo; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; import cn.iocoder.yudao.module.camera.dal.entity.HikPythonEntity; @@ -56,7 +57,7 @@ public class HikFlaskApiService implements ScanService { * @param templateType 模板类型(type 字段) * @param data 模板数据(JSON 格式 Map) */ - public HikPythonEntity addTemplate(String templateType, HikPythonEntity data,String baseUrl) throws IOException { + public HikPythonEntity addTemplate(String templateType, SpecificationConfDO data, String baseUrl) throws IOException { if (templateType == null || templateType.isEmpty()) { throw new IllegalArgumentException("Missing 'type' field"); @@ -108,6 +109,30 @@ public class HikFlaskApiService implements ScanService { } } + public HikPythonEntity picBitCloudy(String type,String baseUrl) throws IOException { + HikPythonEntity requestData = new HikPythonEntity(); + requestData.setType(type); + + String json = gson.toJson(requestData); + RequestBody body = RequestBody.create(json, JSON); + + Request request = new Request.Builder() + .url(baseUrl + "/api/picBitCloudy") + .post(body) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) + System.out.println("Unexpected code " + response); + + String responseBody = Objects.requireNonNull(response.body()).string(); + log.info("picComputeAll:{}",responseBody); + return gson.fromJson(responseBody, HikPythonEntity.class); + }catch (Exception e){ + log.error("Error occurred while calling /api/picComputeAll", e); + return null; + } + } // ================== /api/picCompute ================== /** @@ -145,10 +170,52 @@ public class HikFlaskApiService implements ScanService { String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "port").getValue(); String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); try { - - scanData.setCode("缺件"); + scanData.setCode("false"); HikPythonEntity hikPythonEntity = picComputeAll(stockDO.getWmsItemCode(),urlPath); +// for (int i = 0; i < 4; i++){ +// if (hikPythonEntity == null || hikPythonEntity.getColors()==null|| hikPythonEntity.getColors().size()==0){ +// hikPythonEntity = picComputeAll(stockDO.getWmsItemCode(),urlPath); +// } +// } + log.info("hik3d拍照结果:"+hikPythonEntity.toString()); + if (hikPythonEntity != null && !hikPythonEntity.getStatus().equals("ERROR")){ + if (hikPythonEntity.getLack()!= null && hikPythonEntity.getLack()) { + }else { + scanData.setCode( "true"); + log.info("taskId:"+stockDO.getTaskId()+" hik3d拍照结果:"+hikPythonEntity.toString()); + } + if (hikPythonEntity.getColors() != null && hikPythonEntity.getColors().size() > 0) { + for (String color:hikPythonEntity.getColors()){ + if (color.startsWith(".")) { + color = color.substring(1); + } + color = picPath + color ; + urlResourcesService.save(URLResourcesDo.builder().url(color).uuid( stockDO.getCheckPic()).type("1").little("缺件拍照").build()); + } + } + } + return scanData; + } catch (IOException e) { + log.error("识别异常",e); + System.out.println("识别异常"); + e.printStackTrace(); + throw new RuntimeException(e); + } +// return null; + } + + public ScanData scanExist(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + + + String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "port").getValue(); + String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); + try { + + scanData.setCode("有货"); + + HikPythonEntity hikPythonEntity = picBitCloudy(stockDO.getWmsItemCode(),urlPath); for (int i = 0; i < 4; i++){ if (hikPythonEntity.getColors()==null|| hikPythonEntity.getColors().size()==0){ hikPythonEntity = picComputeAll(stockDO.getWmsItemCode(),urlPath); @@ -158,7 +225,7 @@ public class HikFlaskApiService implements ScanService { if (hikPythonEntity != null && !hikPythonEntity.getStatus().equals("ERROR")){ if (hikPythonEntity.getLack()!= null && hikPythonEntity.getLack()) { }else { - scanData.setCode( "正常"); + scanData.setCode( "无货"); log.info("taskId:"+stockDO.getTaskId()+" hik3d拍照结果:"+hikPythonEntity.toString()); } if (hikPythonEntity.getColors() != null && hikPythonEntity.getColors().size() > 0) { @@ -167,7 +234,7 @@ public class HikFlaskApiService implements ScanService { color = color.substring(1); } color = picPath + color ; - urlResourcesService.save(URLResourcesDo.builder().url(color).uuid( stockDO.getCheckPic()).type("1").little("缺件拍照").build()); + urlResourcesService.save(URLResourcesDo.builder().url(color).uuid( stockDO.getCheckPic()).type("1").little("有无拍照").build()); } } } @@ -180,7 +247,6 @@ public class HikFlaskApiService implements ScanService { } // return null; } - // ================== 测试方法 ================== } diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java index e43c661..585d3c6 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/order/OrderServiceImpl.java @@ -99,6 +99,7 @@ public class OrderServiceImpl implements OrderService { @Override public PageResult getOrderPage(OrderPageReqVO pageReqVO) { + return orderMapper.selectPage(pageReqVO); } diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCService.java index f44fede..f68582e 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCService.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.camera.framework.netty.streetAlgorithm.executor.A public interface PLCService { void action(String taskId,String cmd); +// 调用预置点位,先进行拍照 void checkStart(KsecDataInfo dataInfo); void checkStop(String taskId); diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java index 0c3870e..735743c 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/plc/PLCServiceImpl.java @@ -180,34 +180,76 @@ public class PLCServiceImpl implements PLCService { @Resource RedisUtil redisUtil; - void setUpdateResult(String taskId) { + void setUpdateResult(Map resultReport) { Map dictDataList = dictDataService.getDictDataList("base_conf"); if (dictDataList.get("cssc_update_result_api") != null) { String url = dictDataList.get("cssc_update_result_api").getValue(); Integer count = Integer.valueOf(dictDataList.get("cssc_set_max_count").getValue()); - Map resultMap = redisUtil.hmget("stock:task:" + taskId); - setHttp(url, resultMap, count); + setHttpUpdateStatus(url, resultReport, count); } } - void setUpdateStatus(String taskId, String cmd) { - char secondChar = cmd.charAt(1); // 获取第二个字符 - int number = Character.getNumericValue(secondChar); // 将字符转换为数字 - cmd = "E" + (number + 1); + void setUpdateStatus(StockDO stockDO, String cmd ,Map result) { + Map dictDataList = dictDataService.getDictDataList("base_conf"); if (dictDataList.get("cssc_update_status_api") != null) { String url = dictDataList.get("cssc_update_status_api").getValue(); Integer count = Integer.valueOf(dictDataList.get("cssc_set_max_count").getValue()); - Map resultMap = new HashMap<>(); - resultMap.put("cmdName", cmd); - resultMap.put("taskId", taskId); - setHttp(url, resultMap, count); + + result.put("cmdName", cmd); + result.put("taskId", stockDO.getTaskId()); + result.put("resultType", "inventory"); +// result.put("shelfCode", stockDO.getShelfCode()); + + setHttp(url, result, count); + } + } + + void setHttpUpdateStatus(String url, Map resultMap, Integer count) { + if (count == 0) { + return; + } + count--; + // 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", "application/json"); // 设置 Content-Type 为 JSON + // 创建 ObjectMapper 实例 + ObjectMapper objectMapper = new ObjectMapper(); + + // 将对象转换为 JSON 字符串 + try { + String jsonString = objectMapper.writeValueAsString(resultMap); + // 创建 HttpEntity + HttpEntity entity = new HttpEntity<>(jsonString, headers); + + log.info("request json: " + jsonString); + // 发起 POST 请求 + ResponseEntity response = restTemplate.exchange( + url, // 替换为你的 API 地址 + HttpMethod.POST, + entity, + String.class + ); + + // 输出响应结果 + log.info("Status Code: " + response.getStatusCode()); + log.info("Response Body: " + response.getBody()); + + if (!response.getStatusCode().is2xxSuccessful()) { + setHttpUpdateStatus(url, resultMap, count); + } + } catch (Exception e) { + e.printStackTrace(); + setHttpUpdateStatus(url, resultMap, count); + } + } + void setHttp(String url, Map resultMap, Integer count) { if (count == 0) { return; @@ -248,7 +290,6 @@ public class PLCServiceImpl implements PLCService { } } - @Override public void action(String taskId, String cmd) { OrderDO order = orderMapper.selectOne(new LambdaQueryWrapper() @@ -263,12 +304,15 @@ public class PLCServiceImpl implements PLCService { //OrderInfo orderInfo = new OrderInfo(street, plcCmdInfo, times, code); //判断是否拍照 boolean needCapture = false; - String picCmd = cmd.substring(0, 2); + String picCmd = cmd; Integer direction = order.getFromDirection(); - if (picCmd.equals("C4") || picCmd.equals("C3")) { + if (picCmd.endsWith("ing")){ + return; + } + if (picCmd.startsWith("unload") ) { needCapture = true; direction = order.getToDirection(); - } else if (picCmd.equals("C1") || picCmd.equals("C2")) { + } else if (picCmd.startsWith("load")) { needCapture = true; } else { @@ -311,7 +355,7 @@ public class PLCServiceImpl implements PLCService { @Override public void checkStart(KsecDataInfo dataInfo) { - dataInfo.setCountNumber("正常"); + dataInfo.setCountNumber("true"); dataInfo = dataInfo.toWMSData(); String saveApiPath = dictDataService.parseDictData("base_conf", "data_api_path").getValue(); @@ -396,6 +440,9 @@ public class PLCServiceImpl implements PLCService { // getPhotoDelayExecutor.communicationFactory(algorithmDelayTask); } + String getEndCmd(String cmd){ + return cmd.replace("inventory","").toLowerCase()+ "End"; + } public void check(String taskId, String cmd) { //根据扫码配置 获取扫码结果 Map dictDataList = dictDataService.getDictDataList("scan_conf"); @@ -419,10 +466,11 @@ public class PLCServiceImpl implements PLCService { CameraDO camera = getCameraByLeftRight(street, stock.getDirection()); // 调用预置点位 gyrateCameraByCode(camera, cmd); + Map result = new HashMap<>(); for (String scanType : scanTypes) { DictDataDO dictDataDO = dictDataList.get(scanType); ScanData scanData = scanServiceFactory.scan(dictDataDO.getValue(), street, stock); - + result.put(scanType, scanData.getCode()); redisUtil.hset("stock:task:" + taskId, scanType, scanData.getCode()); try { String wmsType = "wms" + capitalize(scanType); @@ -444,11 +492,30 @@ public class PLCServiceImpl implements PLCService { } stockService.updateById(stock); checkLog(stock); + if (cmd.contains("inventory")){ + + setUpdateStatus(stock, getEndCmd(cmd),result); + + } } - setUpdateStatus(taskId, cmd); } + public ScanData scanTest(KsecDataInfo dataInfo,String type) { + StreetDO street = streetService.getStreetByPlcId(dataInfo.getSRMNumber()); + +// 判断巷道有几个相机 如果只有一个,则调用一个,如果是两个,先判断是否有对拍设置决定那个相机拍摄 + CameraDO camera = getCameraByLeftRight(street, dataInfo.getFromDirection()); + gyrateCameraByCode(camera, dataInfo.getCmdName()); + + String pathSrc = PathUtil.createFileName(dataInfo, street, dataInfo.getCmdName(), ".jpg"); + pathSrc = cameraCapture(camera, false, pathSrc, dictDataService.getDictDataList("camera_conf")); + StockDO stockDO = new StockDO(); + stockDO.setCheckPic(pathSrc); + return scanServiceFactory.scan(type,street,stockDO); + } + public void checkStop(String taskId) { + Map resultReport = new HashMap<>(); Map dictDataList = dictDataService.getDictDataList("base_conf"); @@ -459,13 +526,16 @@ public class PLCServiceImpl implements PLCService { .orderByDesc("export_time") .last("limit 1") ); + resultReport.put("taskId", taskId); + Map result = new HashMap<>(); + resultReport.put("inventoryResult", result); + if (stock == null) { log.error("taskId:{}不存在", taskId); return; } stock.setStatus("2"); for (String key : csscStartList.keySet()) { - if (key.startsWith("E")) { String[] split = csscStartList.get(key).getValue().split(","); for (String s : split) { String wmsType = "wms" + capitalize(s); @@ -476,6 +546,9 @@ public class PLCServiceImpl implements PLCService { // 添加以下两行代码,设置字段可访问 stockField.setAccessible(true); wmsField.setAccessible(true); + resultReport.put(s, stockField.get(stock)); + result.put(s, wmsField.get(stock).toString().equals(stockField.get(stock).toString())); + if (!wmsField.get(stock).toString().equals(stockField.get(stock).toString())) { stock.setStatus("1"); } @@ -485,11 +558,10 @@ public class PLCServiceImpl implements PLCService { log.error("scan error", e); } } - } } stockService.updateById(stock); checkLog(stock); - setUpdateResult(taskId); + setUpdateResult(resultReport); redisUtil.del("stock:task:" + taskId); @@ -659,7 +731,7 @@ public class PLCServiceImpl implements PLCService { orderMapper.updateById(order); - sseClient.sendMessage(street.getPlcId()+"巷道结束盘点"); +// sseClient.sendMessage(street.getPlcId()+"巷道结束盘点"); } /** diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/QRCodeScanServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/QRCodeScanServiceImpl.java new file mode 100644 index 0000000..6dea456 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/QRCodeScanServiceImpl.java @@ -0,0 +1,267 @@ +package cn.iocoder.yudao.module.camera.service.scan; + +import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; +import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; +import cn.iocoder.yudao.module.camera.dal.entity.ScanData; +import com.google.zxing.*; +import com.google.zxing.client.j2se.BufferedImageLuminanceSource; +import com.google.zxing.common.HybridBinarizer; +import com.google.zxing.multi.GenericMultipleBarcodeReader; +import com.google.zxing.multi.MultipleBarcodeReader; +import com.google.zxing.multi.qrcode.QRCodeMultiReader; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static org.springframework.data.redis.connection.util.DecodeUtils.decodeMultiple; + +@Service +@Slf4j +public class QRCodeScanServiceImpl implements ScanService { + + @Override + public ScanData scan(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + try { + // 构建图片URL路径 + + // 从URL读取图片 + BufferedImage image = ImageIO.read(new File(stockDO.getCheckPic())); + + // 解析多个二维码 + String results = decodeQRCode(image); + scanData.setCode(results); +// +// if (results != null && results.length > 0) { +// // 将多个结果用分隔符连接 +// scanData.setCode(String.join(";", results)); +//// log.info("二维码识别成功: {}", Arrays.toString(results)); +// } else { +// scanData.setCode("二维码识别失败"); +// log.warn("二维码识别失败"); +// } + } catch (Exception e) { + log.error("二维码识别异常", e); + scanData.setCode("二维码识别异常: " + e.getMessage()); + } + return scanData; + } + + public static void main(String[] args) { + QRCodeScanServiceImpl qrCodeScanService = new QRCodeScanServiceImpl(); + + // 从URL读取图片 + BufferedImage image = null; + try { +// "C:\Users\昊天\Downloads\1.jpg" + image = ImageIO.read(new File("C:\\Users\\昊天\\Downloads\\1.jpg")); + } catch (IOException e) { + throw new RuntimeException(e); + } + + String[] results = qrCodeScanService.decodeMultipleQRCodeWithEnhancement(image); +// String results = qrCodeScanService.decodeQRCode(image); +// System.out.println("识别结果: " + results); + System.out.println("识别结果数量: " + results.length); + System.out.println("识别结果: " + Arrays.toString(results)); + } + + /** + * 增强版多二维码识别方法 + * @param image 二维码图片 + * @return 解析结果数组 + */ + private String[] decodeMultipleQRCodeWithEnhancement(BufferedImage image) { + // 尝试多种方法识别二维码 + Set results = new HashSet<>(); + + // 方法1: 直接使用多二维码识别器 + String[] method1Results = decodeMultipleQRCode(image); + results.addAll(Arrays.asList(method1Results)); + + // 方法2: 尝试不同的图像处理方式 + String[] method2Results = decodeMultipleQRCodeWithPreprocessing(image); + results.addAll(Arrays.asList(method2Results)); + + // 方法3: 分区域识别 + String[] method3Results = decodeMultipleQRCodeByRegions(image); + results.addAll(Arrays.asList(method3Results)); + + return results.toArray(new String[0]); + } + + /** + * 基础多二维码识别方法 + * @param image 二维码图片 + * @return 解析结果数组 + */ + private String[] decodeMultipleQRCode(BufferedImage image) { + decodeMultiple(); + String[] count ; + try { + LuminanceSource source = new BufferedImageLuminanceSource(image); + Binarizer binarizer = new HybridBinarizer(source); + BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); + Map hints = new HashMap(); + hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); +// Result result = new MultiFormatReader().decode(binaryBitmap, hints);//解码 + Result[] results = new QRCodeMultiReader().decodeMultiple(binaryBitmap, hints); +// System.out.println("图片中内容: "); + count = new String[results.length]; + for (int i = 0; i < results.length; i++) { +// System.out.println("第"+i+"个二维码: " + results[i].getText()+"\n"); + count[i] = results[i].getText(); +// count = "第"+i+"个二维码: " + results[i].getText()+"\n"; + } + return count; + }catch (Exception e){ + return new String[0]; + } + + } + + /** + * 带预处理的多二维码识别方法 + * @param image 二维码图片 + * @return 解析结果数组 + */ + private String[] decodeMultipleQRCodeWithPreprocessing(BufferedImage image) { + try { + // 尝试不同的预处理方式 + List results = new ArrayList<>(); + + // 原始图像 + String[] originalResults = decodeMultipleQRCode(image); + results.addAll(Arrays.asList(originalResults)); + + // 如果原始图像没有识别到,尝试其他预处理方式 + if (results.isEmpty()) { + Map hints = new HashMap<>(); + hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); + hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); + List formats = Arrays.asList(BarcodeFormat.QR_CODE); + hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); + hints.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE); + + // 尝试不同的二值化方法 + LuminanceSource source = new BufferedImageLuminanceSource(image); + Binarizer binarizer1 = new HybridBinarizer(source); + BinaryBitmap binaryBitmap1 = new BinaryBitmap(binarizer1); + + MultipleBarcodeReader reader = new GenericMultipleBarcodeReader(new MultiFormatReader()); + + try { + Result[] results1 = reader.decodeMultiple(binaryBitmap1, hints); + if (results1 != null) { + for (Result result : results1) { + if (!results.contains(result.getText())) { + results.add(result.getText()); + } + } + } + } catch (NotFoundException e) { + log.debug("预处理方法1未找到二维码", e); + } + } + + log.info("预处理多二维码识别找到 {} 个二维码", results.size()); + return results.toArray(new String[0]); + } catch (Exception e) { + log.warn("预处理多二维码解析错误", e); + return new String[0]; + } + } + + /** + * 分区域识别方法 + * @param image 二维码图片 + * @return 解析结果数组 + */ + private String[] decodeMultipleQRCodeByRegions(BufferedImage image) { + try { + List results = new ArrayList<>(); + int width = image.getWidth(); + int height = image.getHeight(); + + // 将图像分成4个区域进行识别 + int[][] regions = { + {0, 0, width/2, height/2}, // 左上 + {width/2, 0, width/2, height/2}, // 右上 + {0, height/2, width/2, height/2}, // 左下 + {width/2, height/2, width/2, height/2} // 右下 + }; + + Map hints = new HashMap<>(); + hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); + hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); + List formats = Arrays.asList(BarcodeFormat.QR_CODE); + hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); + hints.put(DecodeHintType.PURE_BARCODE, Boolean.FALSE); + + MultipleBarcodeReader reader = new GenericMultipleBarcodeReader(new MultiFormatReader()); + + for (int[] region : regions) { + try { + // 裁剪图像区域 + BufferedImage subImage = image.getSubimage(region[0], region[1], region[2], region[3]); + LuminanceSource source = new BufferedImageLuminanceSource(subImage); + Binarizer binarizer = new HybridBinarizer(source); + BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); + + Result[] regionResults = reader.decodeMultiple(binaryBitmap, hints); + if (regionResults != null) { + for (Result result : regionResults) { + if (!results.contains(result.getText())) { + results.add(result.getText()); + } + } + } + } catch (NotFoundException e) { + log.debug("区域识别未在区域找到二维码: {}", Arrays.toString(region)); + } catch (Exception e) { + log.warn("区域识别错误", e); + } + } + + log.info("分区域多二维码识别找到 {} 个二维码", results.size()); + return results.toArray(new String[0]); + } catch (Exception e) { + log.warn("分区域多二维码解析错误", e); + return new String[0]; + } + } + + /** + * 解析图片中的单个二维码(保留原有方法) + * @param image 二维码图片 + * @return 解析结果 + */ + private String decodeQRCode(BufferedImage image) { + try { + LuminanceSource source = new BufferedImageLuminanceSource(image); + Binarizer binarizer = new HybridBinarizer(source); + BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); + + Map hints = new HashMap<>(); + hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); + hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); + // 修复错误:需要传入Collection类型而不是单个BarcodeFormat + List formats = Arrays.asList(BarcodeFormat.QR_CODE); + hints.put(DecodeHintType.POSSIBLE_FORMATS, formats); + + Result result = new MultiFormatReader().decode(binaryBitmap, hints); + return result.getText(); + } catch (NotFoundException e) { + log.warn("未找到二维码", e); + return null; + } catch (Exception e) { + log.error("二维码解析错误", e); + return null; + } + } +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java index 1ddce3a..0a1200a 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/ScanServiceFactory.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; import cn.iocoder.yudao.module.camera.dal.entity.ScanData; import cn.iocoder.yudao.module.camera.service.Hik3D.HikFlaskApiService; +import cn.iocoder.yudao.module.camera.service.scan.yoloCameraApi.YoloServiceImpl; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -23,6 +24,8 @@ public class ScanServiceFactory { private OpencvServiceImpl opencvService; @Resource private HikFlaskApiService hikFlaskApiService; + @Resource + private QRCodeScanServiceImpl qrCodeScanService; // 返回的ScanData的code会将作为扫描结果,如果和wms的一致,则记录为成功 @@ -44,23 +47,40 @@ public class ScanServiceFactory { return rfidScanService.scan(streetDO, stockDO); // 视觉扫码 case "3": - log.info("视觉扫码"); - return yoloService.scan(streetDO, stockDO); - + log.info("视觉扫码-分类"); + return yoloService.scanClassify(streetDO, stockDO); // 3D扫码 case "4": log.info("3D扫码"); return pcdService.scan(streetDO, stockDO); - // opencv扫码 case "5": log.info("opencv扫码"); return opencvService.scan(streetDO, stockDO); - // hik3d识别扫码 case "6": log.info("hik3d识别扫码"); return hikFlaskApiService.scan(streetDO, stockDO); + // hik3d识别扫码存在 + case "7": + log.info("hik3d识别扫码存在"); + return hikFlaskApiService.scanExist(streetDO, stockDO); + // hik3d识别扫码存在 + case "8": + log.info("lx识别扫码存在"); + return yoloService.scanExist(streetDO, stockDO); + // hik3d识别扫码存在 + case "9": + log.info("yolo识别扫码-检测"); + return yoloService.scanDetect(streetDO, stockDO); + // hik3d识别扫码存在 + case "10": + log.info("yolo识别扫码-球机检测"); + return yoloService.scanCameraDetect(streetDO, stockDO); + // 二维码识别 + case "11": + log.info("二维码识别"); + return qrCodeScanService.scan(streetDO, stockDO); // 默认情况处理 default: return new ScanData(); diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/YoloServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/YoloServiceImpl.java deleted file mode 100644 index 61e849b..0000000 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/YoloServiceImpl.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.camera.service.scan; - -import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; -import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; -import cn.iocoder.yudao.module.camera.dal.entity.ScanData; -import org.springframework.stereotype.Service; - -@Service("yoloService") -public class YoloServiceImpl implements ScanService{ - @Override - public ScanData scan(StreetDO streetDO, StockDO stockDO) { - return null; - } -} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/BoundingBox.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/BoundingBox.java new file mode 100644 index 0000000..0c9c9b3 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/BoundingBox.java @@ -0,0 +1,15 @@ +package cn.iocoder.yudao.module.camera.service.scan.yoloCameraApi; + +import lombok.Data; + +@Data +public class BoundingBox { + private double x; + private double y; + private double w; + private double h; + private double confidence; + private int classId; + private String classProb; + +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/Pojo.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/Pojo.java new file mode 100644 index 0000000..4b2bd39 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/Pojo.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.camera.service.scan.yoloCameraApi; + +import lombok.Data; + +import java.util.List; + +@Data +public class Pojo { + //旋转路径 + private String rotationPath; + //判定路径 + private String determinePath; + //结果 + private Boolean result; + private String type; + private List detects; + private String path; + private String streetId; + private Integer direction; +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/YoloServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/YoloServiceImpl.java new file mode 100644 index 0000000..b041e25 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/scan/yoloCameraApi/YoloServiceImpl.java @@ -0,0 +1,215 @@ +package cn.iocoder.yudao.module.camera.service.scan.yoloCameraApi; + +import cn.iocoder.yudao.module.camera.dal.dataobject.resources.URLResourcesDo; +import cn.iocoder.yudao.module.camera.dal.dataobject.stock.StockDO; +import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; +import cn.iocoder.yudao.module.camera.dal.entity.ScanData; +import cn.iocoder.yudao.module.camera.service.resources.URLResourcesService; +import cn.iocoder.yudao.module.camera.service.scan.ScanService; +import cn.iocoder.yudao.module.system.service.dict.DictDataService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.google.gson.Gson; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +@Service("yoloService") +@Slf4j +public class YoloServiceImpl implements ScanService { + + private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); + @Resource + private OkHttpClient client; + private final Gson gson = new Gson(); + + + @Resource + private DictDataService dictDataService; + @Override + public ScanData scan(StreetDO streetDO, StockDO stockDO) { + return null; + } + + /** + * 识别是否存在 + * @param streetDO + * @param stockDO + * @return + */ + public ScanData scanExist(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + + + String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "yoloApiPort").getValue(); + String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); + try { + scanData.setCode("有货"); + Pojo pojo = new Pojo(); + pojo.setStreetId(streetDO.getPlcId()); + pojo.setDirection(stockDO.getDirection()); + pojo = setHttp(pojo,urlPath+"/category/exist"); + + log.info("lx3d拍照结果:"+pojo.toString()); + + if (pojo.getResult()!= null && pojo.getResult()) { + }else { + scanData.setCode( "无货"); + log.info("taskId:"+stockDO.getTaskId()+" lx3d拍照结果:"+pojo.toString()); + } +// if (hikPythonEntity.getColors() != null && hikPythonEntity.getColors().size() > 0) { +// for (String color:hikPythonEntity.getColors()){ +// if (color.startsWith(".")) { +// color = color.substring(1); +// } +// color = picPath + color ; +// urlResourcesService.save(URLResourcesDo.builder().url(color).uuid( stockDO.getCheckPic()).type("1").little("有无拍照").build()); +// } +// } + return scanData; + } catch (IOException e) { + log.error("识别异常",e); + System.out.println("识别异常"); + e.printStackTrace(); + throw new RuntimeException(e); + } +// return null; + } + + @Resource + URLResourcesService urlResourcesService; + + /** + * 识别是否存在 + * @param streetDO + * @param stockDO + * @return + */ + public ScanData scanClassify(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + + + String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "yoloApiPort").getValue(); + String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); + try { +// scanData.setCode("有货"); + Pojo pojo = new Pojo(); + pojo.setStreetId(streetDO.getPlcId()); + pojo.setDirection(stockDO.getDirection()); + pojo = setHttp(pojo,urlPath+"/yolo/classify"); + + log.info("lx3d拍照结果:"+pojo.toString()); + scanData.setCode(pojo.getType()); + urlResourcesService.save(URLResourcesDo.builder().url(picPath+pojo.getPath()).uuid( stockDO.getCheckPic()).type("1").little("有无拍照").build()); + return scanData; + } catch (IOException e) { + log.error("识别异常",e); + System.out.println("识别异常"); + e.printStackTrace(); + throw new RuntimeException(e); + } +// return null; + } + + /** + * 识别是否存在 + * @param streetDO + * @param stockDO + * @return + */ + public ScanData scanDetect(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "yoloApiPort").getValue(); + String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); + try { +// scanData.setCode("有货"); + Pojo pojo = new Pojo(); + pojo.setStreetId(streetDO.getPlcId()); + pojo.setDirection(stockDO.getDirection()); + pojo = setHttp(pojo,urlPath+"/yolo/detect"); + + log.info("lx3d拍照结果:"+pojo.toString()); + scanData.setCode(pojo.getType()); + urlResourcesService.save(URLResourcesDo.builder().url(picPath+pojo.getPath()).uuid( stockDO.getCheckPic()).type("1").little("有无拍照").build()); + return scanData; + } catch (IOException e) { + log.error("识别异常",e); + System.out.println("识别异常"); + e.printStackTrace(); + throw new RuntimeException(e); + } +// return null; + } + + + /** + * 识别是否存在 + * @param streetDO + * @param stockDO + * @return + */ + public ScanData scanCameraDetect(StreetDO streetDO, StockDO stockDO) { + ScanData scanData = new ScanData(); + String urlPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "yoloApiPort").getValue(); + String picPath ="http://"+streetDO.getPlcIp() + ":" + dictDataService.parseDictData("Hik3DApi", "picPath").getValue(); + + String realPath = dictDataService.getDictDataList("camera_conf").get("media_path").getValue(); + + String saveApiPath = dictDataService.parseDictData("base_conf", "data_api_path").getValue(); + try { +// scanData.setCode("有货"); + List urls = urlResourcesService.list(new LambdaQueryWrapper().eq(URLResourcesDo::getUuid, stockDO.getCheckPic())); + for (URLResourcesDo url:urls) { + Pojo pojo = new Pojo(); + pojo.setStreetId(streetDO.getPlcId()); + pojo.setPath(realPath+url.getUrl().replace(saveApiPath,"")); + pojo.setDirection(stockDO.getDirection()); + pojo = setHttp(pojo, urlPath + "/yolo/detect"); + + log.info("lx3d拍照结果:" + pojo.toString()); + if (pojo.getType()!= null && !pojo.getType().equals("")){ + scanData.setCode(pojo.getType()); + } + } +// urlResourcesService.save(URLResourcesDo.builder().url(picPath+pojo.getPath()).uuid( stockDO.getCheckPic()).type("1").little("有无拍照").build()); + return scanData; + } catch (IOException e) { + log.error("识别异常",e); + System.out.println("识别异常"); + e.printStackTrace(); + throw new RuntimeException(e); + } +// return null; + } + /** + * 调用 /api/picComputeAll 接口,批量处理所有设备图片 + */ + public Pojo setHttp(Pojo pojo, String baseUrl) throws IOException { + + + String json = gson.toJson(pojo); + RequestBody body = RequestBody.create(json, JSON); + + Request request = new Request.Builder() + .url(baseUrl) + .post(body) + .build(); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) + System.out.println("Unexpected code " + response); + + String responseBody = Objects.requireNonNull(response.body()).string(); + log.info("picComputeAll:{}",responseBody); + return gson.fromJson(responseBody, Pojo.class); + }catch (Exception e){ + log.error("Error occurred while calling "+baseUrl, e); + return null; + } + } + +} diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java index af0d9ad..80e6a96 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/sensorgun/CognexSocket.java @@ -8,6 +8,7 @@ import java.io.*; import java.net.InetSocketAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; +import java.util.function.Predicate; @Slf4j public class CognexSocket { @@ -20,6 +21,7 @@ public class CognexSocket { InputStream is = null; try { socket.connect(new InetSocketAddress(ip,port),3000); + socket.setSoTimeout(3000); os = socket.getOutputStream(); is = socket.getInputStream(); int i = 0; @@ -80,4 +82,86 @@ public class CognexSocket { BufferedReader bd = new BufferedReader(new InputStreamReader(inStream)); return bd.readLine(); } + + /** + * 建立TCP连接并发送命令,根据函数式参数判断返回值 + * + * @param ip IP地址 + * @param port 端口号 + * @param responseValidator 函数式参数,用于验证返回值 + * @return 符合条件的返回值或"NOREAD" + */ + public static String readOCR(String ip, int port, + Predicate responseValidator) { + + Socket socket = new Socket(); + OutputStream os = null; + InputStream is = null; + BufferedReader reader = null; + + try { + // 建立连接,设置3秒超时 + socket.connect(new InetSocketAddress(ip, port), 3000); + socket.setSoTimeout(3000); + + os = socket.getOutputStream(); + is = socket.getInputStream(); + reader = new BufferedReader(new InputStreamReader(is)); + + // 发送 "+" 命令 + os.write("+".getBytes()); + os.flush(); + + long startTime = System.currentTimeMillis(); + + // 循环读取返回数据,直到3秒超时或找到符合条件的返回 + while (System.currentTimeMillis() - startTime < 3000) { + String response = reader.readLine(); + log.info("Response: {}", response); + + // 如果读取到数据 + if (response != null) { + // 使用函数式参数验证返回值 + if (responseValidator.test(response)) { + // 如果验证通过,发送 "-" 命令并返回结果 + os.write("-".getBytes()); + os.flush(); + return response; + } + } + } + + } catch (IOException e) { + // 记录异常但不抛出,返回默认值 + e.printStackTrace(); + } finally { + // 清理资源 + try { + if (reader != null) reader.close(); + if (is != null) is.close(); + if (os != null) os.close(); + if (socket != null) socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 超时或未找到符合条件的返回值 + return "NOREAD"; + } + + // 使用示例 + public static void main(String[] args) { +// // 示例:查找包含"SUCCESS"的返回 +// String result = readOCR("192.168.0.113", 23, +// response -> response.contains("SUCCESS")); +// System.out.println("Result: " + result); +// +// // 示例:查找以"CODE:"开头的返回 +// String result2 = readOCR("192.168.1.100", 8080, +// response -> response.startsWith("CODE:")); +// System.out.println("Result2: " + result2); + String result = readOCR("192.168.0.113", 23); + System.out.println("Result: " + result); + } } diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfService.java new file mode 100644 index 0000000..89d0bb4 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.camera.service.specificationConf; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; +import jakarta.validation.Valid; + +/** + * 品规配置 Service 接口 + * + * @author 管理员 + */ +public interface SpecificationConfService { + + /** + * 创建品规配置 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Integer createSpecificationConf(@Valid SpecificationConfSaveReqVO createReqVO); + + /** + * 更新品规配置 + * + * @param updateReqVO 更新信息 + */ + void updateSpecificationConf(@Valid SpecificationConfSaveReqVO updateReqVO); + + /** + * 删除品规配置 + * + * @param id 编号 + */ + void deleteSpecificationConf(Integer id); + + /** + * 获得品规配置 + * + * @param id 编号 + * @return 品规配置 + */ + SpecificationConfDO getSpecificationConf(Integer id); + + /** + * 获得品规配置分页 + * + * @param pageReqVO 分页查询 + * @return 品规配置分页 + */ + PageResult getSpecificationConfPage(SpecificationConfPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfServiceImpl.java new file mode 100644 index 0000000..fbbcaf1 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/specificationConf/SpecificationConfServiceImpl.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.camera.service.specificationConf; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.specificationConf.vo.SpecificationConfSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.specificationConf.SpecificationConfDO; +import cn.iocoder.yudao.module.camera.dal.dataobject.street.StreetDO; +import cn.iocoder.yudao.module.camera.dal.mysql.specificationConf.SpecificationConfMapper; +import cn.iocoder.yudao.module.camera.dal.mysql.street.StreetMapper; +import cn.iocoder.yudao.module.camera.service.Hik3D.HikFlaskApiService; +import cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; + +/** + * 品规配置 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class SpecificationConfServiceImpl implements SpecificationConfService { + + @Resource + private SpecificationConfMapper specificationConfMapper; + @Resource + private HikFlaskApiService hikFlaskApiService; + + @Resource + private StreetMapper streetMapper; + + + + + @Override + public Integer createSpecificationConf(SpecificationConfSaveReqVO createReqVO) { + // 插入 + SpecificationConfDO specificationConf = BeanUtils.toBean(createReqVO, SpecificationConfDO.class); + specificationConfMapper.insert(specificationConf); + List streetDOList = streetMapper.selectList(); + for (StreetDO streetDO : streetDOList) { + try { + hikFlaskApiService.addTemplate(specificationConf.getType(), specificationConf,"http://"+streetDO.getPlcIp()+":5000"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + // 返回 + return specificationConf.getId(); + } + + @Override + public void updateSpecificationConf(SpecificationConfSaveReqVO updateReqVO) { + // 校验存在 + validateSpecificationConfExists(updateReqVO.getId()); + // 更新 + SpecificationConfDO updateObj = BeanUtils.toBean(updateReqVO, SpecificationConfDO.class); + + specificationConfMapper.updateById(updateObj); + SpecificationConfDO specificationConfDO = specificationConfMapper.selectById(updateReqVO.getId()); + + List streetDOList = streetMapper.selectList(); + for (StreetDO streetDO : streetDOList) { + try { + hikFlaskApiService.addTemplate(specificationConfDO.getType(), specificationConfDO,"http://"+streetDO.getPlcIp()+":5000"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void deleteSpecificationConf(Integer id) { + // 校验存在 + validateSpecificationConfExists(id); + // 删除 + specificationConfMapper.deleteById(id); + } + + private void validateSpecificationConfExists(Integer id) { + if (specificationConfMapper.selectById(id) == null) { + throw exception(ErrorCodeConstants.SPECIFICATION_CONF_NOT_EXISTS); + } + } + + @Override + public SpecificationConfDO getSpecificationConf(Integer id) { + return specificationConfMapper.selectById(id); + } + + @Override + public PageResult getSpecificationConfPage(SpecificationConfPageReqVO pageReqVO) { + return specificationConfMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java index 80deabe..d5a6f57 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/streamingMedia/ZLMediaKitServiceImpl.java @@ -34,6 +34,8 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.lang.Thread.sleep; + @Service @Validated @Slf4j @@ -286,6 +288,11 @@ public class ZLMediaKitServiceImpl implements ZLMediaKitService{ // addParams.put("url", CameraChannel.getRtspUrl(camera.getIp(), camera.getRtspPort(), camera.getChannel(), camera.getUser(), camera.getPassword(),camera.getType())); RtspSessionResponse rtspSessionResponse = sendHttp(addParams, "stopRecord"); if (rtspSessionResponse!=null && rtspSessionResponse.isResult()){ + try { + sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } String fileName = getLatestCameraFileNameAfterTime(app, "camera"+stream, time.minusSeconds(10)); return fileName; }else { diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnService.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnService.java new file mode 100644 index 0000000..814954f --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.camera.service.warn; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.warn.WarnDO; +import jakarta.validation.Valid; + +/** + * 报警信息 Service 接口 + * + * @author 管理员 + */ +public interface WarnService { + + /** + * 创建报警信息 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarn(@Valid WarnSaveReqVO createReqVO); + + /** + * 更新报警信息 + * + * @param updateReqVO 更新信息 + */ + void updateWarn(@Valid WarnSaveReqVO updateReqVO); + + /** + * 删除报警信息 + * + * @param id 编号 + */ + void deleteWarn(Long id); + + /** + * 获得报警信息 + * + * @param id 编号 + * @return 报警信息 + */ + WarnDO getWarn(Long id); + + /** + * 获得报警信息分页 + * + * @param pageReqVO 分页查询 + * @return 报警信息分页 + */ + PageResult getWarnPage(WarnPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnServiceImpl.java b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnServiceImpl.java new file mode 100644 index 0000000..dfe9df8 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/java/cn/iocoder/yudao/module/camera/service/warn/WarnServiceImpl.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.camera.service.warn; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnPageReqVO; +import cn.iocoder.yudao.module.camera.controller.admin.warn.vo.WarnSaveReqVO; +import cn.iocoder.yudao.module.camera.dal.dataobject.warn.WarnDO; +import cn.iocoder.yudao.module.camera.dal.mysql.warn.WarnMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.WARN_NOT_EXISTS; + + +/** + * 报警信息 Service 实现类 + * + * @author 管理员 + */ +@Service +@Validated +public class WarnServiceImpl implements WarnService { + + @Resource + private WarnMapper warnMapper; + + @Override + public Long createWarn(WarnSaveReqVO createReqVO) { + // 插入 + WarnDO warn = BeanUtils.toBean(createReqVO, WarnDO.class); + warnMapper.insert(warn); + // 返回 + return warn.getId(); + } + + @Override + public void updateWarn(WarnSaveReqVO updateReqVO) { + + } + + @Override + public void deleteWarn(Long id) { + // 校验存在 + validateWarnExists(id); + // 删除 + warnMapper.deleteById(id); + } + + private void validateWarnExists(Long id) { + if (warnMapper.selectById(id) == null) { + throw exception(WARN_NOT_EXISTS); + } + } + + @Override + public WarnDO getWarn(Long id) { + return warnMapper.selectById(id); + } + + @Override + public PageResult getWarnPage(WarnPageReqVO pageReqVO) { + return warnMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/cameraio/CameraIoMapper.xml b/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/cameraio/CameraIoMapper.xml index a9b6592..98c3326 100644 --- a/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/cameraio/CameraIoMapper.xml +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/cameraio/CameraIoMapper.xml @@ -1,6 +1,6 @@ - + + + \ No newline at end of file diff --git a/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/warn/WarnMapper.xml b/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/warn/WarnMapper.xml new file mode 100644 index 0000000..48422f4 --- /dev/null +++ b/yudao-module-logistics/yudao-module-logistics-biz/src/main/resources/mapper/warn/WarnMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index 082b6b4..1affa5b 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -28,6 +28,16 @@ yudao-module-infra-api ${revision} + + com.google.zxing + core + 3.5.1 + + + com.google.zxing + javase + 3.5.1 + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java index 62c112a..27e2c1e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/dict/DictDataServiceImpl.java @@ -19,6 +19,7 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; @@ -51,15 +52,32 @@ public class DictDataServiceImpl extends ServiceImpl @PostConstruct void init(){ -// log.info("init DictDataServiceImpl"); -// 删除 + // 获取所有字典数据 List list = dictDataMapper.selectList(); - Map> map = list.stream().collect(Collectors.groupingBy(DictDataDO::getDictType)); - map.forEach((k,v)->{ - - redisUtil.del("dict:"+k); - redisUtil.hsetList("dict:"+k, v.stream().collect(Collectors.toMap(DictDataDO::getLabel,DictDataDO::getValue))); + + // 按字典类型分组 + Map> map = list.stream() + .collect(Collectors.groupingBy(DictDataDO::getDictType)); + + System.out.println(LocalTime.now()); + + // 批量处理每个字典类型 + map.forEach((dictType, dictDataList) -> { + // 构造Redis key + String redisKey = "dict:" + dictType; + + // 一次性删除旧数据 + redisUtil.del(redisKey); + + // 批量构造数据 + Map dictMap = dictDataList.stream() + .collect(Collectors.toMap(DictDataDO::getLabel, DictDataDO::getValue)); + + // 一次性写入所有数据到Redis + redisUtil.hmset(redisKey, new HashMap<>(dictMap)); }); + + System.out.println(LocalTime.now()); } @Override diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 74f5830..5b054c6 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -48,6 +48,12 @@ ${revision} + + cn.iocoder.boot + yudao-module-annotation-biz + ${revision} + + cn.iocoder.boot yudao-module-camera-biz diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 989cad1..d31f72a 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -5,6 +5,12 @@ server: spring: # 数据源配置项 + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 + - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 + - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 datasource: druid: # Druid 【监控】相关的全局配置 web-stat-filter: @@ -26,32 +32,25 @@ spring: multi-statement-allow: true dynamic: # 多数据源配置 druid: # Druid 【连接池】相关的全局配置 - initial-size: 5 # 初始连接数 - min-idle: 10 # 最小连接池数量 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 max-active: 20 # 最大连接池数量 max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 - validation-query: SELECT 1 # 配置检测连接是否有效 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 test-while-idle: true test-on-borrow: false test-on-return: false primary: master datasource: master: - name: ruoyi-vue-pro - url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&serverTimezone=CTT&allowPublicKeyRetrieval=true - driver-class-name: com.mysql.jdbc.Driver - username: root - password: 3WLiVUBEwTbvAfsh - slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改 - name: ruoyi-vue-pro - url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&serverTimezone=CTT&allowPublicKeyRetrieval=true - driver-class-name: com.mysql.jdbc.Driver - username: root - password: 3WLiVUBEwTbvAfsh + name: sy + url: jdbc:mysql://121.43.244.209:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + username: root + password: Sy+1234567 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: redis: @@ -63,17 +62,17 @@ spring: max-wait: 5000ms # 增加获取连接的最大等待时间 shutdown-timeout: 1000ms # 增加关闭超时时间 timeout: 5000ms # 增加连接超时时间 - host: 127.0.0.1 # 地址 + host: 121.43.244.209 # 地址 port: 6379 # 端口 - database: 1 # 数据库索引 -# password: 123456 # 密码,建议生产环境开启 + database: 0 # 数据库索引 +# password: dev # 密码,建议生产环境开启 --- #################### 定时任务相关配置 #################### # Quartz 配置项,对应 QuartzProperties 配置类 spring: quartz: - auto-startup: true # 测试环境,需要开启 Job + auto-startup: true # 本地开发环境,尽量不要开启 Job scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true @@ -110,8 +109,8 @@ spring: rabbitmq: host: 127.0.0.1 # RabbitMQ 服务的地址 port: 5672 # RabbitMQ 服务的端口 - username: guest # RabbitMQ 服务的账号 - password: guest # RabbitMQ 服务的密码 + username: rabbit # RabbitMQ 服务的账号 + password: rabbit # RabbitMQ 服务的密码 # Kafka 配置项,对应 KafkaProperties 配置类 kafka: bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 @@ -122,7 +121,9 @@ spring: lock4j: acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 - +yudao: + tenant: + enable: false --- #################### 监控相关配置 #################### # Actuator 监控端点的配置项 @@ -149,21 +150,49 @@ spring: logging: file: name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 - ---- #################### 微信公众号相关配置 #################### -wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 - mp: - # 公众号配置(必填) - app-id: wx041349c6f39b268b - secret: 5abee519483bc9f8cb37ce280e814bd0 + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.bpm.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印 + cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info + cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info + cn.iocoder.yudao.module.pay.dal.mysql: debug + cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info + cn.iocoder.yudao.module.system.dal.mysql: debug + cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info + cn.iocoder.yudao.module.tool.dal.mysql: debug + cn.iocoder.yudao.module.member.dal.mysql: debug + cn.iocoder.yudao.module.trade.dal.mysql: debug + cn.iocoder.yudao.module.promotion.dal.mysql: debug + cn.iocoder.yudao.module.statistics.dal.mysql: debug + cn.iocoder.yudao.module.crm.dal.mysql: debug + cn.iocoder.yudao.module.erp.dal.mysql: debug + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 + +debug: false + +--- #################### 微信公众号、小程序相关配置 #################### +wx: + mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 + # app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) + # secret: 5abee519483bc9f8cb37ce280e814bd0 + app-id: wx5b23ba7a5589ecbb # 测试号(自己的) + secret: 2a7b3b20c537e52e74afd395eb85f61f + # app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) + # secret: bd4f9fab889591b62aeac0d7b8d8b4a0 # 存储配置,解决 AccessToken 的跨节点的共享 config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wx # Redis Key 的前缀 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 - appid: wx63c280fe3248a3e7 + # appid: wx62056c0d5e8db250 # 测试号(牛希尧提供的) + # secret: 333ae72f41552af1e998fe1f54e1584a + appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 secret: 6f270509224a7ae1296bbf1c8cb97aed + # appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) + # secret: 4a1a04e07f6a4a0751b39c3064a92c8b config-storage: type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 key-prefix: wa # Redis Key 的前缀 @@ -173,6 +202,10 @@ wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-sta # 芋道配置项,设置当前项目所有自定义的配置 yudao: + captcha: + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; + security: + mock-enable: true xss: enable: false exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 @@ -181,7 +214,9 @@ yudao: pay: order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 - demo: true # 开启演示模式 + access-log: # 访问日志的配置项 + enable: false + demo: false # 关闭演示模式 tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc justauth: @@ -196,7 +231,17 @@ justauth: client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw agent-id: 1000004 ignore-check-redirect-uri: true + WECHAT_MINI_APP: # 微信小程序 + client-id: ${wx.miniapp.appid} + client-secret: ${wx.miniapp.secret} + ignore-check-redirect-uri: true + ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 + WECHAT_MP: # 微信公众号 + client-id: ${wx.mp.app-id} + client-secret: ${wx.mp.secret} + ignore-check-redirect-uri: true cache: type: REDIS prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: - timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 \ No newline at end of file + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 + diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 1b847eb..32d0321 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -1,5 +1,5 @@ server: - port: 48081 + port: 48080 --- #################### 数据库相关配置 #################### @@ -55,7 +55,7 @@ spring: # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 username: root - password: root + password: Sy+1234567 # username: sa # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # username: SYSDBA # DM 连接的示例 diff --git a/yudao-server/src/main/resources/application-prod.yaml b/yudao-server/src/main/resources/application-prod.yaml new file mode 100644 index 0000000..9bc6551 --- /dev/null +++ b/yudao-server/src/main/resources/application-prod.yaml @@ -0,0 +1,269 @@ +server: + port: 48080 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 + - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 + - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 + - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 1 # 初始连接数 + min-idle: 1 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: sy + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + # url: jdbc:mysql://192.168.2.162:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 + # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例 + # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 + # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 + # url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 + + username: root + password: Sy+1234567 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + # username: SYSDBA # DM 连接的示例 + # password: SYSDBA # DM 连接的示例 +# slave: # 模拟从库,可根据自己需要修改 +# name: ruoyi-vue-pro +# lazy: true # 开启懒加载,保证启动速度 +# url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 +# # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 +# # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 +# # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 +# # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 +# username: root +# password: 123456 + # username: sa + # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + data: + redis: + lettuce: + pool: + max-active: 100 # 增加最大连接数 + max-idle: 50 # 增加最大空闲连接数 + min-idle: 10 # 增加最小空闲连接数 + max-wait: 5000ms # 增加获取连接的最大等待时间 + shutdown-timeout: 1000ms # 增加关闭超时时间 + timeout: 5000ms # 增加连接超时时间 + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 +# password: dev # 密码,建议生产环境开启 + +--- #################### 定时任务相关配置 #################### + +# Quartz 配置项,对应 QuartzProperties 配置类 +spring: + quartz: + auto-startup: true # 本地开发环境,尽量不要开启 Job + scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName + job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。 + wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true + properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 + org: + quartz: + # Scheduler 相关配置 + scheduler: + instanceName: schedulerName + instanceId: AUTO # 自动生成 instance ID + # JobStore 相关配置 + jobStore: + # JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162 + class: org.springframework.scheduling.quartz.LocalDataSourceJobStore + isClustered: true # 是集群模式 + clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒 + misfireThreshold: 60000 # misfire 阀值,单位:毫秒。 + # 线程池相关配置 + threadPool: + threadCount: 25 # 线程池大小。默认为 10 。 + threadPriority: 5 # 线程优先级 + class: org.quartz.simpl.SimpleThreadPool # 线程池类型 + jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置 + initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。 + +--- #################### 消息队列相关 #################### +# +## rocketmq 配置项,对应 RocketMQProperties 配置类 +#rocketmq: +# name-server: 192.168.2.162:9876 # RocketMQ Namesrv +# +#spring: +# # RabbitMQ 配置项,对应 RabbitProperties 配置类 +# rabbitmq: +# host: 192.168.2.162 # RabbitMQ 服务的地址 +# port: 5672 # RabbitMQ 服务的端口 +# username: rabbit # RabbitMQ 服务的账号 +# password: rabbit # RabbitMQ 服务的密码 +# # Kafka 配置项,对应 KafkaProperties 配置类 +# kafka: +# bootstrap-servers: 192.168.2.162:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔 + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 +yudao: + tenant: + enable: false +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://192.168.2.162:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME] + # Spring Boot Admin Server 服务端的相关配置 + context-path: /admin # 配置 Spring + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + level: + # 配置自己写的 MyBatis Mapper 打印日志 + cn.iocoder.yudao.module.bpm.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql: debug + cn.iocoder.yudao.module.infra.dal.mysql.logger.ApiErrorLogMapper: INFO # 配置 ApiErrorLogMapper 的日志级别为 info,避免和 GlobalExceptionHandler 重复打印 + cn.iocoder.yudao.module.infra.dal.mysql.job.JobLogMapper: INFO # 配置 JobLogMapper 的日志级别为 info + cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper: INFO # 配置 FileConfigMapper 的日志级别为 info + cn.iocoder.yudao.module.pay.dal.mysql: debug + cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info + cn.iocoder.yudao.module.system.dal.mysql: debug + cn.iocoder.yudao.module.system.dal.mysql.sms.SmsChannelMapper: INFO # 配置 SmsChannelMapper 的日志级别为 info + cn.iocoder.yudao.module.tool.dal.mysql: debug + cn.iocoder.yudao.module.member.dal.mysql: debug + cn.iocoder.yudao.module.trade.dal.mysql: debug + cn.iocoder.yudao.module.promotion.dal.mysql: debug + cn.iocoder.yudao.module.statistics.dal.mysql: debug + cn.iocoder.yudao.module.crm.dal.mysql: debug + cn.iocoder.yudao.module.erp.dal.mysql: debug + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 + +debug: false + +--- #################### 微信公众号、小程序相关配置 #################### +wx: + mp: # 公众号配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档 +# app-id: wx041349c6f39b268b # 测试号(牛希尧提供的) +# secret: 5abee519483bc9f8cb37ce280e814bd0 + app-id: wx5b23ba7a5589ecbb # 测试号(自己的) + secret: 2a7b3b20c537e52e74afd395eb85f61f +# app-id: wxa69ab825b163be19 # 测试号(Kongdy 提供的) +# secret: bd4f9fab889591b62aeac0d7b8d8b4a0 + # 存储配置,解决 AccessToken 的跨节点的共享 + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wx # Redis Key 的前缀 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 + # appid: wx62056c0d5e8db250 # 测试号(牛希尧提供的) + # secret: 333ae72f41552af1e998fe1f54e1584a + appid: wx63c280fe3248a3e7 # wenhualian的接口测试号 + secret: 6f270509224a7ae1296bbf1c8cb97aed +# appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的) +# secret: 4a1a04e07f6a4a0751b39c3064a92c8b + config-storage: + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取 + key-prefix: wa # Redis Key 的前缀 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + captcha: + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试; + security: + mock-enable: true + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + pay: + order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址 + refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址 + access-log: # 访问日志的配置项 + enable: false + demo: false # 关闭演示模式 + tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc + +justauth: + enabled: true + type: + DINGTALK: # 钉钉 + client-id: dingvrnreaje3yqvzhxg + client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI + ignore-check-redirect-uri: true + WECHAT_ENTERPRISE: # 企业微信 + client-id: wwd411c69a39ad2e54 + client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw + agent-id: 1000004 + ignore-check-redirect-uri: true + WECHAT_MINI_APP: # 微信小程序 + client-id: ${wx.miniapp.appid} + client-secret: ${wx.miniapp.secret} + ignore-check-redirect-uri: true + ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验 + WECHAT_MP: # 微信公众号 + client-id: ${wx.mp.app-id} + client-secret: ${wx.mp.secret} + ignore-check-redirect-uri: true + cache: + type: REDIS + prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE:: + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟 + diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 7a48b52..86570b0 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -3,7 +3,8 @@ spring: name: yudao-server profiles: - active: local + active: dev + main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 @@ -75,6 +76,7 @@ mybatis-plus: logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) banner: false # 关闭控制台的 Banner 打印 type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject + type-handlers-package: com.baomidou.mybatisplus.extension.handlers # 添加这行 encryptor: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成