diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java index e45570e..5a9d84c 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java @@ -1,188 +1,188 @@ -package org.jeecg.config; - - -import io.swagger.annotations.ApiOperation; -import org.jeecg.common.constant.CommonConstant; -import org.jeecg.config.mybatis.MybatisPlusSaasConfig; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; -import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.ParameterBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.schema.ModelRef; -import springfox.documentation.service.*; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; -import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @Author scott - */ -@Configuration -@EnableSwagger2WebMvc -@Import(BeanValidatorPluginsConfiguration.class) -public class Swagger2Config implements WebMvcConfigurer { - - /** - * - * 显示swagger-ui.html文档展示页,还必须注入swagger资源: - * - * @param registry - */ - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); - registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); - registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); - } - - /** - * swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等 - * - * @return Docket - */ - @Bean(value = "defaultApi2") - public Docket defaultApi2() { - return new Docket(DocumentationType.SWAGGER_2) - .apiInfo(apiInfo()) - .select() - //此包路径下的类,才生成接口文档 - .apis(RequestHandlerSelectors.basePackage("org.jeecg")) - //加了ApiOperation注解的类,才生成接口文档 - .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) - .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) - .paths(PathSelectors.any()) - .build() - .securitySchemes(Collections.singletonList(securityScheme())) - .securityContexts(securityContexts()) - .globalOperationParameters(setHeaderToken()); - } - - /*** - * oauth2配置 - * 需要增加swagger授权回调地址 - * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html - * @return - */ - @Bean - SecurityScheme securityScheme() { - return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header"); - } - /** - * JWT token - * @return - */ - private List setHeaderToken() { - ParameterBuilder tokenPar = new ParameterBuilder(); - List pars = new ArrayList<>(); - tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - pars.add(tokenPar.build()); - //update-begin-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id - if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){ - ParameterBuilder tenantPar = new ParameterBuilder(); - tenantPar.name(CommonConstant.TENANT_ID).description("租户ID").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - pars.add(tenantPar.build()); - } - //update-end-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id - - return pars; - } - - /** - * api文档的详细信息函数,注意这里的注解引用的是哪个 - * - * @return - */ - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - // //大标题 - .title("JeecgBoot 后台服务API接口文档") - // 版本号 - .version("1.0") -// .termsOfServiceUrl("NO terms of service") - // 描述 - .description("后台API接口") - // 作者 - .contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com")) - .license("The Apache License, Version 2.0") - .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html") - .build(); - } - - /** - * 新增 securityContexts 保持登录状态 - */ - private List securityContexts() { - return new ArrayList( - Collections.singleton(SecurityContext.builder() - .securityReferences(defaultAuth()) - .forPaths(PathSelectors.regex("^(?!auth).*$")) - .build()) - ); - } - - private List defaultAuth() { - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - return new ArrayList( - Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes))); - } - - /** - * 解决springboot2.6 和springfox不兼容问题 - * @return - */ - @Bean - public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { - return new BeanPostProcessor() { - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof WebMvcRequestHandlerProvider) { - customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); - } - return bean; - } - - private void customizeSpringfoxHandlerMappings(List mappings) { - List copy = mappings.stream() - .filter(mapping -> mapping.getPatternParser() == null) - .collect(Collectors.toList()); - mappings.clear(); - mappings.addAll(copy); - } - - @SuppressWarnings("unchecked") - private List getHandlerMappings(Object bean) { - try { - Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); - field.setAccessible(true); - return (List) field.get(bean); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - }; - } - - -} +//package org.jeecg.config; +// +// +//import io.swagger.annotations.ApiOperation; +//import org.jeecg.common.constant.CommonConstant; +//import org.jeecg.config.mybatis.MybatisPlusSaasConfig; +//import org.springframework.beans.BeansException; +//import org.springframework.beans.factory.config.BeanPostProcessor; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Import; +//import org.springframework.util.ReflectionUtils; +//import org.springframework.web.bind.annotation.RestController; +//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +//import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; +//import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; +//import springfox.documentation.builders.ApiInfoBuilder; +//import springfox.documentation.builders.ParameterBuilder; +//import springfox.documentation.builders.PathSelectors; +//import springfox.documentation.builders.RequestHandlerSelectors; +//import springfox.documentation.schema.ModelRef; +//import springfox.documentation.service.*; +//import springfox.documentation.spi.DocumentationType; +//import springfox.documentation.spi.service.contexts.SecurityContext; +//import springfox.documentation.spring.web.plugins.Docket; +//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; +//import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; +// +//import java.lang.reflect.Field; +//import java.util.ArrayList; +//import java.util.Collections; +//import java.util.List; +//import java.util.stream.Collectors; +// +///** +// * @Author scott +// */ +//@Configuration +//@EnableSwagger2WebMvc +//@Import(BeanValidatorPluginsConfiguration.class) +//public class Swagger2Config implements WebMvcConfigurer { +// +// /** +// * +// * 显示swagger-ui.html文档展示页,还必须注入swagger资源: +// * +// * @param registry +// */ +// @Override +// public void addResourceHandlers(ResourceHandlerRegistry registry) { +// registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); +// registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); +// registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); +// } +// +// /** +// * swagger2的配置文件,这里可以配置swagger2的一些基本的内容,比如扫描的包等等 +// * +// * @return Docket +// */ +// @Bean(value = "defaultApi2") +// public Docket defaultApi2() { +// return new Docket(DocumentationType.SWAGGER_2) +// .apiInfo(apiInfo()) +// .select() +// //此包路径下的类,才生成接口文档 +// .apis(RequestHandlerSelectors.basePackage("org.jeecg")) +// //加了ApiOperation注解的类,才生成接口文档 +// .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)) +// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) +// .paths(PathSelectors.any()) +// .build() +// .securitySchemes(Collections.singletonList(securityScheme())) +// .securityContexts(securityContexts()) +// .globalOperationParameters(setHeaderToken()); +// } +// +// /*** +// * oauth2配置 +// * 需要增加swagger授权回调地址 +// * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html +// * @return +// */ +// @Bean +// SecurityScheme securityScheme() { +// return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header"); +// } +// /** +// * JWT token +// * @return +// */ +// private List setHeaderToken() { +// ParameterBuilder tokenPar = new ParameterBuilder(); +// List pars = new ArrayList<>(); +// tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); +// pars.add(tokenPar.build()); +// //update-begin-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id +// if(MybatisPlusSaasConfig.OPEN_SYSTEM_TENANT_CONTROL){ +// ParameterBuilder tenantPar = new ParameterBuilder(); +// tenantPar.name(CommonConstant.TENANT_ID).description("租户ID").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); +// pars.add(tenantPar.build()); +// } +// //update-end-author:liusq---date:2024-08-15--for: 开启多租户时,全局参数增加租户id +// +// return pars; +// } +// +// /** +// * api文档的详细信息函数,注意这里的注解引用的是哪个 +// * +// * @return +// */ +// private ApiInfo apiInfo() { +// return new ApiInfoBuilder() +// // //大标题 +// .title("JeecgBoot 后台服务API接口文档") +// // 版本号 +// .version("1.0") +//// .termsOfServiceUrl("NO terms of service") +// // 描述 +// .description("后台API接口") +// // 作者 +// .contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com")) +// .license("The Apache License, Version 2.0") +// .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html") +// .build(); +// } +// +// /** +// * 新增 securityContexts 保持登录状态 +// */ +// private List securityContexts() { +// return new ArrayList( +// Collections.singleton(SecurityContext.builder() +// .securityReferences(defaultAuth()) +// .forPaths(PathSelectors.regex("^(?!auth).*$")) +// .build()) +// ); +// } +// +// private List defaultAuth() { +// AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); +// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; +// authorizationScopes[0] = authorizationScope; +// return new ArrayList( +// Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes))); +// } +// +// /** +// * 解决springboot2.6 和springfox不兼容问题 +// * @return +// */ +// @Bean +// public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { +// return new BeanPostProcessor() { +// +// @Override +// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { +// if (bean instanceof WebMvcRequestHandlerProvider) { +// customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); +// } +// return bean; +// } +// +// private void customizeSpringfoxHandlerMappings(List mappings) { +// List copy = mappings.stream() +// .filter(mapping -> mapping.getPatternParser() == null) +// .collect(Collectors.toList()); +// mappings.clear(); +// mappings.addAll(copy); +// } +// +// @SuppressWarnings("unchecked") +// private List getHandlerMappings(Object bean) { +// try { +// Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); +// field.setAccessible(true); +// return (List) field.get(bean); +// } catch (IllegalArgumentException | IllegalAccessException e) { +// throw new IllegalStateException(e); +// } +// } +// }; +// } +// +// +//} diff --git a/jeecg-module-custom/ocr.sql b/jeecg-module-custom/ocr.sql index 035cb39..fa382da 100644 --- a/jeecg-module-custom/ocr.sql +++ b/jeecg-module-custom/ocr.sql @@ -1,18 +1,108 @@ -CREATE TABLE form_config ( - id BIGINT NOT NULL PRIMARY KEY, - status VARCHAR(255), - message VARCHAR(255), - timestamp TIMESTAMP, - signature VARCHAR(255), - data LONGTEXT, - tenant_no BIGINT, - account_no BIGINT, - project_no BIGINT, - taskForm_no BIGINT, - field_list VARCHAR(255), - type INT, - field_code VARCHAR(255), - field_name VARCHAR(255), - parent_file_code VARCHAR(255), - level INT +CREATE TABLE ocr_form_config ( + id BIGINT NOT NULL PRIMARY KEY, + status VARCHAR(255), + message VARCHAR(255), + timestamp TIMESTAMP, + signature VARCHAR(255), + data LONGTEXT, + tenant_no BIGINT, + account_no BIGINT, + project_no BIGINT, + taskForm_no BIGINT, + field_list VARCHAR(255), + type INT, + field_code VARCHAR(255), + field_name VARCHAR(255), + parent_file_code VARCHAR(255), + level INT ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE ocr_picture ( + id BIGINT NOT NULL PRIMARY KEY, + task_id BIGINT, + image_no BIGINT, + image_url VARCHAR(255), + image_type VARCHAR(255), + image_status VARCHAR(10), + local_image_url VARCHAR(255), + max_similarity_score VARCHAR(255), + similarity_score VARCHAR(255) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE duplicate_task ( + id BIGINT NOT NULL PRIMARY KEY, + task_id BIGINT, + image_no BIGINT, + image_url VARCHAR(255), + image_type VARCHAR(255), + image_status VARCHAR(10), + local_image_url VARCHAR(255), + max_similarity_score VARCHAR(255), + similarity_score VARCHAR(255) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE task ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + tenant_code VARCHAR(50) COMMENT '租户编码', + access_key VARCHAR(100) COMMENT '访问密钥', + timestamp BIGINT COMMENT '时间戳', + signature VARCHAR(255) COMMENT '签名', + tenant_no BIGINT COMMENT '租户雪花no', + task_no BIGINT COMMENT '任务NO', + account_no BIGINT COMMENT '业务主体雪花no', + account_name VARCHAR(100) COMMENT '业务主体名称', + project_no BIGINT COMMENT '关联项目no', + project_name VARCHAR(100) COMMENT '项目名称', + task_form_no BIGINT COMMENT '任务表单no', + plan_no BIGINT COMMENT '所属主计划ID', + plan_name VARCHAR(100) COMMENT '所属主计划名称', + plan_child_no BIGINT COMMENT '所属子计划ID', + plan_child_name VARCHAR(100) COMMENT '所属子计划名称', + task_id BIGINT COMMENT '任务ID', + task_name VARCHAR(100) COMMENT '任务名称', + user_no BIGINT COMMENT '提报人no', + user_name VARCHAR(100) COMMENT '提报人名称', + submit_time BIGINT COMMENT '任务提交时间', + live_photo LONGTEXT COMMENT '拍照打卡', + dynamic_fields TEXT COMMENT '动态字段' +) COMMENT='任务表'; + +CREATE TABLE duplicate_task ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + tenant_code VARCHAR(255) NOT NULL COMMENT '租户代码', + access_key VARCHAR(255) NOT NULL COMMENT '访问标识', + timestamp BIGINT NOT NULL COMMENT '请求时间戳', + signature VARCHAR(255) NOT NULL COMMENT '签名', + account_no BIGINT COMMENT '业务主体', + tenant_no BIGINT COMMENT '租户', + request_id BIGINT COMMENT '请求批次ID', + task_nos TEXT COMMENT '任务nos', + query_config TEXT COMMENT '查询配置(JSON格式)', + max_similarity_score TEXT COMMENT '最大相似度', + completed TINYINT COMMENT '是否已经完成(0:否, 1:是)' +) COMMENT='重复任务表'; + +CREATE TABLE ocr_picture_compare ( + id BIGINT NOT NULL PRIMARY KEY, + task_no BIGINT, + image_no BIGINT, + image_url VARCHAR(255), + image_type VARCHAR(255), + image_status VARCHAR(10), + local_image_url VARCHAR(255), + max_similarity_score VARCHAR(255), + similarity_score VARCHAR(255) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE photos_compare ( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键', + first_img_no BIGINT NOT NULL COMMENT '图片NO', + first_img_url VARCHAR(255) COMMENT '图片地址', + first_local_img_url VARCHAR(255) COMMENT '本地图片地址', + first_img_hash VARCHAR(255) COMMENT '图片hash值', + second_img_no BIGINT NOT NULL COMMENT '图片NO', + second_img_url VARCHAR(255) COMMENT '图片地址', + second_local_img_url VARCHAR(255) COMMENT '本地图片地址', + second_img_hash VARCHAR(255) COMMENT '图片hash值', + similarity_score VARCHAR(50) COMMENT '相似度' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='图片对比表'; diff --git a/jeecg-module-custom/pom.xml b/jeecg-module-custom/pom.xml index 9a831aa..fb5f9be 100644 --- a/jeecg-module-custom/pom.xml +++ b/jeecg-module-custom/pom.xml @@ -13,17 +13,21 @@ jar + + + + + - org.jeecgframework.boot - jeecg-boot-base-core + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} - - io.springfox - springfox-boot-starter - 3.0.0 + io.swagger + swagger-annotations + 1.6.6 - com.alanpoi alanpoi-common @@ -35,6 +39,66 @@ thumbnailator 0.4.14 + + org.springframework.boot + spring-boot-starter-validation + + + cn.hutool + hutool-all + 5.8.12 + + + + commons-lang + commons-lang + ${commons.version} + + + com.google.guava + guava + 29.0-jre + + + org.apache.httpcomponents + httpclient + 4.5.12 + + + commons-codec + commons-codec + 1.15 + + + mysql + mysql-connector-java + 8.0.33 + + + com.alibaba + druid-spring-boot-starter + 1.2.8 + + + + ${project.artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + 3.4.4 + + + + repackage + + + + + + + diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/OcrApplication.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/OcrApplication.java new file mode 100644 index 0000000..085e692 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/OcrApplication.java @@ -0,0 +1,14 @@ +package org.jeecg.module.custom.ocr; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@MapperScan("org.jeecg.module.custom.ocr.dataDao") +@SpringBootApplication +public class OcrApplication { + + public static void main(String[] args) { + SpringApplication.run(OcrApplication.class, args); + } +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/entity/TaskCompletionRequest.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/entity/TaskCompletionRequest.java new file mode 100644 index 0000000..45abf46 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/entity/TaskCompletionRequest.java @@ -0,0 +1,134 @@ +package org.jeecg.module.custom.ocr.api.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +@Data +public class TaskCompletionRequest { + @JSONField(name = "status") + private Integer status; + + @JSONField(name = "message") + private String message; + + @JSONField(name = "timestamp") + private Long timestamp; + + @JSONField(name = "signature") + private String signature; + + @JSONField(name = "data") + private String data; + + @Data + public static class TaskCompletionData { + @JSONField(name = "tenantNo") + private Long tenantNo; + + @JSONField(name = "accountNo") + private Long accountNo; + + @JSONField(name = "taskNo") + private Long taskNo; + + @JSONField(name = "approveResult") + private Integer approveResult; + + @JSONField(name = "approveRemark") + private String approveRemark; + + @JSONField(name = "pictureMatchDegree") + private BigDecimal pictureMatchDegree; + + @JSONField(name = "extendField") + private String extendField; + + @JSONField(name = "isPictureRepeat") + private Integer isPictureRepeat; + + @JSONField(name = "isPictureRight") + private Integer isPictureRight; + + @JSONField(name = "isBriefRepeat") + private Integer isBriefRepeat; + + @JSONField(name = "pictureRepeatList") + private List pictureRepeatList; + + @JSONField(name = "hisPictureRepeatList") + private List hisPictureRepeatList; + + @JSONField(name = "falseImgList") + private List falseImgList; + + @JSONField(name = "briefRepeatTaskList") + private List briefRepeatTaskList; + + @JSONField(name = "approveDetailList") + private List approveDetailList; + } + + @Data + public static class PictureRepeat { + @JSONField(name = "imgNo") + private Long imgNo; + + @JSONField(name = "imgUrl") + private String imgUrl; + + @JSONField(name = "dynamicFields") + private Map dynamicFields; + } + + @Data + public static class HisPictureRepeat { + @JSONField(name = "hisTaskNo") + private Long hisTaskNo; + + @JSONField(name = "hisRepeatImgNo") + private Long hisRepeatImgNo; + + @JSONField(name = "hisRepeatImgUrl") + private String hisRepeatImgUrl; + } + + @Data + public static class ApproveDetail { + @JSONField(name = "nodeName") + private String nodeName; + + @JSONField(name = "approveByName") + private String approveByName; + + @JSONField(name = "approveWay") + private Integer approveWay; + + @JSONField(name = "approveResult") + private Integer approveResult; + + @JSONField(name = "reason") + private String reason; + + @JSONField(name = "processMethod") + private Integer processMethod; + + @JSONField(name = "approveRemark") + private String approveRemark; + + @JSONField(name = "extendField") + private String extendField; + + @JSONField(name = "isPictureRight") + private Integer isPictureRight; + + @JSONField(name = "isPictureRepeat") + private Integer isPictureRepeat; + + @JSONField(name = "isBriefRepeat") + private Integer isBriefRepeat; + } +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/impl/PrevailCloudApiImpl.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/impl/PrevailCloudApiImpl.java index cec0bb8..6d03c36 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/impl/PrevailCloudApiImpl.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/impl/PrevailCloudApiImpl.java @@ -35,7 +35,7 @@ import java.util.Map; * @version 1.0 * @date 2024/3/14 10:16 */ -@Service +@Service("ocrPrevailCloudApiImpl") public class PrevailCloudApiImpl implements PrevailCloudApi { private static Logger logger = LoggerFactory.getLogger(PrevailCloudApiImpl.class); @@ -47,7 +47,7 @@ public class PrevailCloudApiImpl implements PrevailCloudApi { private ApiConfig apiConfig; @Resource - private OcrPrevailCloudLogService prevailCloudLogService; + private OcrPrevailCloudLogService ocrPrevailCloudLogService; @Override @@ -112,7 +112,7 @@ public class PrevailCloudApiImpl implements PrevailCloudApi { } else { logger.error("请求图片接口数据失败,参数:{},返回值:{}", json, responseJsonStr); } - prevailCloudLogService.save(prevailCloudLog); + ocrPrevailCloudLogService.save(prevailCloudLog); return resultApiPage; } } diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/thread/DuplicateTaskRunner.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/thread/DuplicateTaskRunner.java new file mode 100644 index 0000000..bf28c13 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/api/thread/DuplicateTaskRunner.java @@ -0,0 +1,332 @@ +package org.jeecg.module.custom.ocr.api.thread; + +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.jeecg.module.custom.ocr.api.entity.TaskCompletionRequest; +import org.jeecg.module.custom.ocr.common.entity.RequestData; +import org.jeecg.module.custom.ocr.common.entity.ResultData; +import org.jeecg.module.custom.ocr.config.ApiConfig; +import org.jeecg.module.custom.ocr.dataDao.DuplicateTaskMapper; +import org.jeecg.module.custom.ocr.dataDao.PictureCompareMapper; +import org.jeecg.module.custom.ocr.dataobject.DuplicateTask; +import org.jeecg.module.custom.ocr.dataobject.OcrPicture; +import org.jeecg.module.custom.ocr.dataobject.PictureCompare; +import org.jeecg.module.custom.ocr.service.OcrPictureService; +import org.jeecg.module.custom.ocr.utils.ApiHelper; +import org.jeecg.module.custom.ocr.utils.ImageClassUtil; +import org.jeecg.module.custom.ocr.utils.httputil.HttpClient; +import org.jeecg.module.custom.ocr.utils.httputil.HttpMethod; +import org.jeecg.module.custom.ocr.utils.httputil.HttpParamers; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 重复任务运行器,负责处理未完成的 DuplicateTask + */ +@Slf4j +@Component +public class DuplicateTaskRunner { + + @Resource + private DuplicateTaskMapper duplicateTaskMapper; + + @Resource + private OcrPictureService ocrPictureService; + + @Resource + private PictureCompareMapper pictureCompareMapper; + + /** + * 注入api 配置信息 + */ + @Autowired + private ApiConfig apiConfig; + + private ScheduledExecutorService executor; + + @PostConstruct + public void init() { + startTask(); + } + + private void startTask() { + executor = Executors.newSingleThreadScheduledExecutor(); + executor.scheduleWithFixedDelay(this::processDuplicateTasks, 0, 10, TimeUnit.SECONDS); + } + + private void processDuplicateTasks() { + try { + // 查询所有未完成的 DuplicateTask + List tasks = duplicateTaskMapper.getAllUnCompletedTask(); + if (tasks != null && !tasks.isEmpty()) { + for (DuplicateTask task : tasks) { + // 解析 queryConfig 为 QueryWrapper + QueryWrapper queryWrapper = toQueryWrapper(task); + // 调用 OcrPictureService.listPage 查询图片 + List pictures = ocrPictureService.listPage(queryWrapper); + + // 如果图片数量大于 1,进行两两对比 + double maxSimilarity = 0.0; + if (pictures != null && pictures.size() > 1) { + for (int i = 0; i < pictures.size(); i++) { + for (int j = i + 1; j < pictures.size(); j++) { + OcrPicture first = pictures.get(i); + OcrPicture second = pictures.get(j); + + // 计算相似度 + String similarityScore = ImageClassUtil.getSimilarity(first.getImgurl(), second.getImgurl()); + double similarityValue = Double.parseDouble(similarityScore); + maxSimilarity = Math.max(maxSimilarity, similarityValue); + + // 保存对比结果到 PictureCompare + PictureCompare compare = new PictureCompare(); + compare.setFirstImgNo(first.getId()); + compare.setFirstImgUrl(first.getImgurl()); + compare.setFirstLocalImgUrl(first.getLocalpictrueurl()); + compare.setFirstImgHash(first.getImgHash()); + compare.setSecondImgNo(second.getId()); + compare.setSecondImgUrl(second.getImgurl()); + compare.setSecondLocalImgUrl(second.getLocalpictrueurl()); + compare.setSecondImgHash(second.getImgHash()); + compare.setSimilarityScore(similarityScore); + pictureCompareMapper.save(compare); + } + } + + // 更新 DuplicateTask 状态和最大相似度 + duplicateTaskMapper.updateCompletedAndMaxSimilarity(task.getId(), true, String.valueOf(maxSimilarity)); + } else { + // 更新 DuplicateTask 状态和最大相似度 + duplicateTaskMapper.updateCompletedAndMaxSimilarity(task.getId(), true, "0"); + } + + String[] taskNos = task.getTaskNos().split(","); + for (String taskNo : taskNos) { + notifyTaskCompletion(taskNo, task.getTenantNo(), task.getAccountNo(), maxSimilarity, pictures); + } + } + } + } catch (Exception e) { + // 捕获异常,避免线程中断 + System.err.println("Error processing duplicate tasks: " + e.getMessage()); + } catch (Throwable t) { + // 捕获致命错误,重新启动线程池 + System.err.println("Fatal error in task, restarting thread pool: " + t.getMessage()); + executor.shutdownNow(); + startTask(); // 创建新线程池并重启任务 + } + } + + private QueryWrapper toQueryWrapper(DuplicateTask task) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + + // 解析 queryConfig JSON + if (task.getQueryConfig() != null && !task.getQueryConfig().isEmpty()) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + Map queryMap = objectMapper.readValue(task.getQueryConfig(), Map.class); + + // 映射 OcrPicture 的数据库列名 + Map fieldToColumnMap = new HashMap<>(); + fieldToColumnMap.put("id", "ID"); + fieldToColumnMap.put("createBy", "create_by"); + fieldToColumnMap.put("createTime", "create_time"); + fieldToColumnMap.put("updateBy", "update_by"); + fieldToColumnMap.put("updateTime", "update_time"); + fieldToColumnMap.put("classificationid", "classificationid"); + fieldToColumnMap.put("pictureclassid", "pictureclassid"); + fieldToColumnMap.put("pictureclassscores", "pictureclassscores"); + fieldToColumnMap.put("iztrueorfalse", "iztrueorfalse"); + fieldToColumnMap.put("judgeid", "judgeid"); + fieldToColumnMap.put("judgedesc", "judgedesc"); + fieldToColumnMap.put("tenantId", "tenant_id"); + fieldToColumnMap.put("tenantstatus", "tenantstatus"); + fieldToColumnMap.put("plantcode", "plantCode"); + fieldToColumnMap.put("tenantname", "tenantname"); + fieldToColumnMap.put("pictureid", "pictureid"); + fieldToColumnMap.put("picturename", "picturename"); + fieldToColumnMap.put("imgname", "imgName"); + fieldToColumnMap.put("imgurl", "imgUrl"); + fieldToColumnMap.put("picturestatus", "picturestatus"); + fieldToColumnMap.put("projectid", "projectId"); + fieldToColumnMap.put("projectidname", "projectIdName"); + fieldToColumnMap.put("projectstatus", "projectstatus"); + fieldToColumnMap.put("planid", "planId"); + fieldToColumnMap.put("planname", "planName"); + fieldToColumnMap.put("planstatus", "planstatus"); + fieldToColumnMap.put("planchildid", "planchildid"); + fieldToColumnMap.put("planchildname", "planchildname"); + fieldToColumnMap.put("planchildstatus", "planchildstatus"); + fieldToColumnMap.put("uptime", "upTime"); + fieldToColumnMap.put("gentime", "genTime"); + fieldToColumnMap.put("space", "space"); + fieldToColumnMap.put("source", "source"); + fieldToColumnMap.put("uphead", "upHead"); + fieldToColumnMap.put("upuserid", "upuserid"); + fieldToColumnMap.put("upname", "upName"); + fieldToColumnMap.put("releasearea", "releaseArea"); + fieldToColumnMap.put("releaseprovince", "releaseProvince"); + fieldToColumnMap.put("remark", "remark"); + fieldToColumnMap.put("taskname", "taskName"); + fieldToColumnMap.put("taskstatus", "taskstatus"); + fieldToColumnMap.put("workStatus", "work_status"); + fieldToColumnMap.put("categoryid", "categoryid"); + fieldToColumnMap.put("taskchildpictureid", "taskchildpictureid"); + fieldToColumnMap.put("field1", "field1"); + fieldToColumnMap.put("field2", "field2"); + fieldToColumnMap.put("field3", "field3"); + fieldToColumnMap.put("field4", "field4"); + fieldToColumnMap.put("field5", "field5"); + fieldToColumnMap.put("field6", "field6"); + fieldToColumnMap.put("field7", "field7"); + fieldToColumnMap.put("field8", "field8"); + fieldToColumnMap.put("field9", "field9"); + fieldToColumnMap.put("field10", "field10"); + fieldToColumnMap.put("field11", "field11"); + fieldToColumnMap.put("field12", "field12"); + fieldToColumnMap.put("field13", "field13"); + fieldToColumnMap.put("field14", "field14"); + fieldToColumnMap.put("field15", "field15"); + fieldToColumnMap.put("field16", "field16"); + fieldToColumnMap.put("field17", "field17"); + fieldToColumnMap.put("field18", "field18"); + fieldToColumnMap.put("localpictrueurl", "local_pictrue_url"); + fieldToColumnMap.put("isdownload", "is_download"); + fieldToColumnMap.put("imgHash", "img_hash"); + fieldToColumnMap.put("similarityscore", "similarity_score"); + fieldToColumnMap.put("downloadErrorCount", "download_error_count"); + fieldToColumnMap.put("localThumbnailUrl", "local_thumbnail_url"); + fieldToColumnMap.put("serverThumbnailUrl", "server_thumbnail_url"); + fieldToColumnMap.put("submitDateTimestamp", "submit_date_timestamp"); + fieldToColumnMap.put("isRepeat", "is_repeat"); + fieldToColumnMap.put("suspiciousfile", "suspiciousfile"); + fieldToColumnMap.put("location", "location"); + fieldToColumnMap.put("comment", "comment"); + fieldToColumnMap.put("photoDateTimestamp", "photo_date_timestamp"); + fieldToColumnMap.put("completeSimilarGroupId", "complete_similar_group_id"); + fieldToColumnMap.put("history", "history"); + + // 动态添加查询条件 + for (Map.Entry entry : queryMap.entrySet()) { + String fieldName = entry.getKey(); + Object value = entry.getValue(); + String columnName = fieldToColumnMap.get(fieldName); + + if (columnName != null && value != null) { + queryWrapper.eq(columnName, value); + } + } + } catch (Exception e) { + throw new RuntimeException("Failed to parse queryConfig", e); + } + } + + // 添加 DuplicateTask 的其他字段作为查询条件 + if (task.getTenantNo() != null) { + queryWrapper.eq("tenant_id", task.getTenantNo()); + } + if (task.getAccountNo() != null) { + queryWrapper.eq("pictureid", task.getAccountNo()); // 假设 pictureid 对应 accountNo + } + if (task.getTaskNos() != null && !task.getTaskNos().isEmpty()) { + // 假设 taskNos 是逗号分隔的字符串,转换为 List + String[] taskNosArray = task.getTaskNos().split(","); + List taskNosList = Arrays.asList(taskNosArray).stream() + .map(Long::parseLong) + .collect(Collectors.toList()); + queryWrapper.in("remark", taskNosList); + } + + return queryWrapper; + } + + private void notifyTaskCompletion(String taskNo, Long tenantNo, Long accountNo, double maxSimilarity, List pictures) { + try { + // 构造任务完成数据 + TaskCompletionRequest.TaskCompletionData data = new TaskCompletionRequest.TaskCompletionData(); + data.setTenantNo(tenantNo); + data.setAccountNo(accountNo); + data.setTaskNo(Long.parseLong(taskNo)); + data.setApproveResult(0); // 假设默认通过 + data.setApproveRemark("Task completed successfully"); + data.setPictureMatchDegree(new BigDecimal(maxSimilarity)); + data.setExtendField(null); + data.setIsPictureRepeat(maxSimilarity > 90 ? 1 : 0); // 假设相似度 > 90% 表示重复 + data.setIsPictureRight(1); // 假设图片为真 + data.setIsBriefRepeat(0); // 假设无小结重复 + + // 构造 pictureRepeatList + List pictureRepeatList = pictures.stream() + .map(p -> { + TaskCompletionRequest.PictureRepeat repeat = new TaskCompletionRequest.PictureRepeat(); + repeat.setImgNo(p.getId()); + repeat.setImgUrl(p.getImgurl()); + repeat.setDynamicFields(new HashMap<>()); // 动态字段待补充 + return repeat; + }) + .collect(Collectors.toList()); + data.setPictureRepeatList(pictureRepeatList); + + // 其他列表暂设为空(需补充逻辑) + data.setHisPictureRepeatList(Arrays.asList()); + data.setFalseImgList(Arrays.asList()); + data.setBriefRepeatTaskList(Arrays.asList()); + data.setApproveDetailList(Arrays.asList()); + + // 序列化 data 为 JSON + String jsonData = JSONObject.toJSONString(data); + + // 加密请求参数 + RequestData requestData = ApiHelper.buildRequest( + tenantNo.toString(), + apiConfig.getAccessKey(), + apiConfig.getAccessCode(), + jsonData + ); + + // 组装请求 + // TODO: 需提供实际路径 + String url = apiConfig.getInterfaceDomain() + "/api/task/complete"; + String requestBodyJson = JSONObject.toJSONString(requestData); + HttpParamers httpParamers = new HttpParamers(HttpMethod.POST); + httpParamers.setJsonParamer(requestBodyJson); + + // 发起请求 + String responseJsonStr = HttpClient.doPost( + url, + httpParamers, + null, + apiConfig.getConnectTimeout(), + apiConfig.getReadTimeout() + ); + + // 解析响应 + ResultData resultData = JSONUtil.toBean(responseJsonStr, ResultData.class); + log.info("Task completion notification response: msg={}, status={}", resultData.getMessage(), resultData.getStatus()); + + // 处理响应 + if (resultData.getStatus() == 100) { + log.info("Task {} completion notified successfully", taskNo); + } else { + log.error("Failed to notify task completion, taskNo={}, response={}", taskNo, responseJsonStr); + } + } catch (Exception e) { + log.error("Error notifying task completion, taskNo={}", taskNo, e); + } + } +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/common/vo/FlowModelVO.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/common/vo/FlowModelVO.java index 7af8737..29ffab5 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/common/vo/FlowModelVO.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/common/vo/FlowModelVO.java @@ -3,7 +3,7 @@ package org.jeecg.module.custom.ocr.common.vo; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.jeecg.module.custom.ocr.common.dto.HistoricTaskInstanceDto; @@ -15,45 +15,45 @@ import java.util.Map; public class FlowModelVO { // 任务编号 private String taskId; - @Schema(description = "业务表流水号") + @ApiModelProperty(value = "业务表流水号") @JsonSerialize(using = ToStringSerializer.class) private Long formid; - @Schema(description = "受理人主键") + @ApiModelProperty(value = "受理人主键") @JsonSerialize(using = ToStringSerializer.class) private Long userid; - @Schema(description = "受理人姓名") + @ApiModelProperty(value = "受理人姓名") private String username; - @Schema(description = "是否归档,0:未归档,1:归档") + @ApiModelProperty(value = "是否归档,0:未归档,1:归档") private Integer guidang; - @Schema(description = "附件") + @ApiModelProperty(value = "附件") private String fileannex; - @Schema(description = "流程类型") + @ApiModelProperty(value = "流程类型") @JsonSerialize(using = ToStringSerializer.class) private Long categoryid; - @Schema(description = "状态,审批状态 1:未提交 2:审批中 3:审批通过 ") + @ApiModelProperty(value = "状态,审批状态 1:未提交 2:审批中 3:审批通过 ") private Integer states; - @Schema(description = "流程定义id") + @ApiModelProperty(value = "流程定义id") private String processdefinitionid; - @Schema(description = "流程部署id") + @ApiModelProperty(value = "流程部署id") private String deploymentid; - @Schema(description = "审批人姓名") + @ApiModelProperty(value = "审批人姓名") private String assigneename; - @Schema(description = "审批人") + @ApiModelProperty(value = "审批人") private String assignee; - @Schema(description = "创建人,记录创建人的帐号") + @ApiModelProperty(value = "创建人,记录创建人的帐号") private String createuser; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - @Schema(description = "创建时间") + @ApiModelProperty(value = "创建时间") private Long createdate; - @Schema(description = "创建人姓名") + @ApiModelProperty(value = "创建人姓名") private String createusername; //临时存放部门主键,用于审批部门,查询对应的审批人使用,当前审批主键与提交人所在部门无关,所以单独存放 diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/PrevailCloudApiController.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/PrevailCloudApiController.java index c3facbb..263fc0e 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/PrevailCloudApiController.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/PrevailCloudApiController.java @@ -9,11 +9,15 @@ import org.jeecg.module.custom.ocr.api.PrevailCloudApi; import org.jeecg.module.custom.ocr.api.entity.PictureSourceAllPullMsg; import org.jeecg.module.custom.ocr.api.thread.PullAllPictureSourceThread; import org.jeecg.module.custom.ocr.config.ApiConfig; +import org.jeecg.module.custom.ocr.controller.dto.AddTaskRequest; +import org.jeecg.module.custom.ocr.controller.dto.DeleteTaskRequest; +import org.jeecg.module.custom.ocr.controller.dto.DuplicateTaskRequest; +import org.jeecg.module.custom.ocr.service.DuplicateTaskService; +import org.jeecg.module.custom.ocr.service.TaskService; import org.jeecg.module.custom.ocr.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; @@ -23,7 +27,7 @@ import java.util.concurrent.*; @Api(tags = "ocr_无量云拉取") @Slf4j @RestController -@RequestMapping("/test/api") +@RequestMapping("/api/prevailCloud") public class PrevailCloudApiController { @Resource @@ -32,6 +36,12 @@ public class PrevailCloudApiController { @Autowired private PrevailCloudApi prevailCloudApi; + @Autowired + private TaskService taskService; + + @Autowired + private DuplicateTaskService duplicateTaskService; + /** * 用于执行全量拉取的定长线程池 */ @@ -97,4 +107,40 @@ public class PrevailCloudApiController { ); return "执行开始"; } + + /** + * 添加任务 + * + * @param request + * @return + */ + @ApiOperation(value = "添加任务", notes = "添加任务") + @PostMapping("/addTask") + public void addTask(@RequestBody AddTaskRequest request) { + taskService.save(request); + } + + /** + * 删除任务 + * + * @param request + * @return + */ + @ApiOperation(value = "删除任务", notes = "删除任务") + @PostMapping("/deleteTask") + public void deleteTask(@RequestBody @Validated DeleteTaskRequest request) { + taskService.deleteTask(request.getTaskNo()); + } + + /** + * 查重 + * + * @param request + * @return + */ + @ApiOperation(value = "查重", notes = "查重") + @PostMapping("/checkDuplicate") + public void checkDuplicate(@RequestBody @Validated DuplicateTaskRequest request) { + duplicateTaskService.save(request); + } } diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskData.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskData.java new file mode 100644 index 0000000..020865e --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskData.java @@ -0,0 +1,11 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class AddTaskData { + + private List records; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskRequest.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskRequest.java new file mode 100644 index 0000000..8415370 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/AddTaskRequest.java @@ -0,0 +1,17 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; + +@Data +public class AddTaskRequest { + + private String tenantCode; + + private String accessKey; + + private Long timestamp; + + private String signature; + + private AddTaskData data; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DeleteTaskRequest.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DeleteTaskRequest.java new file mode 100644 index 0000000..34e3b60 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DeleteTaskRequest.java @@ -0,0 +1,15 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class DeleteTaskRequest { + + /** + * 任务NO + */ + @NotNull + private Long taskNo; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskData.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskData.java new file mode 100644 index 0000000..ee3b762 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskData.java @@ -0,0 +1,34 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; + +import java.util.List; + +@Data +public class DuplicateTaskData { + + /** + * 业务主体,选填 + */ + private Long accountNo; + + /** + * 租户,选填 + */ + private Long tenantNo; + + /** + * 请求批次ID,选填 + */ + private Long requestId; + + /** + * 任务nos,选填 + */ + private List taskNos; + + /** + * 查询配置(JSON格式),选填 + */ + private String queryConfig; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskRequest.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskRequest.java new file mode 100644 index 0000000..80c71f9 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/DuplicateTaskRequest.java @@ -0,0 +1,31 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; + +@Data +public class DuplicateTaskRequest { + /** + * 租户代码,必填 + */ + private String tenantCode; + + /** + * 访问标识,必填 + */ + private String accessKey; + + /** + * 请求时间戳,必填 + */ + private Long timestamp; + + /** + * 签名,必填 + */ + private String signature; + + /** + * 加密的请求数据,必填 + */ + private DuplicateTaskData data; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/TaskDTO.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/TaskDTO.java new file mode 100644 index 0000000..76d0a10 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/controller/dto/TaskDTO.java @@ -0,0 +1,98 @@ +package org.jeecg.module.custom.ocr.controller.dto; + +import lombok.Data; +import org.jeecg.module.custom.ocr.api.entity.LivePhoto; + +import java.util.Map; + +@Data +public class TaskDTO { + + /** + * 租户雪花no + */ + private Long tenantNo; + + /** + * 任务NO + */ + private Long taskNo; + + /** + * 业务主体雪花no + */ + private Long accountNo; + + /** + * 业务主体名称 + */ + private String accountName; + + /** + * 关联项目no + */ + private Long projectNo; + + /** + * 项目名称 + */ + private String projectName; + + /** + * 任务表单no + */ + private Long taskFormNo; + + /** + * 所属主计划ID + */ + private Long planNo; + + /** + * 所属主计划名称 + */ + private String planName; + + /** + * 所属子计划ID + */ + private Long planChildNo; + + /** + * 所属子计划名称 + */ + private String planChildName; + + /** + * 任务ID + */ + private Long taskId; + + /** + * 任务名称 + */ + private String taskName; + + /** + * 提报人no + */ + private Long userNo; + + /** + * 提报人名称 + */ + private String userName; + + /** + * 任务提交时间 + */ + private Long submitTime; + + /** + * 拍照打卡 + */ + private LivePhoto livePhoto; + + // 使用 Map 捕获动态字段 + private Map dynamicFields; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/DuplicateTaskMapper.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/DuplicateTaskMapper.java new file mode 100644 index 0000000..5abd832 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/DuplicateTaskMapper.java @@ -0,0 +1,16 @@ +package org.jeecg.module.custom.ocr.dataDao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.module.custom.ocr.dataobject.DuplicateTask; + +import java.util.List; + +public interface DuplicateTaskMapper extends BaseMapper { + void save(DuplicateTask task); + + List getAllUnCompletedTask(); + + void updateCompletedById(Long id); + + void updateCompletedAndMaxSimilarity(Long id, boolean completed, String maxSimilarityScore); +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/PictureCompareMapper.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/PictureCompareMapper.java new file mode 100644 index 0000000..ecadd45 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/PictureCompareMapper.java @@ -0,0 +1,8 @@ +package org.jeecg.module.custom.ocr.dataDao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.module.custom.ocr.dataobject.PictureCompare; + +public interface PictureCompareMapper extends BaseMapper { + void save(PictureCompare compare); +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/TaskMapper.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/TaskMapper.java new file mode 100644 index 0000000..411c7c5 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataDao/TaskMapper.java @@ -0,0 +1,10 @@ +package org.jeecg.module.custom.ocr.dataDao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.jeecg.module.custom.ocr.dataobject.Task; + +public interface TaskMapper extends BaseMapper { + void save(Task task); + + void deleteByTaskNo(Long taskNo); +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Category.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Category.java index 9cdeefb..b467992 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Category.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Category.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -21,82 +21,84 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +/** + * 流程类型 + */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "流程类型", title = "流程类型") @TableName(value = "OA_CATEGORY_T") public class Category implements BaseDto,java.io.Serializable { private static final long serialVersionUID = 3650775877135330041L; - @Schema(description = "流水号") + @ApiModelProperty(value = "流水号") @TableId(value = "id",type = IdType.ASSIGN_ID) @JsonSerialize(using = ToStringSerializer.class) @TableField(value="ID") private Long id; - @Schema(description = "项目名称") + @ApiModelProperty(value = "项目名称") @TableField(value="CATEGORYNAME") private String categoryname; - @Schema(description = "项目编码") + @ApiModelProperty(value = "项目编码") @TableField(value="CATEGORY") private String category; - @Schema(description = "对应的Service名,主要是spring的service名") + @ApiModelProperty(value = "对应的Service名,主要是spring的service名") @TableField(value="SERVICENAME") private String servicename; - @Schema(description = "内置表单,使用flowable表单,0:使用本地数据,1:使用flowable表单,3:外置表单,4:其他自定义表单") + @ApiModelProperty(value = "内置表单,使用flowable表单,0:使用本地数据,1:使用flowable表单,3:外置表单,4:其他自定义表单") @TableField(value="BUILTFORM") private Integer builtform; - @Schema(description = "表单地址,用户展示用户表单使用") + @ApiModelProperty(value = "表单地址,用户展示用户表单使用") @TableField(value="FORMURL") private String formurl; - @Schema(description = "表单详情") + @ApiModelProperty(value = "表单详情") @TableField(value="FORMDETAIL") private String formdetail; - @Schema(description = "是否启用,0:禁用,1:启用") + @ApiModelProperty(value = "是否启用,0:禁用,1:启用") @TableField(value="HAVEUSE") private Integer haveuse; - @Schema(description = "表单分类") + @ApiModelProperty(value = "表单分类") @TableField(value="FORMTYPE") private String formtype; - @Schema(description = "流程定义id") + @ApiModelProperty(value = "流程定义id") @TableField(value="PROCESSDEFINITIONID") private String processdefinitionid; - @Schema(description = "排序") + @ApiModelProperty(value = "排序") @TableField(value="FORMNO") private Integer formno; - @Schema(description = "创建人,记录创建人的帐号") + @ApiModelProperty(value = "创建人,记录创建人的帐号") @TableField(value="CREATEUSER") private String createuser; - @Schema(description = "创建时间") + @ApiModelProperty(value = "创建时间") @TableField(value="CREATEDATE") private Long createdate; - @Schema(description = "修改人,记录创建人的帐号") + @ApiModelProperty(value = "修改人,记录创建人的帐号") @TableField(value="UPDATEUSER") private String updateuser; - @Schema(description = "更新时间") + @ApiModelProperty(value = "更新时间") @TableField(value="UPDATETIME") private Long updatetime; - @Schema(description = "隶属机构") + @ApiModelProperty(value = "隶属机构") @TableField(value="DEPTID") private Long deptid; - @Schema(description = "租户主键") + @ApiModelProperty(value = "租户主键") @TableField(value="TENANTID") private String tenantid; @@ -105,7 +107,7 @@ public class Category implements BaseDto,java.io.Serializable { private Tenant tenant; //业务表主键 - @Schema(description = "业务表主键") + @ApiModelProperty(value = "业务表主键") @TableField(exist = false) private String formid; @@ -113,7 +115,7 @@ public class Category implements BaseDto,java.io.Serializable { @TableField(exist = false) String documentation; - @Schema(description = "状态,审批状态 1:未提交 2:审批中 3:审批通过 ") + @ApiModelProperty(value = "状态,审批状态 1:未提交 2:审批中 3:审批通过 ") @TableField(exist = false) private Integer states; diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/DuplicateTask.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/DuplicateTask.java new file mode 100644 index 0000000..c682df1 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/DuplicateTask.java @@ -0,0 +1,64 @@ +package org.jeecg.module.custom.ocr.dataobject; + +import lombok.Data; + +@Data +public class DuplicateTask { + + private Long id; + + /** + * 租户代码,必填 + */ + private String tenantCode; + + /** + * 访问标识,必填 + */ + private String accessKey; + + /** + * 请求时间戳,必填 + */ + private Long timestamp; + + /** + * 签名,必填 + */ + private String signature; + + /** + * 业务主体,选填 + */ + private Long accountNo; + + /** + * 租户,选填 + */ + private Long tenantNo; + + /** + * 请求批次ID,选填 + */ + private Long requestId; + + /** + * 任务nos,选填 + */ + private String taskNos; + + /** + * 查询配置(JSON格式),选填 + */ + private String queryConfig; + + /** + * 最大相似度 + */ + private String maxSimilarityScore; + + /** + * 是否已经完成 + */ + private Boolean completed; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/FormConfig.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/FormConfig.java index 29f4a58..cd3a7cf 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/FormConfig.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/FormConfig.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -17,11 +16,13 @@ import lombok.NoArgsConstructor; import java.io.Serializable; +/** + * 表单字段配置信息表 + */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "表单字段配置信息表", title = "表单字段配置信息表") @ApiModel(value = "表单字段配置信息表", description = "表单字段配置信息表") @TableName(value = "form_config") public class FormConfig implements Serializable { diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrCheckDuplicateResult.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrCheckDuplicateResult.java index ec54215..25e4022 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrCheckDuplicateResult.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrCheckDuplicateResult.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -16,14 +15,6 @@ import lombok.NoArgsConstructor; import java.io.Serializable; -/** - *

- * - *

- * - * @author author - * @since 2024-03-24 - */ @Data @Builder @NoArgsConstructor @@ -34,7 +25,7 @@ public class OcrCheckDuplicateResult implements Serializable { private static final long serialVersionUID = 1L; - @Schema(description = "主键") + @ApiModelProperty(value = "主键") @TableId(value = "id",type = IdType.ASSIGN_ID) @JsonSerialize(using = ToStringSerializer.class) @TableField(value="ID") diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionary.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionary.java index 3918567..09dcd47 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionary.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionary.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -22,18 +21,10 @@ import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; -/** - * TODO - * - * @author hugh(shuli.yao) 1397940314@qq.com - * @version 1.0 - * @date 2024/3/16 12:40 - */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "业务数据字典值表", title = "业务数据字典值表") @ApiModel(value="业务数据字典值表", description="业务数据字典值表") @TableName(value = "ocr_dictionary") public class OcrDictionary implements BaseDto,java.io.Serializable{ diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionaryGroup.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionaryGroup.java index aee65ad..0de2253 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionaryGroup.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrDictionaryGroup.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -24,17 +23,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * TODO - * - * @author hugh(shuli.yao) 1397940314@qq.com - * @version 1.0 - * @date 2024/3/16 12:40 + * 业务数据字典组表 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "业务数据字典组表", title = "业务数据字典组表") @ApiModel(value="业务数据字典组表", description="业务数据字典组表") @TableName(value = "ocr_dictionary_group") public class OcrDictionaryGroup implements BaseDto,java.io.Serializable { diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPicture.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPicture.java index 2448a06..d938eed 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPicture.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPicture.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -19,20 +18,17 @@ import org.jeecg.module.custom.ocr.common.dto.BaseDto; import org.jeecg.module.custom.ocr.jsonDomain.DateNotimeSerializer; import org.jeecg.module.custom.ocr.utils.requestFormat.SearchQuery; -import java.util.AbstractMap.SimpleEntry; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - +/** + * 图片信息表 + */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "图片信息表", title = "图片信息表") @ApiModel(value = "图片信息表", description = "图片信息表") -@TableName(value = "ocr_picture") +@TableName(value = "ocr_task") public class OcrPicture implements BaseDto, java.io.Serializable { private static final long serialVersionUID = -10378331243377607L; @@ -68,7 +64,7 @@ public class OcrPicture implements BaseDto, java.io.Serializable { @TableField(value = "pictureclassid") private String pictureclassid; - @Schema(description = "图片类型相似度,图片类型--通过“AI图片分类接口获得”") + @ApiModelProperty(value = "图片类型相似度,图片类型--通过“AI图片分类接口获得”") @TableField(value = "pictureclassscores") private String pictureclassscores; @@ -284,30 +280,27 @@ public class OcrPicture implements BaseDto, java.io.Serializable { @TableField(value = "field16") private String field16; - - @Schema(description = "拜访项目类别") + @ApiModelProperty(value = "拜访项目类别") @TableField(value = "field17") private String field17; - @Schema(description = "备用字段") + @ApiModelProperty(value = "备用字段") @TableField(value = "field18") private String field18; - @Schema(description = "本地图片地址") + @ApiModelProperty(value = "本地图片地址") @TableField(value = "local_pictrue_url") private String localpictrueurl; - @Schema(description = "是否已下载到本地") + @ApiModelProperty(value = "是否已下载到本地") @TableField(value = "is_download") private Integer isdownload; @ApiModelProperty(value = "图片hash值") - @Schema(description = "图片hash值") @TableField(value = "img_hash") private String imgHash; @ApiModelProperty(value = "相似度数值") - @Schema(description = "相似度数值") @TableField(value = "similarity_score") private Integer similarityscore; @@ -333,12 +326,10 @@ public class OcrPicture implements BaseDto, java.io.Serializable { private String result; @ApiModelProperty(value = "缩略图服务器绝对路径") - @Schema(description = "缩略图服务器绝对路径") @TableField(value = "local_thumbnail_url") private String localThumbnailUrl; @ApiModelProperty(value = "缩略图请求地址") - @Schema(description = "缩略图请求地址") @TableField(value = "server_thumbnail_url") private String serverThumbnailUrl; @@ -350,22 +341,19 @@ public class OcrPicture implements BaseDto, java.io.Serializable { @TableField(value = "is_repeat") private Integer isRepeat; - @ApiModelProperty(value = "任务状态") @TableField(exist = false) private Integer states; + @ApiModelProperty(value = "可疑文件夹 0:不在,1:在") - @Schema(description = "可疑文件夹 0:不在,1:在") @TableField(value = "suspiciousfile") private Integer suspiciousfile; @ApiModelProperty(value = "定位") - @Schema(description = "定位") @TableField(value = "location") private String location; @ApiModelProperty(value = "备注") - @Schema(description = "备注") @TableField(value = "comment") private String comment; @@ -379,7 +367,6 @@ public class OcrPicture implements BaseDto, java.io.Serializable { private Long completeSimilarGroupId; @ApiModelProperty(value = "是否为历史图") - @Schema(description = "是否为历史图") @TableField(value = "history") private Boolean history; @@ -411,85 +398,8 @@ public class OcrPicture implements BaseDto, java.io.Serializable { @TableField(exist = false) private OcrPictureInfo pictureInfo; - @TableField(exist = false) - @JsonIgnore - private final Map query = Stream.of( - new SimpleEntry<>("ID", "id"), - new SimpleEntry<>("create_by", "createBy"), - new SimpleEntry<>("create_time", "createTime"), - new SimpleEntry<>("update_by", "updateBy"), - new SimpleEntry<>("update_time", "updateTime"), - new SimpleEntry<>("classificationid", "classificationid"), - new SimpleEntry<>("pictureclassid", "pictureclassid"), - new SimpleEntry<>("pictureclassscores", "pictureclassscores"), - new SimpleEntry<>("iztrueorfalse", "iztrueorfalse"), - new SimpleEntry<>("judgeid", "judgeid"), - new SimpleEntry<>("judgedesc", "judgedesc"), - new SimpleEntry<>("tenant_id", "tenantId"), - new SimpleEntry<>("tenantstatus", "tenantstatus"), - new SimpleEntry<>("plantCode", "plantcode"), - new SimpleEntry<>("tenantname", "tenantname"), - new SimpleEntry<>("pictureid", "pictureid"), - new SimpleEntry<>("picturename", "picturename"), - new SimpleEntry<>("imgName", "imgname"), - new SimpleEntry<>("imgUrl", "imgurl"), - new SimpleEntry<>("picturestatus", "picturestatus"), - new SimpleEntry<>("projectId", "projectid"), - new SimpleEntry<>("projectIdName", "projectidname"), - new SimpleEntry<>("projectstatus", "projectstatus"), - new SimpleEntry<>("planId", "planid"), - new SimpleEntry<>("planName", "planname"), - new SimpleEntry<>("planstatus", "planstatus"), - new SimpleEntry<>("planchildid", "planchildid"), - new SimpleEntry<>("planchildname", "planchildname"), - new SimpleEntry<>("planchildstatus", "planchildstatus"), - new SimpleEntry<>("upTime", "uptime"), - new SimpleEntry<>("genTime", "gentime"), - new SimpleEntry<>("space", "space"), - new SimpleEntry<>("source", "source"), - new SimpleEntry<>("upHead", "uphead"), - new SimpleEntry<>("upuserid", "upuserid"), - new SimpleEntry<>("upName", "upname"), - new SimpleEntry<>("releaseArea", "releasearea"), - new SimpleEntry<>("releaseProvince", "releaseprovince"), - new SimpleEntry<>("remark", "remark"), - new SimpleEntry<>("taskName", "taskname"), - new SimpleEntry<>("taskstatus", "taskstatus"), - new SimpleEntry<>("work_status", "workStatus"), - new SimpleEntry<>("categoryid", "categoryid"), - new SimpleEntry<>("taskchildpictureid", "taskchildpictureid"), - new SimpleEntry<>("field1", "field1"), - new SimpleEntry<>("field2", "field2"), - new SimpleEntry<>("field3", "field3"), - new SimpleEntry<>("field4", "field4"), - new SimpleEntry<>("field5", "field5"), - new SimpleEntry<>("field6", "field6"), - new SimpleEntry<>("field7", "field7"), - new SimpleEntry<>("field8", "field8"), - new SimpleEntry<>("field9", "field9"), - new SimpleEntry<>("field10", "field10"), - new SimpleEntry<>("field11", "field11"), - new SimpleEntry<>("field12", "field12"), - new SimpleEntry<>("field13", "field13"), - new SimpleEntry<>("field14", "field14"), - new SimpleEntry<>("field15", "field15"), - new SimpleEntry<>("field16", "field16"), - new SimpleEntry<>("field17", "field17"), - new SimpleEntry<>("field18", "field18"), - new SimpleEntry<>("localpictrueurl", "localpictrueurl"), - new SimpleEntry<>("imgHash", "imgHash"), - new SimpleEntry<>("serverThumbnailUrl", "serverThumbnailUrl"), - new SimpleEntry<>("localThumbnailUrl", "localThumbnailUrl"), - new SimpleEntry<>("suspiciousfile", "suspiciousfile") - ) - .collect(Collectors.toMap(SimpleEntry::getKey, SimpleEntry::getValue)); - @Override public String getQueryFiled(String filedname) { - String obj = null; - if (null != query && query.size() > 0) { - obj = query.get(filedname); - } - return obj; + return ""; } } diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPictureDuplicateHis.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPictureDuplicateHis.java index a5a9782..407e114 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPictureDuplicateHis.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrPictureDuplicateHis.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -34,7 +33,7 @@ public class OcrPictureDuplicateHis implements Serializable { private static final long serialVersionUID = 1L; - @Schema(description = "主键") + @ApiModelProperty(value = "主键") @TableId(value = "id",type = IdType.ASSIGN_ID) @JsonSerialize(using = ToStringSerializer.class) @TableField(value="id") diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrTaskchildPicture.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrTaskchildPicture.java index d1a1e5b..82cfef8 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrTaskchildPicture.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/OcrTaskchildPicture.java @@ -9,7 +9,6 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -186,31 +185,31 @@ public class OcrTaskchildPicture implements BaseDto, java.io.Serializable { @TableField(value = "HAVEPOINTS") private Integer havepoints; - @Schema(description = "当前节点名称") + @ApiModelProperty(value = "当前节点名称") @TableField(value = "TASKNAME") private String taskname; - @Schema(description = "当前节点名称") + @ApiModelProperty(value = "当前节点名称") @TableField(value = "TASKNODE") private String taskNode; - @Schema(description = "当前节点id") + @ApiModelProperty(value = "当前节点id") @TableField(value = "TASKID") private String taskId; - @Schema(description = "完成时间") + @ApiModelProperty(value = "完成时间") @TableField(value = "FINISHTIME") private Long finishtime; - @Schema(description = "是否终审") + @ApiModelProperty(value = "是否终审") @TableField(value = "ISFINAIL") private Integer isFinal; - @Schema(description = "是否小结重复,1重复,0不重复") + @ApiModelProperty(value = "是否小结重复,1重复,0不重复") @TableField(value = "is_repeated_nodules") private Integer isRepeatedNodules; - @Schema(description = "无量云回调结果") + @ApiModelProperty(value = "无量云回调结果") @TableField(value = "send_result") private Integer sendResult; @@ -268,7 +267,7 @@ public class OcrTaskchildPicture implements BaseDto, java.io.Serializable { @TableField(exist = false) private String field14; - @Schema(description = "是否图片重复") + @ApiModelProperty(value = "是否图片重复") @TableField(exist = false) private Integer isRepeat; diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/PictureCompare.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/PictureCompare.java new file mode 100644 index 0000000..9a43896 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/PictureCompare.java @@ -0,0 +1,54 @@ +package org.jeecg.module.custom.ocr.dataobject; + +import lombok.Data; + +@Data +public class PictureCompare { + + private Long id; + + /** + * 图片NO + */ + private Long firstImgNo; + + /** + * 图片地址 + */ + private String firstImgUrl; + + /** + * 本地图片地址 + */ + private String firstLocalImgUrl; + + /** + * 图片hash值 + */ + private String firstImgHash; + + /** + * 图片NO + */ + private Long secondImgNo; + + /** + * 图片地址 + */ + private String secondImgUrl; + + /** + * 本地图片地址 + */ + private String secondLocalImgUrl; + + /** + * 图片hash值 + */ + private String secondImgHash; + + /** + * 相似度 + */ + private String similarityScore; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Task.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Task.java new file mode 100644 index 0000000..d3b8d0d --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Task.java @@ -0,0 +1,105 @@ +package org.jeecg.module.custom.ocr.dataobject; + +import lombok.Data; + +@Data +public class Task { + + private Long id; + + private String tenantCode; + + private String accessKey; + + private Long timestamp; + + private String signature; + + /** + * 租户雪花no + */ + private Long tenantNo; + + /** + * 任务NO + */ + private Long taskNo; + + /** + * 业务主体雪花no + */ + private Long accountNo; + + /** + * 业务主体名称 + */ + private String accountName; + + /** + * 关联项目no + */ + private Long projectNo; + + /** + * 项目名称 + */ + private String projectName; + + /** + * 任务表单no + */ + private Long taskFormNo; + + /** + * 所属主计划ID + */ + private Long planNo; + + /** + * 所属主计划名称 + */ + private String planName; + + /** + * 所属子计划ID + */ + private Long planChildNo; + + /** + * 所属子计划名称 + */ + private String planChildName; + + /** + * 任务ID + */ + private Long taskId; + + /** + * 任务名称 + */ + private String taskName; + + /** + * 提报人no + */ + private Long userNo; + + /** + * 提报人名称 + */ + private String userName; + + /** + * 任务提交时间 + */ + private Long submitTime; + + /** + * 拍照打卡 + */ + private String livePhoto; + + // 使用 Map 捕获动态字段 + private String dynamicFields; +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Tenant.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Tenant.java index 1f63281..2c4f1cf 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Tenant.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Tenant.java @@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -20,91 +19,131 @@ import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; - +/** + * 多租户管理 + */ @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "多租户管理", title = "多租户管理") @TableName(value = "S_TENANT_T") public class Tenant implements BaseDto,java.io.Serializable { private static final long serialVersionUID = -421629635552978382L; - @Schema(description = "流水号") + + /** + * 流水号 + */ @TableId(value = "id",type = IdType.ASSIGN_ID) @JsonSerialize(using = ToStringSerializer.class) @TableField(value="ID") private Long id; - @Schema(description = "租户名称") + /** + * 租户名称 + */ @TableField(value="NAME") private String name; - @Schema(description = "开始时间") + /** + * 开始时间 + */ @TableField(value="STARTDATE") private Long startdate; - @Schema(description = "结束时间") + /** + * 结束时间 + */ @TableField(value="ENDDATE") private Long enddate; - @Schema(description = "状态 1正常 0冻结") + /** + * 状态 1正常 0冻结 + */ @TableField(value="STATUS") private Integer status; - @Schema(description = "所属行业") + /** + * 所属行业 + */ @TableField(value="TRADE") private String trade; - @Schema(description = "公司规模") + /** + * 公司规模 + */ @TableField(value="COMPANYSIZE") private String companysize; - @Schema(description = "公司地址") + /** + * 公司地址 + */ @TableField(value="COMPANYADDRESS") private String companyaddress; - @Schema(description = "公司LOGO") + /** + * 公司LOGO + */ @TableField(value="COMPANYLOGO") private String companylogo; - @Schema(description = "门牌号") + /** + * 门牌号 + */ @TableField(value="COMPANTNO") private String compantno; - @Schema(description = "工作地点") + /** + * 工作地点 + */ @TableField(value="COMPANYPLACE") private String companyplace; - @Schema(description = "域名") + /** + * 域名 + */ @TableField(value="DOMAIN") private String domain; - @Schema(description = "登录背景图片") + /** + * 登录背景图片 + */ @TableField(value="BACKIMG") private String backimg; - @Schema(description = "允许申请管理员 1允许 0不允许") + /** + * 允许申请管理员 1允许 0不允许 + */ @TableField(value="APPLYADMIN") private Integer applyadmin; - @Schema(description = "创建人,记录创建人的帐号") + /** + * 创建人,记录创建人的帐号 + */ @TableField(value="CREATEUSER") private String createuser; - @Schema(description = "创建时间") + /** + * 创建时间 + */ @TableField(value="CREATEDATE") private Long createdate; - @Schema(description = "修改人,记录创建人的帐号") + /** + * 修改人,记录创建人的帐号 + */ @TableField(value="UPDATEUSER") private String updateuser; - @Schema(description = "更新时间") + /** + * 更新时间 + */ @TableField(value="UPDATETIME") private Long updatetime; - @Schema(description = "三方系统标识,用于第三方系统标志使用") + /** + * 三方系统标识,用于第三方系统标志使用 + */ @TableField(value="OTHERNO") private String otherno; diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Userapprove.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Userapprove.java index 8b93a43..ab747be 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Userapprove.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/dataobject/Userapprove.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -21,64 +21,67 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +/** + * 用户审批过的关联表 + */ + @Data @Builder @NoArgsConstructor @AllArgsConstructor -@Schema(name = "用户审批过的关联表", title = "用户审批过的关联表") @TableName(value = "OA_USERAPPROVE_T") public class Userapprove implements BaseDto,java.io.Serializable { private static final long serialVersionUID = 8103332734950693652L; - @Schema(description = "流水号") + @ApiModelProperty(value = "流水号") @TableId(value = "id",type = IdType.ASSIGN_ID) @JsonSerialize(using = ToStringSerializer.class) @TableField(value="ID") private Long id; - @Schema(description = "审批用户主键,记录审批人的主键") + @ApiModelProperty(value = "审批用户主键,记录审批人的主键") @TableField(value="USERID") @JsonSerialize(using = ToStringSerializer.class) private Long userid; - @Schema(description = "表单主键,业务表主键") + @ApiModelProperty(value = "表单主键,业务表主键") @TableField(value="FORMID") @JsonSerialize(using = ToStringSerializer.class) private Long formid; - @Schema(description = "审批节点名称") + @ApiModelProperty(value = "审批节点名称") @TableField(value="TASKNAME") private String taskname; - @Schema(description = "审批状态,记录当前节点审批状态,1:.待审批 (只针对前端返回 库中逻辑上不存在) 2.通过 3.不通过") + @ApiModelProperty(value = "审批状态,记录当前节点审批状态,1:.待审批 (只针对前端返回 库中逻辑上不存在) 2.通过 3.不通过") @TableField(value="STATSHIS") private Integer statshis; - @Schema(description = "审批意见") + @ApiModelProperty(value = "审批意见") @TableField(value="COMMENTHIS") private String commenthis; - @Schema(description = "节点位置,待定字段,") + @ApiModelProperty(value = "节点位置,待定字段,") @TableField(value="TASKINDEX") private String taskindex; - @Schema(description = "节点编号") + @ApiModelProperty(value = "节点编号") @TableField(value="TASKNO") private String taskno; - @Schema(description = "用户名称") + @ApiModelProperty(value = "用户名称") @TableField(value="USERNAME") private String username; - @Schema(description = "创建时间") + @ApiModelProperty(value = "创建时间") @TableField(value="CREATEDATE") private Long createdate; - @Schema(description = "审批意见") + @ApiModelProperty(value = "审批意见") @TableField(value="TASKCOMMENT") private String taskcomment; - @Schema(description = "审批不通过原因") + @ApiModelProperty(value = "审批不通过原因") @TableField(value="REASON") private String reason; - @Schema(description = "审批不通过处理方式") + @ApiModelProperty(value = "审批不通过处理方式") @TableField(value="PROCESSMETHOD") private String processMethod; diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/DuplicateTaskService.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/DuplicateTaskService.java new file mode 100644 index 0000000..7874339 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/DuplicateTaskService.java @@ -0,0 +1,16 @@ +package org.jeecg.module.custom.ocr.service; + +import org.jeecg.module.custom.ocr.controller.dto.DuplicateTaskRequest; +import org.jeecg.module.custom.ocr.dataobject.DuplicateTask; + +import java.util.List; + + +public interface DuplicateTaskService { + + void save(DuplicateTaskRequest request); + + void updateCompletedById(Long id); + + List getAllUnCompletedTask(); +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/OcrPictureService.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/OcrPictureService.java index 8f163d1..cd2ef11 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/OcrPictureService.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/OcrPictureService.java @@ -1,5 +1,6 @@ package org.jeecg.module.custom.ocr.service; +import com.baomidou.mybatisplus.core.conditions.Wrapper; import org.jeecg.module.custom.ocr.base.BaseService; import org.jeecg.module.custom.ocr.dataobject.OcrPicture; @@ -10,6 +11,9 @@ import java.util.Map; * 业务层 */ public interface OcrPictureService extends BaseService { + + List listPage(Wrapper queryWrapper); + /** * 批量保存 图片信息 * diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/TaskService.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/TaskService.java new file mode 100644 index 0000000..7caa440 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/TaskService.java @@ -0,0 +1,12 @@ +package org.jeecg.module.custom.ocr.service; + +import org.jeecg.module.custom.ocr.controller.dto.AddTaskRequest; + +import javax.validation.constraints.NotNull; + +public interface TaskService { + + void save(AddTaskRequest request); + + void deleteTask(Long taskNo); +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/DuplicateTaskServiceImpl.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/DuplicateTaskServiceImpl.java new file mode 100644 index 0000000..8de8ae9 --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/DuplicateTaskServiceImpl.java @@ -0,0 +1,68 @@ +package org.jeecg.module.custom.ocr.service.impl; + +import org.jeecg.module.custom.ocr.controller.dto.DuplicateTaskData; +import org.jeecg.module.custom.ocr.controller.dto.DuplicateTaskRequest; +import org.jeecg.module.custom.ocr.dataDao.DuplicateTaskMapper; +import org.jeecg.module.custom.ocr.dataobject.DuplicateTask; +import org.jeecg.module.custom.ocr.service.DuplicateTaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class DuplicateTaskServiceImpl implements DuplicateTaskService { + + @Autowired + private DuplicateTaskMapper duplicateTaskMapper; + + @Override + public void save(DuplicateTaskRequest request) { + DuplicateTask task = toDuplicateTask(request); + duplicateTaskMapper.save(task); + } + + @Override + public void updateCompletedById(Long id) { + duplicateTaskMapper.updateCompletedById(id); + } + + @Override + public List getAllUnCompletedTask() { + return duplicateTaskMapper.getAllUnCompletedTask(); + } + + private DuplicateTask toDuplicateTask(DuplicateTaskRequest request) { + DuplicateTask task = new DuplicateTask(); + + // 映射顶级字段 + task.setTenantCode(request.getTenantCode()); + task.setAccessKey(request.getAccessKey()); + task.setTimestamp(request.getTimestamp()); + task.setSignature(request.getSignature()); + + // 映射 DuplicateTaskData 中的字段 + if (request.getData() != null) { + DuplicateTaskData data = request.getData(); + task.setAccountNo(data.getAccountNo()); + task.setTenantNo(data.getTenantNo()); + task.setRequestId(data.getRequestId()); + task.setQueryConfig(data.getQueryConfig()); + + // 将 List taskNos 转换为逗号分隔的字符串 + if (data.getTaskNos() != null && !data.getTaskNos().isEmpty()) { + String taskNosString = data.getTaskNos().stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); + task.setTaskNos(taskNosString); + } + } + + // 设置默认值 + task.setMaxSimilarityScore(null); // 未提供,设为 null + task.setCompleted(false); // 默认未完成 + + return task; + } +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPictureServiceImpl.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPictureServiceImpl.java index 5269020..1d2ac8f 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPictureServiceImpl.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPictureServiceImpl.java @@ -1,6 +1,9 @@ package org.jeecg.module.custom.ocr.service.impl; import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jeecg.module.custom.ocr.api.entity.FormRecord; @@ -61,6 +64,15 @@ public class OcrPictureServiceImpl extends BaseServiceImpl listPage(Wrapper queryWrapper) { + + long count = this.count(queryWrapper); + Page ocrPicturePage = new Page<>(1, count); + ocrPicturePage.setMaxLimit(count); + IPage iPage = this.page(ocrPicturePage, queryWrapper); + + return iPage.getRecords(); + } @Override public int savePictures(List ocrPictureList) { diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPrevailCloudLogServiceImpl.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPrevailCloudLogServiceImpl.java index db4034d..ee8004f 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPrevailCloudLogServiceImpl.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/OcrPrevailCloudLogServiceImpl.java @@ -6,6 +6,6 @@ import org.jeecg.module.custom.ocr.dataobject.OcrPrevailCloudLog; import org.jeecg.module.custom.ocr.service.OcrPrevailCloudLogService; import org.springframework.stereotype.Service; -@Service("ocrPrevailCloudLogService") +@Service public class OcrPrevailCloudLogServiceImpl extends BaseServiceImpl implements OcrPrevailCloudLogService { } diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/TaskServiceImpl.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/TaskServiceImpl.java new file mode 100644 index 0000000..20bf6ed --- /dev/null +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/service/impl/TaskServiceImpl.java @@ -0,0 +1,115 @@ +package org.jeecg.module.custom.ocr.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.jeecg.module.custom.ocr.api.entity.FormRecord; +import org.jeecg.module.custom.ocr.api.thread.TaskQueue; +import org.jeecg.module.custom.ocr.controller.dto.AddTaskRequest; +import org.jeecg.module.custom.ocr.controller.dto.TaskDTO; +import org.jeecg.module.custom.ocr.dataDao.TaskMapper; +import org.jeecg.module.custom.ocr.dataobject.Task; +import org.jeecg.module.custom.ocr.service.TaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TaskServiceImpl implements TaskService { + + @Autowired + private TaskMapper taskMapper; + + @Override + public void save(AddTaskRequest request) { + Task task = toTask(request); + FormRecord formRecord = toFormRecord(request); + // 任务落库 + taskMapper.save(task); + + // 图片任务 将图片下载并更新imgHash到ocr_picture库中 + TaskQueue.pictureImgToLocalPushData(formRecord); + } + + @Override + public void deleteTask(Long taskNo) { + taskMapper.deleteByTaskNo(taskNo); + } + + private Task toTask(AddTaskRequest request) { + Task task = new Task(); + + // 设置 AddTaskRequest 中的顶级字段 + task.setTenantCode(request.getTenantCode()); + task.setAccessKey(request.getAccessKey()); + task.setTimestamp(request.getTimestamp()); + task.setSignature(request.getSignature()); + + // 处理 AddTaskData 中的 records 列表 + if (request.getData() != null && request.getData().getRecords() != null && !request.getData().getRecords().isEmpty()) { + // 取第一条 TaskDTO 记录(如果需要处理多条记录,可改为循环) + TaskDTO taskDTO = request.getData().getRecords().get(0); + + // 映射 TaskDTO 到 Task + task.setTenantNo(taskDTO.getTenantNo()); + task.setTaskNo(taskDTO.getTaskNo()); + task.setAccountNo(taskDTO.getAccountNo()); + task.setAccountName(taskDTO.getAccountName()); + task.setProjectNo(taskDTO.getProjectNo()); + task.setProjectName(taskDTO.getProjectName()); + task.setTaskFormNo(taskDTO.getTaskFormNo()); + task.setPlanNo(taskDTO.getPlanNo()); + task.setPlanName(taskDTO.getPlanName()); + task.setPlanChildNo(taskDTO.getPlanChildNo()); + task.setPlanChildName(taskDTO.getPlanChildName()); + task.setTaskId(taskDTO.getTaskId()); + task.setTaskName(taskDTO.getTaskName()); + task.setUserNo(taskDTO.getUserNo()); + task.setUserName(taskDTO.getUserName()); + task.setSubmitTime(taskDTO.getSubmitTime()); + task.setLivePhoto(JSONObject.toJSONString(taskDTO.getLivePhoto())); + + // 将 Map 转换为 JSON 字符串 + try { + ObjectMapper objectMapper = new ObjectMapper(); + String dynamicFieldsJson = objectMapper.writeValueAsString(taskDTO.getDynamicFields()); + task.setDynamicFields(dynamicFieldsJson); + } catch (Exception e) { + // 处理序列化异常,可根据业务需求抛出或记录日志 + throw new RuntimeException("Failed to serialize dynamicFields", e); + } + } + + return task; + } + + private FormRecord toFormRecord(AddTaskRequest request) { + FormRecord formRecord = new FormRecord(); + + // 处理 AddTaskData 中的 records 列表 + if (request.getData() != null && request.getData().getRecords() != null && !request.getData().getRecords().isEmpty()) { + // 取第一条 TaskDTO 记录 + TaskDTO taskDTO = request.getData().getRecords().get(0); + + // 映射 TaskDTO 到 FormRecord + formRecord.setTenantNo(taskDTO.getTenantNo()); + formRecord.setTenantName(request.getTenantCode()); // 假设 tenantName 使用 tenantCode,需确认 + formRecord.setAccountNo(taskDTO.getAccountNo()); + formRecord.setAccountName(taskDTO.getAccountName()); + formRecord.setProjectNo(taskDTO.getProjectNo()); + formRecord.setProjectName(taskDTO.getProjectName()); + formRecord.setTaskFormNo(taskDTO.getTaskFormNo()); + formRecord.setPlanNo(taskDTO.getPlanNo()); + formRecord.setPlanName(taskDTO.getPlanName()); + formRecord.setPlanChildNo(taskDTO.getPlanChildNo()); + formRecord.setPlanChildName(taskDTO.getPlanChildName()); + formRecord.setTaskId(taskDTO.getTaskId()); + formRecord.setTaskName(taskDTO.getTaskName()); + formRecord.setUserNo(taskDTO.getUserNo()); + formRecord.setUserName(taskDTO.getUserName()); + formRecord.setSubmitTime(taskDTO.getSubmitTime()); + formRecord.setLivePhoto(taskDTO.getLivePhoto()); + formRecord.setDynamicFields(taskDTO.getDynamicFields()); + } + + return formRecord; + } +} diff --git a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/utils/ImageClassUtil.java b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/utils/ImageClassUtil.java index 543072e..77e6f36 100644 --- a/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/utils/ImageClassUtil.java +++ b/jeecg-module-custom/src/main/java/org/jeecg/module/custom/ocr/utils/ImageClassUtil.java @@ -13,36 +13,67 @@ import org.slf4j.LoggerFactory; public class ImageClassUtil { private static Logger logger = LoggerFactory.getLogger(ImageClassUtil.class); + private final static String SERVER_URL = "http://47.93.59.251/ai/api/classify/"; + + /** + * 相似度检查 + * 接口文档 + * https://console-docs.apipost.cn/preview/b85e3fe97510f177/96421d73df6c7f7d + * + * @param imgUrl + * @param baseurl + * @return + */ + public static String getSimilarity(String imgUrl, String baseurl) { + JSONObject jsonObjectXs = new JSONObject(); + jsonObjectXs.put("imgUrl", imgUrl); + jsonObjectXs.put("baseUrl", baseurl); + + HttpParamers paramersXs = HttpParamers.httpPostParamers(); + paramersXs.setJsonParamer(jsonObjectXs.toJSONString()); + HttpHeader headerXs = null; + String responseDataXs = ""; + try { + responseDataXs = HttpClient.doService(SERVER_URL, paramersXs, headerXs, 15000, 30000); + } catch (Exception e) { + logger.error("similarity={}", e); + return null; + } + JSONObject jsonObject = JSON.parseObject(responseDataXs); + return jsonObject.get("similarity").toString(); + } + /** * 类型检查 * 接口文档 * https://console-docs.apipost.cn/preview/7add2088a9a191d5/874020cbfba4287b + * * @param imgurl * @param taskId - * @return { - * "code": 0, - * "data": [ - * { - * "imgs": "/server/data/images/1754716707781476352.jpg", - * "classId": 704, - * "scores": 0.11721831560134888, - * "hash": "0000000000000000110001101111111111100110111011101111110011110000" - * } - * ], - * "taskId": "1" + * @return { + * "code": 0, + * "data": [ + * { + * "imgs": "/server/data/images/1754716707781476352.jpg", + * "classId": 704, + * "scores": 0.11721831560134888, + * "hash": "0000000000000000110001101111111111100110111011101111110011110000" + * } + * ], + * "taskId": "1" * } */ - public static JSONObject getClassify(String imgurl,String taskId,String serverurl){ - if(StringUtils.isBlank(serverurl)){ + public static JSONObject getClassify(String imgurl, String taskId, String serverurl) { + if (StringUtils.isBlank(serverurl)) { serverurl = "http://47.93.59.251/ai/api/classify/"; } - + //类型检查 JSONObject jsonObjectVi = new JSONObject(); - jsonObjectVi.put("taskId",taskId); + jsonObjectVi.put("taskId", taskId); JSONArray jsonArrayVi = new JSONArray(); jsonArrayVi.add(imgurl); - jsonObjectVi.put("imgUrls",jsonArrayVi); + jsonObjectVi.put("imgUrls", jsonArrayVi); HttpParamers paramersVi = HttpParamers.httpPostParamers(); paramersVi.setJsonParamer(jsonObjectVi.toJSONString()); diff --git a/jeecg-module-custom/src/main/resources/application.yml b/jeecg-module-custom/src/main/resources/application.yml new file mode 100644 index 0000000..2eaba13 --- /dev/null +++ b/jeecg-module-custom/src/main/resources/application.yml @@ -0,0 +1,269 @@ +server: + compression: + enabled: true + min-response-size: 10KB + mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json + port: 9090 + servlet: + session: + timeout: ${xiaoyao.cache.tokenExpire} + context-path: /foodapi +knife4j: + enable: true + documents: + - + group: 1.2.x + name: 测试自定义标题分组 + # 某一个文件夹下所有的.md文件 + locations: classpath:markdown/* +spring: + datasource: + url: jdbc:mysql://localhost:3306/ocr?useUnicode=true&nullCatalogMeansCurrent=true&characterEncoding=UTF-8&characterSetResults=utf8&serverTimezone=Asia/Shanghai&useSSL=false + driver-class-name: com.mysql.cj.jdbc.Driver + username: root + password: qwertyuiop[] + type: com.alibaba.druid.pool.DruidDataSource + druid: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: + login-password: + allow: + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + servlet: + multipart: + max-file-size: 50MB + max-request-size: 50MB + freemarker: + template-loader-path: file:${xiaoyao.web.webPath} + suffix: .html + allow-request-override: true + cache: true + check-template-location: true + charset: UTF-8 + content-type: text/html + expose-request-attributes: false + expose-session-attributes: false + expose-spring-macro-helpers: false + request-context-attribute: request + web: + resources: + static-locations: file:${xiaoyao.web.webPath},file:${xiaoyao.web.uploadPath},file:${xiaoyao.web.frontPath},file:${xiaoyao.web.staticPath} + session: + store-type: none + cache: + type: ehcache + ehcache: + config: classpath:/myehcache.xml +flowable: + modeler: + app: + deployment-api-url: http://127.0.0.1:9090/foodapi/flowable-task/app-api + #关闭定时任务JOB + async-executor-activate: false + database-schema-update: false +# +# cache: +# type: redis +# redis: +# #Redis服务器地址 +# #host: 192.168.0.198 +# host: 127.0.0.1 +# # Redis服务器连接端口 +# port: 6379 +# # 链接超时时间 单位 ms(毫秒) +# timeout: 20000 +## cluster: +## nodes: +## 192.168.0.191:7001, +## 192.168.0.192:7001, +## 192.168.0.193:7001, +## 192.168.0.201:7001, +## 192.168.0.202:7001, +## 192.168.0.203:7001 +## #跨集群执行命令时要遵循的最大重定向数量 +## max-redirects: 18 +# #lettuce: +# jedis: +# pool: +# #连接池最大连接数(使用负值表示没有限制) 默认 8 +# max-active: 20 +# #连接池中的最大空闲连接 默认 8 +# max-idle: 10 +# #连接池中的最小空闲连接 默认 0 +# min-idle: 10 +# #连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1 +# max-wait: 10000 +mybatis: + mapper-locations: + - classpath*:mapper/**/*.xml + # - classpath*:/META-INF/modeler-mybatis-mappings/*.xml + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + configuration-properties: + prefix: + blobType: BLOB + boolValue: TRUE +mybatis-plus: + configuration: + map-underscore-to-camel-case: true + global-config: + db-config: + logic-delete-value: 20 + logic-not-delete-value: 10 + configuration-properties: + prefix: + blobType: BLOB + boolValue: TRUE +xiaoyao: + web: + #上传文件路径 + uploadPath: D:\work\java\gitlab\ocr\htmlweb/upload + #页面根路径 + frontPath: D:\work\java\gitlab\ocr\htmlweb + #js、css、图片存放路径 + staticPath: D:\work\java\gitlab\ocr\htmlweb/static + #页面模版路径 + webPath: D:\work\java\gitlab\ocr\htmlweb/web + #Lucene索引路径 + lucenePath: D:\work\java\gitlab\ocr\htmlweb/lucene/indexDir + #是否开启flowable + haveFlowable: true + webconfig: + #是否用于测试,测试数据不向其他服务器发送 + useSend: true + #jwt 的密钥 + jwtKey: and0X3ZhBGlkYXRpb25fY22uZmlnX1tleQ== + #用户基本信息是否加密,注意数字或字母加密后长度会是原数据的三倍,汉字是原数据的八倍 + entryUse: true + # 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制) + maxLoginSession: 1 + # maxLoginSession为1时,当前状态为true踢出之前登录的用户,否则不能登录 + killOutAfter: false + # 密码错误5次锁定{passwordMaxRetryTime}分钟 + passwordMaxRetryCount: 5 + # 密码错误锁定10分钟 + passwordMaxRetryTime: 10 + #不需要过滤的静态资源 + nofilterurls: /,/static/**,/upload/**,/fonts/**,/druid/**,/site/**,/*.txt,/modeler/**,/swagger-ui.html,/v2/**,/swagger-resources/**,/doc.html/**,/webjars/springfox-swagger-ui/** + #排除链接(多个用双引号包括并且逗号分隔) + excludes: /lanjieqibuhaoyong + #后台管理登录页面入口 + loginPage: ${server.servlet.context-path}/loginadmin + #后台管理登陆 + loginProcessingUrl: /backstage/adminlogin + #后台管理登出 + logoutProcessingUrl: /backstage/adminlogout + #后台管理登录成功跳转的url + loginSuccessUrl: /backstage/index + #超级管理员账号,与数据库对应 + sysLoginUser: admin,zhangyong + #用户默认密码 + userDefaultPassword: 123456 + #是否开启cookie,用于存储校验信息 + cookieopen: true + #Cookie的名字 + cookieName: usertoken + #cookie的有效域 + cookieDomain: + #Cookies的有效期,24 * 60 * 60(1天) + cookieMaxAge: 86400 + #cookie的有效路径 + cookiePath: / + #异步线程池 + task: + #核心线程池大小 + corePoolSize: 20 + #最大线程数 + maxPoolSize: 40 + #活跃时间 + keepAliveSeconds: 300 + #队列容量 + queueCapacity: 50 + #前缀 + taskPrix: taskprix + #上传配置 + uploadConfig: + #none(当前服务器),ftp(ftpServer服务),fdfs(使用FastDFS服务作为文件管理) + type: none + #集群情况下,可能使用分组的方式进行,当前字段主要用户分组前缀使用,例如在FastDFS中的分组填写group1、group2,只能填写数组 + prefix: ftp + ftpServer: + #ftp服务器地址 + ftpHostName: 192.168.0.148 + #ftp服务器端口号默认为21 + ftpHostPort: 21 + #ftp登录账号 + ftoHostUserName: ftp_wordpress + #ftp登录密码 + ftpHostPassword: n123456 + #cms静态化文件,在集群下同步htm文件 + cmsFtpServer: + #是否单独发布手机端静态页面 + mobile: true + #是否开启 + isOpen: false + #ftp服务器地址 + ftpHostName: 192.168.0.148 + #ftp服务器端口号默认为21 + ftpHostPort: 21 + #ftp登录账号 + ftoHostUserName: ftp_wordpress + #ftp登录密码 + ftpHostPassword: n123456 + #FastDFS配置文件路径,查找classpath下的文件 + fdfs_client_path: fdfs_client.conf + cache: + #缓存前缀 + prefix: basegps_ + #缓存默认名称 + managerName: cacheMgrGps + #有效时长(秒),目前登录用户、session使用 + tokenExpire: 18000 + #缓存名称分隔符 + cacheNamePrix: "_" + #存放缓存刷新时间是,使用临时缓存名称前缀 + cacheNameTimePrix: time +springfox: + documentation: + swagger-ui: + enabled: true +# 是否启用swagger,postman调试 +debugger_tools: true +#图片查重模型 +image: + similarityPath: http://81.70.154.131/ai/api/similarity/ + classifyPath: http://81.70.154.131/api/classify/ + serverUrl: http://81.70.154.131/api/image/ diff --git a/jeecg-module-custom/src/main/resources/mapper/DuplicateTaskMapper.xml b/jeecg-module-custom/src/main/resources/mapper/DuplicateTaskMapper.xml new file mode 100644 index 0000000..52522c1 --- /dev/null +++ b/jeecg-module-custom/src/main/resources/mapper/DuplicateTaskMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + id, tenant_code, access_key, `timestamp`, signature, account_no, tenant_no, + request_id, task_nos, query_config, max_similarity_score, completed + + + + INSERT INTO duplicate_task ( + + ) VALUES ( + #{id}, + #{tenantCode}, + #{accessKey}, + #{timestamp}, + #{signature}, + #{accountNo}, + #{tenantNo}, + #{requestId}, + #{taskNos}, + #{queryConfig}, + #{maxSimilarityScore}, + #{completed} + ) + + + + + + UPDATE duplicate_task + SET completed = #{completed,jdbcType=TINYINT} + WHERE id = #{id,jdbcType=BIGINT} + + + + UPDATE duplicate_task + SET completed = #{completed,jdbcType=TINYINT}, + max_similarity_score = #{maxSimilarityScore} + WHERE id = #{id,jdbcType=BIGINT} + + diff --git a/jeecg-module-custom/src/main/resources/mapper/FormConfigMapper.xml b/jeecg-module-custom/src/main/resources/mapper/FormConfigMapper.xml index c09c879..f603538 100644 --- a/jeecg-module-custom/src/main/resources/mapper/FormConfigMapper.xml +++ b/jeecg-module-custom/src/main/resources/mapper/FormConfigMapper.xml @@ -1,6 +1,6 @@ - + diff --git a/jeecg-module-custom/src/main/resources/mapper/PictureCompareMapper.xml b/jeecg-module-custom/src/main/resources/mapper/PictureCompareMapper.xml new file mode 100644 index 0000000..83ebf85 --- /dev/null +++ b/jeecg-module-custom/src/main/resources/mapper/PictureCompareMapper.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + id, first_img_no, first_img_url, first_local_img_url, first_img_hash, + second_img_no, second_img_url, second_local_img_url, second_img_hash, + similarity_score + + + + INSERT INTO photos_compare ( + first_img_no, first_img_url, first_local_img_url, first_img_hash, + second_img_no, second_img_url, second_local_img_url, second_img_hash, + similarity_score + ) VALUES ( + #{firstImgNo}, + #{firstImgUrl}, + #{firstLocalImgUrl}, + #{firstImgHash}, + #{secondImgNo}, + #{secondImgUrl}, + #{secondLocalImgUrl}, + #{secondImgHash}, + #{similarityScore} + ) + + diff --git a/jeecg-module-custom/src/main/resources/mapper/TaskMapper.xml b/jeecg-module-custom/src/main/resources/mapper/TaskMapper.xml new file mode 100644 index 0000000..80b9974 --- /dev/null +++ b/jeecg-module-custom/src/main/resources/mapper/TaskMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id, tenant_code, access_key, timestamp, signature, tenant_no, task_no, account_no, + account_name, project_no, project_name, task_form_no, plan_no, plan_name, + plan_child_no, plan_child_name, task_id, task_name, user_no, user_name, + submit_time, live_photo, dynamic_fields + + + + INSERT INTO task ( + + ) VALUES ( + #{id}, + #{tenantCode}, + #{accessKey}, + #{timestamp}, + #{signature}, + #{tenantNo}, + #{taskNo}, + #{accountNo}, + #{accountName}, + #{projectNo}, + #{projectName}, + #{taskFormNo}, + #{planNo}, + #{planName}, + #{planChildNo}, + #{planChildName}, + #{taskId}, + #{taskName}, + #{userNo}, + #{userName}, + #{submitTime}, + #{livePhoto}, + #{dynamicFields}, + #{imgHash}, + #{similarityScore} + ) + + + + DELETE FROM task WHERE task_no = #{taskNo,jdbcType=BIGINT} + + diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java index 5f8aa52..15f0bb0 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiController.java @@ -31,7 +31,6 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; -import springfox.documentation.spring.web.DocumentationCache; import javax.servlet.http.HttpServletRequest; import java.util.*; @@ -50,8 +49,6 @@ public class OpenApiController extends JeecgController @Autowired private OpenApiHeaderService openApiHeaderService; @Autowired - private DocumentationCache documentationCache; - @Autowired private TypeResolver typeResolver; @Autowired private ISysUserService sysUserService; diff --git a/pom.xml b/pom.xml index d81b670..ceade09 100644 --- a/pom.xml +++ b/pom.xml @@ -585,4 +585,4 @@ - \ No newline at end of file +