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/ 网站生成