Commit 2bafb3ed by 刘栋

UDI

parents
Showing with 7486 additions and 0 deletions
/saas-udi/saas-udi-api/target/*
/saas-udi/saas-udi-service/target/*
/logs/
/.idea/
No preview for this file type
No preview for this file type
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>saas-udi</artifactId>
<name>saas-udi</name>
<groupId>com.infynova</groupId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>saas-udi-api</module>
<module>saas-udi-service</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<java.version>1.8</java.version>
<springboot.version>2.4.6</springboot.version>
<nacos.client.version>1.4.1</nacos.client.version>
<spring.cloud.version>2020.0.3</spring.cloud.version>
<alibaba.version>2021.1</alibaba.version>
<lombok.version>1.18.20</lombok.version>
<fastjson.version>1.2.57</fastjson.version>
<mybatisplus.version>3.4.0</mybatisplus.version>
<mybatisplus.dynamic.datasource.version>3.4.1</mybatisplus.dynamic.datasource.version>
<spring.version>5.3.7</spring.version>
<redis.version>2.4.2</redis.version>
<commons.io.version>2.11.0</commons.io.version>
<commons.fileupload.version>1.3.1</commons.fileupload.version>
<commons.lang.version>3.9</commons.lang.version>
<commons.collections4.version>4.4</commons.collections4.version>
<mysql.connector.version>8.0.16</mysql.connector.version>
<knife4j.version>3.0.2</knife4j.version>
<swagger2.serion>3.0.0</swagger2.serion>
<swagger.ui.version>1.9.6</swagger.ui.version>
<hutool.version>5.6.7</hutool.version>
<httpclient.version>4.5.13</httpclient.version>
<easyexcel.version>3.1.1</easyexcel.version>
<javax.servlet.api.version>4.0.1</javax.servlet.api.version>
<log4j.version>2.17.0</log4j.version>
<javax.validation.version>2.0.1.Final</javax.validation.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.client.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${redis.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- swagger2 knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet.api.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger2.serion}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>${swagger.ui.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons.collections4.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${javax.validation.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<!-- 指定JDK编译版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>saas-udi</artifactId>
<groupId>com.infynova</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>saas-udi-api</artifactId>
<properties>
<jeecg-autopoi.version>1.3.6</jeecg-autopoi.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.4.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<dependency>
<groupId>com.infynova</groupId>
<artifactId>saas-core</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/../libs/saas-core-1.0.0.jar</systemPath>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.infynova.udi;
import com.infynova.common.core.api.ServiceCode;
import java.util.Arrays;
public enum UdiCode implements ServiceCode {
NOFOUND(720001, "数据不存在")
, ILLEGAL(720002, "非法操作")
, UNKNOWN(720003, "未知错误")
, PARAMETER_ERROR(720004, "参数错误")
, SYSTEM_DATA_NOT_REMOVE(750001, "系统数据无法移除")
, GET_COMPANY_ERROR(750002, "获取分公司出现异常")
, IMPORT_ERROR(750003, "导入错误")
, IMPORT_NULL_ERROR(750004,"导入数据为空")
, FILE_IS_NOT_NULL(750005, "文件不允许为空")
, GET_REGION_ERROR(750006, "获取大区出现异常")
, GET_SELLER_ERROR(750007, "获取销售人员出现异常")
;
private int code;
private String msg;
@Override
public int getCode() {
return code;
}
@Override
public String getMsg() {
return msg;
}
UdiCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static ServiceCode getServiceCode(int code) {
return Arrays.stream(UdiCode.values()).filter(p -> p.getCode() == code).findFirst().orElse(UdiCode.UNKNOWN);
}
}
package com.infynova.udi.config;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
*
* @description long类型id避免丢长度
* @author zoupx
* @date 2020/9/15
* @return
*/
@Configuration
public class JsonSerializerManage {
@Bean
public ObjectMapper jacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule javaTimeModule=new JavaTimeModule();
// java8时间序列化
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
SimpleModule longModule = new SimpleModule();
longModule.addSerializer(new LongToStringSerializer(Long.class));
objectMapper.registerModule(longModule);
objectMapper.registerModules(longModule, javaTimeModule);
objectMapper.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN));
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}
}
package com.infynova.udi.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
public class LongToStringSerializer extends StdSerializer<Long> {
protected LongToStringSerializer(Class<Long> t) {
super(t);
}
@Override
public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
if (value == null) {
jsonGenerator.writeString("");
} else {
jsonGenerator.writeString(value.toString());
}
}
}
\ No newline at end of file
package com.infynova.udi.constant;
public interface UdiConstant {
String UDI_PACKAGE_NAME = "com.infynova.udi";
String INFYNOVA_PACKAGE_NAME = "com.infynova";
String MAPPER_PACKAGE_NAME = "com.infynova.udi.mapper";
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.PageVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.Collection;
/**
* idList分页入参
* @author liudong
* 2022-08-05 19:48
*/
@Data
@ApiModel(value="IdListPageQry",description="IdListPageQry")
public class IdListPageQry extends PageVo {
/**
* 租户号
*/
@ApiModelProperty(value = "租户号")
private Long tenantId;
/**
* id集合
*/
@NotEmpty(message = "idList不能为空")
@ApiModelProperty(value = "id集合",required = true)
private Collection<Long> idList;
}
package com.infynova.udi.dto;
import com.infynova.common.core.api.BaseVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.Collection;
/**
* idList入参
* @author liudong
* 2022-08-05 19:48
*/
@Data
@ApiModel(value="IdListQry",description="IdListQry")
public class IdListQry extends BaseVo {
/**
* 租户号
*/
@ApiModelProperty(value = "租户号")
private Long tenantId;
/**
* id集合
*/
@NotEmpty(message = "idList不能为空")
@ApiModelProperty(value = "id集合",required = true)
private Collection<Long> idList;
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.PageVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* id分页入参
* @author liudong
* 2022-08-05 19:48
*/
@Data
@ApiModel(value="IdPageQry",description="IdPageQry")
public class IdPageQry extends PageVo {
/**
* 租户号
*/
@ApiModelProperty(value = "租户号")
private Long tenantId;
/**
* id集合
*/
@NotNull(message = "id不能为空")
@ApiModelProperty(value = "id",required = true)
private Long id;
}
package com.infynova.udi.dto;
import com.infynova.common.core.api.BaseVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
/**
* id入参
* @author liudong
* 2022-08-05 19:48
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@ApiModel(value="IdQry",description="IdQry")
public class IdQry extends BaseVo {
/**
* 租户号
*/
@ApiModelProperty(value = "租户号")
private Long tenantId;
/**
* id集合
*/
@NotNull(message = "id不能为空")
@ApiModelProperty(value = "id",required = true)
private Long id;
}
package com.infynova.udi.dto;
import lombok.Getter;
/**
* 照搬obs导入返回结果集
* 2023-11-08 16:12:00
*/
@Getter
public class ImportItemCount {
private int totalNum;
private int successNum;
private int failNum;
public void addTotalNum() {
this.totalNum ++;
}
public void addSuccessNum() {
this.successNum ++;
}
public void addFailNum() {
this.failNum ++;
}
public void addTotalNum(int num) {
this.totalNum = this.totalNum + num;
}
public void addSuccessNum(int num) {
this.successNum = this.successNum + num;
}
public void addFailNum(int num) {
this.failNum = this.failNum + num;
}
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.UploadResultVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 照搬obs导入返回结果集
* 2023-11-08 16:12:00
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ImportItemResp {
private UploadResultVo upload;
private ImportItemCount count;
}
package com.infynova.udi.dto;
import com.infynova.common.core.api.BaseVo;
import com.infynova.udi.helper.validator.FixedValueValidator;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author liudong
* 2024/2/22 19:44
* @version 1.0
*/
@Data
public class UdiAllMatchQry extends BaseVo {
@NotNull(message = "对码状态不能为空")
@FixedValueValidator(message = "对码状态类型错误", fixedValue = {"11","22","33","44"})
@ApiModelProperty(value = "对码状态:11-全部 22-部分对码 33-100%对码 44-完全未对码")
private Integer taskStatus;
@NotNull(message = "任务id不能为空")
@ApiModelProperty(value = "任务id")
private Long taskId;
}
package com.infynova.udi.dto;
import com.infynova.common.core.api.BaseVo;
import com.infynova.udi.helper.validator.FixedValueValidator;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author liudong
* 2024/2/22 19:44
* @version 1.0
*/
@Data
public class UdiBatchMatchQry extends BaseVo {
@NotNull(message = "对码状态不能为空")
@FixedValueValidator(message = "对码状态类型错误", fixedValue = {"11","22","33","44"})
@ApiModelProperty(value = "对码状态:11-全部 22-部分对码 33-100%对码 44-完全未对码")
private Integer taskStatus;
@NotNull(message = "matchId集合不能为空")
@ApiModelProperty(value = "matchId集合")
private List<Long> matchIdList;
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.PageVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class UdiListQry extends PageVo {
@ApiModelProperty(value = "DI码")
private String udiCode;
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
@ApiModelProperty(value = "企业名称")
private String companyName;
@ApiModelProperty(value = "品牌")
private String brandName;
@ApiModelProperty(value = "注册备案号")
private String registryNo;
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
@ApiModelProperty(value = "产品编码")
private String productCode;
@ApiModelProperty(value = "厂家产品货号/编号")
private String productFactoryCode;
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
@ApiModelProperty(value = "单件产品名称")
private String productName;
@ApiModelProperty(value = "产品类型")
private String productType;
@ApiModelProperty(value = "规格")
private String specification;
@ApiModelProperty(value = "型号")
private String model;
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private Boolean asepticPackaging;
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private Boolean beforeSterilize;
}
package com.infynova.udi.dto;
import com.infynova.common.core.api.BaseVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* @author liudong
* 2024/2/22 19:44
* @version 1.0
*/
@Data
public class UdiMatchConfirmationDto extends BaseVo {
@NotNull(message = "matchId不能为空")
@ApiModelProperty(value = "matchId")
private Long matchId;
@NotBlank(message = "DI码不能为空")
@ApiModelProperty(value = "DI码")
private String udiCode;
//@NotBlank(message = "医保编码不能为空")
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
@NotBlank(message = "厂家名称不能为空")
@ApiModelProperty(value = "厂家名称")
private String companyName;
//@NotBlank(message = "厂家产品货号或编号")
@ApiModelProperty(value = "厂家产品货号或编号")
private String productFactoryCode;
@NotBlank(message = "品牌")
@ApiModelProperty(value = "品牌")
private String brandName;
@NotBlank(message = "产品名称不能为空")
@ApiModelProperty(value = "单件产品名称")
private String productName;
@NotBlank(message = "规格不能为空")
@ApiModelProperty(value = "规格")
private String specification;
@NotBlank(message = "型号不能为空")
@ApiModelProperty(value = "型号")
private String model;
@NotBlank(message = "注册备案号不能为空")
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.PageVo;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.helper.validator.FixedValueValidator;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@ApiModel(value = "UdiMatchDetailListQry", description = "UdiMatchDetailListQry")
public class UdiMatchDetailListQry extends PageVo {
@NotNull(message = "查询类型不能为空")
@FixedValueValidator(message = "查询类型值错误", fixedValue = {"11","22","33","44"})
@ApiModelProperty(value = "查询类型:11-全部 22-部分对码 33-100%对码 44-完全未对码", required = true)
private Integer queryType;
@ApiModelProperty(value = "任务id")
private Long taskId;
@ApiModelProperty(value = "任务编号")
private String taskNo;
/** udi码 */
@ApiModelProperty(value = "udi码")
private String udiCode;
/** 医保编码 */
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
/** 企业名称 */
@ApiModelProperty(value = "企业名称")
private String companyName;
/** 品牌 */
@ApiModelProperty(value = "品牌")
private String brandName;
/** 厂家产品货号或编号 */
@ApiModelProperty(value = "厂家产品货号或编号")
private String productFactoryCode;
/** 产品编码 */
@ApiModelProperty(value = "产品编码")
private String productCode;
/** 规格 */
@ApiModelProperty(value = "规格")
private String specification;
/** 型号 */
@ApiModelProperty(value = "型号")
private String model;
/**
* @see MatchStatusEnum
*/
@ApiModelProperty(value = "对码状态: 对码状态:0-未开始、10-部分对码、20-100%对码、99-完全未对码")
private List<Integer> matchStatusList;
/**
* 处理状态:0-待处理、10-处理中、44-无需处理、100-已处理
* @see MatchUpdateStatusEnum
*/
@ApiModelProperty(value = "处理状态:0-待处理、10-处理中、44-无需处理、100-已处理")
private List<Integer> updateStatusList;
}
package com.infynova.udi.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author liudong
* 2024/3/26 18:06
* @version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ApiModel(value = "UdiMatchTaskFileDto", description = "UdiMatchTaskFileDto")
public class UdiMatchTaskFileDto implements Serializable {
@ApiModelProperty(value = "文件地址")
private String filePath;
@ApiModelProperty(value = "文件名称")
private String fileName;
@ApiModelProperty(value = "文件id")
private Long fileId;
}
package com.infynova.udi.dto;
import com.infynova.common.core.entity.PageVo;
import com.infynova.udi.helper.validator.FixedValueValidator;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
@Data
public class UdiMatchTaskListQry extends PageVo {
@NotNull(message = "查询类型不能为空")
@FixedValueValidator(message = "查询类型值错误", fixedValue = {"0","1","99"})
@ApiModelProperty(value = "查询类型:0:上传中 1:已上传 99:全部")
private Integer queryType;
@ApiModelProperty(value = "任务状态",hidden = true)
private List<Integer> taskStatusList;
@ApiModelProperty(value = "任务编号")
private String taskNo;
@ApiModelProperty(value = "操作人")
private String operator;
@ApiModelProperty(value = "上传时间开始")
private LocalDate uploadTimeStart;
@ApiModelProperty(value = "上传时间结束")
private LocalDate uploadTimeEnd;
}
package com.infynova.udi.dto;
import com.infynova.udi.vo.UdiVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* @author liudong
* 2024/4/29 10:38
* @version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UdiQueryDto implements Serializable {
private Integer total;
private List<UdiVo> data;
}
package com.infynova.udi.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 对码实体类
* @author liudong
* 2024/3/1 15:41
* @version 1.0
*/
@Data
public class MatchData {
/** 主键ID,自增 */
@TableId(type = IdType.AUTO)
private Long id;
/** 任务ID */
@ApiModelProperty(value = "任务ID")
private Long taskId;
@TableField(exist = false)
@ApiModelProperty(value = "任务编码")
private String taskNo;
/**
* 对码状态:0-未开始、10-部分对码、20-100%对码、99-完全未对码
* @see MatchStatusEnum
*/
@ApiModelProperty(value = "对码状态:0-未开始 10-部分对码、20-100%对码、99-完全未对码")
private Integer matchStatus;
@TableField(exist = false)
@ApiModelProperty(value = "对码状态名称")
private String matchStatusDesc;
/**
* 处理状态:0-待处理、10-处理中、44-无需处理、100-已处理
* @see MatchUpdateStatusEnum
*/
@ApiModelProperty(value = "处理状态:0-待处理、10-处理中、44-无需处理、100-已处理")
private Integer updateStatus;
@TableField(exist = false)
@ApiModelProperty(value = "处理状态名称")
private String updateStatusDesc;
/** udi码 */
@ApiModelProperty(value = "udi码")
private String udiCode;
/** 医保一级编码 */
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
/** 医保二级编码 */
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
/** 医保编码 */
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
/** 医保编码前缀 */
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
/** 企业名称 */
@ApiModelProperty(value = "企业名称")
private String companyName;
/** 品牌 */
@ApiModelProperty(value = "品牌")
private String brandName;
/** 注册备案号(注册证) */
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
/** 注册备案产品名称 */
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
/** 注册备案批准日期 */
@ApiModelProperty(value = "注册备案批准日期")
private LocalDate registryStartTime;
/** 注册备案有效期 */
@ApiModelProperty(value = "注册备案有效期")
private LocalDate registryEndTime;
/** 注册备案人 */
@ApiModelProperty(value = "注册备案人")
private String registry;
/** 产品编码 */
@ApiModelProperty(value = "产品编码")
private String productCode;
/** 厂家产品货号或编号 */
@ApiModelProperty(value = "厂家产品货号或编号")
private String productFactoryCode;
/** 无境UDI库分配编码 */
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
/** 单件产品名称 */
@ApiModelProperty(value = "单件产品名称")
private String productName;
/** 产品类型 */
@ApiModelProperty(value = "产品类型")
private String productType;
/** 规格 */
@ApiModelProperty(value = "规格")
private String specification;
/** 型号 */
@ApiModelProperty(value = "型号")
private String model;
/** 材质 */
@ApiModelProperty(value = "材质")
private String material;
/** 是否为无菌包装 0:否 1:是 */
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private Boolean asepticPackaging;
@TableField(exist = false)
@ApiModelProperty(value = "是否为无菌包装")
private String asepticPackagingDesc;
/** 使用前是否需要进行灭菌 0:否 1:是 */
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private Boolean beforeSterilize;
@TableField(exist = false)
@ApiModelProperty(value = "使用前是否需要进行灭菌")
private String beforeSterilizeDesc;
/** 灭菌方式 */
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
/** 创建人id */
@ApiModelProperty(value = "创建人id")
private Long createBy;
/** 创建人 */
@ApiModelProperty(value = "创建人")
private String createName;
/** 创建时间 */
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
/** 修改人id */
@ApiModelProperty(value = "修改人id")
private Long updateBy;
/** 修改人 */
@ApiModelProperty(value = "修改人")
private String updateName;
/** 修改时间 */
@ApiModelProperty(value = "修改时间")
private LocalDateTime updateTime;
/** 版本号,默认为1 */
@ApiModelProperty(value = "版本号,默认为1")
@Version
@TableField(fill = FieldFill.INSERT_UPDATE, update="%s+1")
private Integer version;
}
package com.infynova.udi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 对码表匹配表实体类
* @author liudong
* 2024/3/1 15:43
* @version 1.0
*/
@Data
public class MatchTemp {
/** 主键ID,自增 */
@TableId(type = IdType.AUTO)
private Long id;
/** 对码ID */
@ApiModelProperty(value = "对码ID")
private Long matchId;
/** 任务ID */
@ApiModelProperty(value = "任务ID")
private Long taskId;
/** 原始记录:0-否、1-是 */
@ApiModelProperty(value = "原始记录:0-否、1-是")
private Boolean originalRecord;
/** 匹配率 */
@ApiModelProperty(value = "匹配率")
private BigDecimal matchRate;
/** udi库主键ID */
@ApiModelProperty(value = "udi库主键ID")
private Long productId;
/** udi码 */
@ApiModelProperty(value = "udi码")
private String udiCode;
/** 医保一级编码 */
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
/** 医保二级编码 */
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
/** 医保编码 */
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
/** 医保编码前缀 */
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
/** 企业名称 */
@ApiModelProperty(value = "企业名称")
private String companyName;
/** 品牌 */
@ApiModelProperty(value = "品牌")
private String brandName;
/** 注册备案号(注册证) */
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
/** 注册备案产品名称 */
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
/** 注册备案批准日期 */
@ApiModelProperty(value = "注册备案批准日期")
private LocalDate registryStartTime;
/** 注册备案有效期 */
@ApiModelProperty(value = "注册备案有效期")
private LocalDate registryEndTime;
/** 注册备案人 */
@ApiModelProperty(value = "注册备案人")
private String registry;
/** 产品编码 */
@ApiModelProperty(value = "产品编码")
private String productCode;
/** 厂家产品货号或编号 */
@ApiModelProperty(value = "厂家产品货号或编号")
private String productFactoryCode;
/** 无境UDI库分配编码 */
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
/** 单件产品名称 */
@ApiModelProperty(value = "单件产品名称")
private String productName;
/** 产品类型 */
@ApiModelProperty(value = "产品类型")
private String productType;
/** 规格 */
@ApiModelProperty(value = "规格")
private String specification;
/** 型号 */
@ApiModelProperty(value = "型号")
private String model;
/** 材质 */
@ApiModelProperty(value = "材质")
private String material;
/** 是否为无菌包装 0:否 1:是 */
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private Boolean asepticPackaging;
/** 使用前是否需要进行灭菌 0:否 1:是 */
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private Boolean beforeSterilize;
/** 灭菌方式 */
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
/** 创建人id */
@ApiModelProperty(value = "创建人id")
private Long createBy;
/** 创建人 */
@ApiModelProperty(value = "创建人")
private String createName;
/** 创建时间 */
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
/** 修改人id */
@ApiModelProperty(value = "修改人id")
private Long updateBy;
/** 修改人 */
@ApiModelProperty(value = "修改人")
private String updateName;
/** 修改时间 */
@ApiModelProperty(value = "修改时间")
private LocalDateTime updateTime;
}
package com.infynova.udi.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/2/29 15:40
* @version 1.0
*/
@Data
public class Task {
/** 主键ID,自增 */
@TableId(type = IdType.AUTO)
private Long id;
/** 任务编码 */
@ApiModelProperty(value = "任务编码")
private String taskNo;
/**
* @see TaskStatusEnum
* 任务上传状态:新建、暂停、完毕
* */
@ApiModelProperty(value = "任务上传状态:0-新建、10-上传中、11-暂停、20-完毕")
private Integer taskStatus;
@TableField(exist = false)
@ApiModelProperty(value = "任务上传状态-转换")
private String taskStatusDesc;
/** 上传文件大小 */
@ApiModelProperty(value = "上传文件大小")
private String taskFileSize;
@TableField(exist = false)
@ApiModelProperty(value = "上传文件大小-转换")
private String taskFileSizeDesc;
/** 上传文件后的数据量 */
@ApiModelProperty(value = "上传文件后的数据量")
private Integer taskFileCount;
/** 上传的数据量 */
@ApiModelProperty(value = "上传的数据量")
private Integer taskUploadNum;
/** 上传文件地址 */
@ApiModelProperty(value = "上传文件地址")
private String taskFileAddress;
/** 上传文件id */
@ApiModelProperty(value = "上传文件id - 获取地址用")
private Long taskFileId;
/** 上传耗时(以秒为单位保存) */
@ApiModelProperty(value = "上传耗时(以秒为单位保存)")
private Integer uploadTime;
@TableField(exist = false)
@ApiModelProperty(value = "上传耗时(以秒为单位保存)-展示")
private String uploadTimeDesc;
/**
* @see TaskMatchStatusEnum
* 对码状态:待对码、对码中、已对码 */
@ApiModelProperty(value = "对码状态:对码状态:0-待对码、10-对码中、99-已对码")
private Integer taskMatchStatus;
@TableField(exist = false)
@ApiModelProperty(value = "对码状态-转换")
private String taskMatchStatusDesc;
/** 对码耗时(以秒为单位保存) */
@ApiModelProperty(value = "对码耗时(以秒为单位保存)")
private Integer matchTime;
@TableField(exist = false)
@ApiModelProperty(value = "对码耗时(以秒为单位保存)-展示")
private String matchTimeDesc;
/** 操作人id */
@ApiModelProperty(value = "操作人id")
private Long operatorId;
/** 操作人 */
@ApiModelProperty(value = "操作人")
private String operator;
/** 创建人id */
@ApiModelProperty(value = "创建人id")
private Long createBy;
/** 创建人 */
@ApiModelProperty(value = "创建人")
private Long creator;
/** 创建时间 */
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
/** 修改时间 */
@ApiModelProperty(value = "修改时间")
private LocalDateTime updateTime;
/** 删除标识 */
@ApiModelProperty(value = "删除标识")
private Boolean delFlag;
/** 版本号,默认为1 */
@ApiModelProperty(value = "版本号")
@Version
@TableField(fill = FieldFill.INSERT_UPDATE, update="%s+1")
private Integer version;
}
package com.infynova.udi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.infynova.udi.enums.task.TaskRecordEnum;
import com.infynova.udi.enums.task.TaskRecordTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 任务操作记录实体类
* @author liudong
* 2024/2/29 16:14
* @version 1.0
*/
@Data
public class TaskRecord {
/** 主键ID,自增 */
@TableId(type = IdType.AUTO)
private Long id;
/** 任务ID */
@ApiModelProperty(value = "任务ID")
private Long taskId;
/**
* @see TaskRecordEnum
* 记录内容(任务操作记录:创建任务-启动上传-暂停上传-上传完成-启动对码-暂停对码-对码完成) */
@ApiModelProperty(value = "记录内容(任务操作记录:创建任务-启动上传-暂停上传-上传完成-启动对码-暂停对码-对码完成)")
private String record;
/**
* @see TaskRecordTypeEnum
* 记录标识:0-普通、1-上传、2-对码 */
@ApiModelProperty(value = "记录标识:0-普通、1-上传、2-对码")
private Integer recordType;
/** 创建人id */
@ApiModelProperty(value = "创建人id")
private Long createBy;
/** 创建人 */
@ApiModelProperty(value = "创建人")
private Long creator;
/** 创建时间 */
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
}
package com.infynova.udi.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/2/22 16:42
* @version 1.0
*/
@Data
@ApiModel(value="udi", description="")
public class Udi implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "udi")
private String udiCode;
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
@ApiModelProperty(value = "企业名称")
private String companyName;
@ApiModelProperty(value = "品牌")
private String brandName;
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
@ApiModelProperty(value = "注册备案批准日期")
private LocalDate registryStartTime;
@ApiModelProperty(value = "注册备案有效期")
private LocalDate registryEndTime;
@ApiModelProperty(value = "注册备案人")
private String registry;
@ApiModelProperty(value = "产品编码")
private String productCode;
@ApiModelProperty(value = "厂家产品货号/编号")
private String productFactoryCode;
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
@ApiModelProperty(value = "单件产品名称")
private String productName;
@ApiModelProperty(value = "产品类型")
private String productType;
@ApiModelProperty(value = "规格")
private String specification;
@ApiModelProperty(value = "型号")
private String model;
@ApiModelProperty(value = "材质")
private String material;
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private Boolean asepticPackaging;
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private Boolean beforeSterilize;
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
@ApiModelProperty(value = "药监外部id")
private String yjForeignId;
@ApiModelProperty(value = "医保外部id")
private String ybForeignId;
@ApiModelProperty(value = "创建来源")
private String sourceName;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
@ApiModelProperty(value = "修改时间")
private LocalDateTime updateTime;
@ApiModelProperty(value = "版本号")
private String version;
}
package com.infynova.udi.enums;
/**
* @author liudong
* 2023/4/7 14:01
* @version 1.0
*/
public interface UdiEnum {
/**
* 获取code
*/
public Integer getCode();
/**
* 获取desc
*/
public String getDesc();
}
package com.infynova.udi.enums;
import java.util.Objects;
/**
* @author liudong
* 2023/4/7 14:33
* @version 1.0
*/
public class UdiEnumUtils {
/**
* code是否存在
*/
public static <T extends UdiEnum> Boolean existsCode(Class<T> enumClass, Integer codeValue) {
for (T enumObj : enumClass.getEnumConstants()) {
if (Objects.equals(enumObj.getCode(),codeValue)) {
return true;
}
}
return false;
}
/**
* desc是否存在
*/
public static <T extends UdiEnum> Boolean existsDesc(Class<T> enumClass, String descValue) {
for (T enumObj : enumClass.getEnumConstants()) {
if (Objects.equals(enumObj.getDesc(),descValue)) {
return true;
}
}
return false;
}
/**
* 根据code获取desc
*/
public static <T extends UdiEnum> String getDescByCode(Class<T> enumClass, Integer codeValue) {
for (T enumObj : enumClass.getEnumConstants()) {
if (Objects.equals(enumObj.getCode(),codeValue)) {
return enumObj.getDesc();
}
}
return null;
}
/**
* 根据desc获取code
*/
public static <T extends UdiEnum> Integer getCodeByDesc(Class<T> enumClass, String descValue) {
for (T enumObj : enumClass.getEnumConstants()) {
if (Objects.equals(enumObj.getDesc(),descValue)) {
return enumObj.getCode();
}
}
return null;
}
}
package com.infynova.udi.enums.match;
import com.infynova.udi.enums.UdiEnum;
/**
* 任务对码状态枚举
* @author liudong
* @version 1.0
* 2024-03-04 16:15
*/
public enum MatchStatusEnum implements UdiEnum {
// 对码状态:0-未开始、10-部分对码、20-100%对码、99-完全未对码
WAITING(0, "未开始"),
SECTION(10, "部分对码"),
HUNDRED(20, "100%对码"),
NO(99, "完全未对码"),
;
private final Integer code;
private final String desc;
private MatchStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
package com.infynova.udi.enums.match;
import com.infynova.udi.enums.UdiEnum;
/**
* 处理状态状态枚举
* @author liudong
* @version 1.0
* 2024-03-13 16:15
*/
public enum MatchUpdateStatusEnum implements UdiEnum {
// 处理状态:0-待处理、10-处理中、44-无需处理、100-已处理
PENDING(0, "待处理"),
IN_PROGRESS(10, "处理中"),
NOT_APPLICABLE(44, "无需处理"),
PROCESSED(100, "已处理"),
;
private final Integer code;
private final String desc;
private MatchUpdateStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
package com.infynova.udi.enums.task;
import com.infynova.udi.enums.UdiEnum;
/**
* 任务对码状态枚举
* @author liudong
* @version 1.0
* 2024-02-29 16:15
*/
public enum TaskMatchStatusEnum implements UdiEnum {
// 对码状态:0-待对码、10-对码中、99-已对码
WAITING(0, "待对码"),
MATCHING(10, "对码中"),
FINISH(99, "已对码"),
;
private final Integer code;
private final String desc;
private TaskMatchStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
package com.infynova.udi.enums.task;
import com.infynova.udi.enums.UdiEnum;
/**
* 记录标识:0-普通、1-上传、2-对码
* @author liudong
* @version 1.0
* 2024-02-29 16:15
*/
public enum TaskRecordEnum implements UdiEnum {
//
IMPORT_BUILD(0, "导入-创建任务"),
UPLOAD_START(1, "启动上传"),
UPLOAD_PAUSE(2, "暂停上传"),
UPLOAD_FINISH(3, "上传完成"),
MATCH_START(4, "启动对码"),
MATCH_PAUSE(5, "暂停对码"),
MATCH_FINISH(6, "对码完成"),
DELETE(99, "删除任务"),
;
private final Integer code;
private final String desc;
private TaskRecordEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
package com.infynova.udi.enums.task;
import com.infynova.udi.enums.UdiEnum;
/**
* 记录标识:0-普通、1-上传、2-对码
* @author liudong
* @version 1.0
* 2024-02-29 16:15
*/
public enum TaskRecordTypeEnum implements UdiEnum {
// 0-新建、10-上传中、11-暂停、20-完毕
DEFAULT(0, "普通"),
UPLOAD(1, "上传"),
MATCH(2, "对码"),
;
private final Integer code;
private final String desc;
private TaskRecordTypeEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
package com.infynova.udi.enums.task;
import com.infynova.udi.enums.UdiEnum;
import java.util.Objects;
/**
* 任务状态枚举
* @author liudong
* @version 1.0
* 2024-02-29 16:15
*/
public enum TaskStatusEnum implements UdiEnum {
// 0-新建、10-上传中、11-暂停、20-完毕
NEW_TASK(0, "新建"),
UPLOADING(10, "上传中"),
PAUSE(11, "暂停"),
FINISH(20, "完毕"),
DELETE(99, "删除"),
;
private final Integer code;
private final String desc;
private TaskStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
/**
* 获取code
*/
@Override
public Integer getCode() {
return this.code;
}
/**
* 获取desc
*/
@Override
public String getDesc() {
return this.desc;
}
}
/*
* Copyright [2021] [SaasPlatform ]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.infynova.udi.exception;
import com.infynova.common.core.api.ServiceCode;
/**
* @author zoupx
* @email
* @date 2020-03-30 17:33
* @description: WEB 异常码
*/
public enum CommonExceptionCode implements ServiceCode {
SYSTEM_500(500, "未知异常,请联系管理员"),
SYSTEM_501(500, "入参错误或入参不全"),
SYSTEM_502(502, "服务调用异常"),
SYSTEM_503(504, "服务调用超时"),
SYSTEM_400(400, "请求错误"),
SYSTEM_401(401, "token失效,请重新登录。"),
SYSTEM_403(403, "接口未授权,请联系管理员"),
SYSTEM_404(404, "路径不存在,请检查路径是否正确"),
SYSTEM_405(405, "请求方式错误"),
SYSTEM_406(406, "已存在下级组织,禁止删除"),
SYSTEM_409(409, "添加的数据已存在,禁止重复添加!"),
SYSTEM_412(412, "不满足条件,禁止添加!"),
SYSTEM_416(416, "已达到添加上限,禁止添加下一层级!"),
SYSTEM_417(417, "token为空,请重新登录!"),
SYSTEM_460(46012, "上传文件太大。"),
SYSTEM_480(48010, "数据重复。"),
SENTINEL_FLOW(429, "操作过于频繁稍后重试 [Sentinel]"),
SENTINEL_DEGRADE_FLOW(430, "服务降级,请稍后重试 [Sentinel]"),
SENTINEL_PARAM_FLOW(431, "参数访问过于频繁,请稍后重试 [Sentinel]"),
SENTINEL_SYSTEM_BLOCK(432, "系统异常,繁稍后重试 [Sentinel]"),
SENTINEL_AUTHORITY(433, "服务授权异常,稍后重试 [Sentinel]"),
JWT_TOKEN_EXPIRED(401031, "token已失效,请重新登录"),
JWT_SIGNATURE(401032, "token签名错误,请重新登录"),
JWT_ILLEGAL_ARGUMENT(401033, "token为空,请重新登录"),
JWT_PARSER_TOKEN_FAIL(401034, "token解析失败,请重新登录"),
TENANT_AUTH_NULL(701, "租户未开通此端权限"),
OPT_ERROR(702, "演示环境不可操作"),
NO_OPEN_PERMISSION(703, "该账户尚未开通任何权限"),
HTTP_REQUEST_ERROR(405011, "请求方式错误"),
;
private int code;
private String msg;
CommonExceptionCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override
public int getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
public void setCode(int code) {
this.code = code;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.infynova.udi.exception;
import com.infynova.common.core.api.ServiceCode;
/**
* @author liudong
* 2022/12/21 20:00
*/
public class UdiCodeException extends RuntimeException {
private ServiceCode code;
public ServiceCode getCode() {
return code;
}
public UdiCodeException(ServiceCode code) {
super(code.getMsg());
this.code = code;
}
public UdiCodeException(int code,String msg){
this.code = new ServiceCode() {
/**
* 响应编码
*/
@Override
public int getCode() {
return code;
}
/**
* 响应描述
*/
@Override
public String getMsg() {
return msg;
}
};
}
}
package com.infynova.udi.exception;
import com.infynova.common.core.api.ResponseData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
@Slf4j
@Order(value = 1)
@RestControllerAdvice
public class UdiExceptionHandler {
/**
* 验证异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseData handlerNoFoundException(MethodArgumentNotValidException e, HttpServletResponse response) {
response.setStatus(200);
return ResponseData.error(CommonExceptionCode.SYSTEM_501.getCode(), Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
}
/**
* 验证异常get
*/
@ExceptionHandler(BindException.class)
public ResponseData handlerNoFoundGetException(BindException e, HttpServletResponse response) {
response.setStatus(200);
return ResponseData.error(CommonExceptionCode.SYSTEM_501.getCode(), Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
}
/**
* 业务异常
*/
@ExceptionHandler(UdiCodeException.class)
public ResponseData handlerNoFoundException(UdiCodeException e, HttpServletResponse response) {
response.setStatus(200);
return ResponseData.error(e.getCode());
}
}
package com.infynova.udi.helper;
import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.List;
/**
* @author liudong
* 2023/11/6 19:09
* @version 1.0
*/
@Slf4j
@Component("udiEasyExcelHelper")
public class UdiEasyExcelHelper {
public static <T> void exportTemplate(String name, Class<T> entity) throws IOException {
List<T> list = Collections.emptyList();
export(name, list, entity);
}
public static <T> void export(String name, List<T> list, Class<T> entity) throws IOException {
String sheetName = name;
export(name, sheetName, list, entity);
}
public static <T> void export(String name, String sheetName, List<T> list, Class<T> entity) throws IOException {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
export(response,name,sheetName,list,entity);
}
public static <T> void export(HttpServletResponse response,String name,String sheetName, List<T> list, Class<T> entity) throws IOException {
log.info("导出excel~");
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode(name, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), entity)
.sheet(sheetName)
.doWrite(list);
}
}
package com.infynova.udi.helper.validator;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Arrays;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 枚举值自定义校验
* 2023/4/2 12:06
* @author derTraum
* @since 1.0.0
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueValidator.EnumValidator.class})
public @interface EnumValueValidator {
String message() default "FixedValue's value is invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<? extends Enum<?>> enumClass();
class EnumValidator implements ConstraintValidator<EnumValueValidator, Object> {
private EnumValueValidator annotation;
@Override
public void initialize(EnumValueValidator constraintAnnotation) {
this.annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
if (o == null) {
return true; // 允许为空
}
Enum<?>[] enumValues = annotation.enumClass().getEnumConstants();
return Arrays.asList(enumValues).contains(o);
}
}
}
package com.infynova.udi.helper.validator;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 入参自定义值校验
* 2023/4/2 12:05
* @author derTraum
* @since 1.0.0
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {FixedValueValidator.FixedValueValid.class})
public @interface FixedValueValidator {
String message() default "FixedValue's value is invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] fixedValue();
class FixedValueValid implements ConstraintValidator<FixedValueValidator, Object> {
String[] fixedValue = null;
public void initialize(FixedValueValidator validData) {
this.fixedValue = validData.fixedValue();
}
public boolean isValid(Object value, ConstraintValidatorContext constraintContext) {
if (fixedValue == null || fixedValue.length == 0 ) {
return false;
}
if (value == null) {
return true;
}
boolean flag = false;
for (String str : fixedValue) {
if (String.valueOf(value).equals(String.valueOf(str))) {
flag = true;
break;
}
}
return flag;
}
}
}
package com.infynova.udi.utils;
import java.util.Objects;
/**
* @author liudong
* 2023/4/7 14:33
* @version 1.0
*/
public class BooleanValueUtils {
public static String getBooleanValue(Boolean value){
if(Objects.isNull(value)){
return "";
}
return value?"是":"否";
}
public static Boolean getBoolean(String item){
if(Objects.isNull(item)){
return null;
}
switch (item){
case "是":
return true;
case "否":
return false;
default:
return null;
}
}
public static Integer getBooleanInt(Boolean value){
if(Objects.isNull(value)){
return null;
}
return value?1:0;
}
}
package com.infynova.udi.vo;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author liudong
* 2024/3/12 12:03
* @version 1.0
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class CommonEnumList {
/**
* @see TaskStatusEnum
* 任务上传状态:0-新建、10-上传中、11-暂停、20-完毕
*/
@ApiModelProperty(value = "任务上传状态:0-新建、10-上传中、11-暂停、20-完毕")
private List<enumValue> taskStatus;
/**
* @see TaskMatchStatusEnum
* 对码状态:对码状态:0-待对码、10-对码中、99-已对码
*/
@ApiModelProperty(value = "对码状态:对码状态:0-待对码、10-对码中、99-已对码")
private List<enumValue> taskMatchStatus;
/**
* 对码状态:0-未开始、10-部分对码、20-100%对码、99-完全未对码
* @see MatchStatusEnum
*/
@ApiModelProperty(value = "对码状态:0-未开始 10-部分对码、20-100%对码、99-完全未对码")
private List<enumValue> matchStatus;
/**
* 处理状态:0-待处理、10-处理中、44-无需处理、100-已处理
* @see MatchUpdateStatusEnum
*/
@ApiModelProperty(value = "处理状态:0-待处理、10-处理中、44-无需处理、100-已处理")
private List<enumValue> updateStatus;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public static class enumValue{
private Integer code;
private String value;
}
}
package com.infynova.udi.vo;
import com.infynova.common.core.api.BaseVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author liudong
* 2024/2/29 16:18
* @version 1.0
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class TaskMatchStatisticVo extends BaseVo {
@ApiModelProperty(value = "任务id")
private Long taskId;
@ApiModelProperty(value = "任务编码")
private String taskNo;
@ApiModelProperty(value = "总数据")
private Integer total = 0;
@ApiModelProperty(value = "待上传")
private Integer uploadWaiting = 0;
@ApiModelProperty(value = "已上传")
private Integer uploadFinish = 0;
@ApiModelProperty(value = "100%对码")
private Integer hundred = 0;
@ApiModelProperty(value = "部分对码")
private Integer section = 0;
@ApiModelProperty(value = "完全未对码")
private Integer never = 0;
@ApiModelProperty(value = "待对码")
private Integer waiting = 0;
}
package com.infynova.udi.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liudong
* 2024/2/29 14:28
* @version 1.0
*/
@Data
public class TaskUdiExcelExportVo extends TaskUdiExcelVo {
@ExcelProperty(value = "结果",order = 0)
@ColumnWidth(20)
@ApiModelProperty(value = "结果")
private String result;
}
package com.infynova.udi.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author liudong
* 2024/2/29 14:28
* @version 1.0
*/
@Data
public class TaskUdiExcelImportVo extends TaskUdiExcelVo {
}
package com.infynova.udi.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/2/29 14:16
* @version 1.0
*/
@Data
public class TaskUdiExcelVo {
// DI码、医保一级编码、医保二级编码、医保编码、医保编码前缀、
@ExcelProperty(value = "DI码",order = 0)
@ColumnWidth(20)
@ApiModelProperty(value = "udi")
private String udiCode;
@ExcelProperty(value = "医保一级编码",order = 1)
@ColumnWidth(20)
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
@ExcelProperty(value = "医保二级编码",order = 2)
@ColumnWidth(20)
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
@ExcelProperty(value = "医保编码",order = 3)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
@ExcelProperty(value = "医保编码前缀",order = 4)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
// 企业名称、品牌、注册备案号、注册备案产品名称、注册备案批准日期、注册备案有效期、注册备案人、
@ExcelProperty(value = "企业名称",order = 5)
@ColumnWidth(20)
@ApiModelProperty(value = "企业名称")
private String companyName;
@ExcelProperty(value = "品牌",order = 6)
@ColumnWidth(20)
@ApiModelProperty(value = "品牌")
private String brandName;
@ExcelProperty(value = "注册备案号",order = 7)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
@ExcelProperty(value = "注册备案产品名称",order = 8)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
@ExcelProperty(value = "注册备案批准日期",order = 9)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案批准日期")
private String registryStartTime;
@ExcelProperty(value = "注册备案有效期",order = 10)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案有效期")
private String registryEndTime;
@ExcelProperty(value = "注册备案人",order = 11)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案人")
private String registry;
// 产品编码、厂家产品货号/编号、无境UDI库分配编码、单件产品名称、产品类型、规格、型号、材质、是否为无菌包装、使用前是否需要进行灭菌、灭菌方式;
@ExcelProperty(value = "产品编码",order = 12)
@ColumnWidth(20)
@ApiModelProperty(value = "产品编码")
private String productCode;
@ExcelProperty(value = "厂家产品货号/编号",order = 13)
@ColumnWidth(20)
@ApiModelProperty(value = "厂家产品货号/编号")
private String productFactoryCode;
// @ExcelProperty(value = "无境UDI库分配编码",order = 14)
// @ColumnWidth(20)
// @ApiModelProperty(value = "无境UDI库分配编码")
// private String infynovaCode;
@ExcelProperty(value = "单件产品名称",order = 15)
@ColumnWidth(20)
@ApiModelProperty(value = "单件产品名称")
private String productName;
@ExcelProperty(value = "产品类型",order = 16)
@ColumnWidth(20)
@ApiModelProperty(value = "产品类型")
private String productType;
@ExcelProperty(value = "规格",order = 17)
@ColumnWidth(20)
@ApiModelProperty(value = "规格")
private String specification;
@ExcelProperty(value = "型号",order = 18)
@ColumnWidth(20)
@ApiModelProperty(value = "型号")
private String model;
@ExcelProperty(value = "材质",order = 19)
@ColumnWidth(20)
@ApiModelProperty(value = "材质")
private String material;
@ExcelProperty(value = "是否为无菌包装",order = 20)
@ColumnWidth(20)
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private String asepticPackaging;
@ExcelProperty(value = "使用前是否需要进行灭菌",order = 21)
@ColumnWidth(20)
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private String beforeSterilize;
@ExcelProperty(value = "灭菌方式",order = 22)
@ColumnWidth(20)
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
}
package com.infynova.udi.vo;
import com.infynova.udi.entity.Task;
import com.infynova.udi.entity.TaskRecord;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author liudong
* 2024/2/29 16:18
* @version 1.0
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class TaskVo {
private Task task;
private List<TaskRecord> taskRecordList;
}
package com.infynova.udi.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.infynova.common.core.api.BaseVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liudong
* 2024/2/22 17:17
* @version 1.0
*/
@Data
public class UdiExportVo extends BaseVo {
@ExcelProperty(value = "DI码",order = 0)
@ColumnWidth(20)
@ApiModelProperty(value = "udi")
private String udiCode;
@ExcelProperty(value = "医保一级编码",order = 1)
@ColumnWidth(20)
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
@ExcelProperty(value = "医保二级编码",order = 2)
@ColumnWidth(20)
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
@ExcelProperty(value = "医保编码",order = 3)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
@ExcelProperty(value = "医保编码前缀",order = 4)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
@ExcelProperty(value = "企业名称",order = 5)
@ColumnWidth(20)
@ApiModelProperty(value = "企业名称")
private String companyName;
@ExcelProperty(value = "品牌",order = 6)
@ColumnWidth(20)
@ApiModelProperty(value = "品牌")
private String brandName;
@ExcelProperty(value = "注册备案号",order = 7)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
@ExcelProperty(value = "注册备案产品名称",order = 8)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
@ExcelProperty(value = "注册备案批准日期",order = 9)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案批准日期")
private String registryStartTime;
@ExcelProperty(value = "注册备案有效期",order = 10)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案有效期")
private String registryEndTime;
@ExcelProperty(value = "注册备案人",order = 11)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案人")
private String registry;
@ExcelProperty(value = "产品编码",order = 12)
@ColumnWidth(20)
@ApiModelProperty(value = "产品编码")
private String productCode;
@ExcelProperty(value = "厂家产品货号/编号",order = 13)
@ColumnWidth(20)
@ApiModelProperty(value = "厂家产品货号/编号")
private String productFactoryCode;
@ExcelProperty(value = "无境UDI库分配编码",order = 14)
@ColumnWidth(20)
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
@ExcelProperty(value = "单件产品名称",order = 15)
@ColumnWidth(20)
@ApiModelProperty(value = "单件产品名称")
private String productName;
@ExcelProperty(value = "产品类型",order = 16)
@ColumnWidth(20)
@ApiModelProperty(value = "产品类型")
private String productType;
@ExcelProperty(value = "规格",order = 17)
@ColumnWidth(20)
@ApiModelProperty(value = "规格")
private String specification;
@ExcelProperty(value = "型号",order = 18)
@ColumnWidth(20)
@ApiModelProperty(value = "型号")
private String model;
@ExcelProperty(value = "材质",order = 19)
@ColumnWidth(20)
@ApiModelProperty(value = "材质")
private String material;
@ExcelProperty(value = "是否为无菌包装",order = 20)
@ColumnWidth(20)
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private String asepticPackaging;
@ExcelProperty(value = "使用前是否需要进行灭菌",order = 21)
@ColumnWidth(20)
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private String beforeSterilize;
@ExcelProperty(value = "灭菌方式",order = 22)
@ColumnWidth(20)
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
}
package com.infynova.udi.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.infynova.common.core.api.BaseVo;
import com.infynova.udi.enums.match.MatchStatusEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/2/22 19:11
* @version 1.0
*/
@Data
public class UdiMatchDataExportVo extends BaseVo {
@ExcelProperty(value = "任务编码",order = 0)
@ColumnWidth(20)
@ApiModelProperty(value = "任务编码")
private String taskNo;
/**
* 对码状态:0-未开始、10-部分对码、20-100%对码、99-完全未对码
* @see MatchStatusEnum
*/
@ExcelIgnore
@ApiModelProperty(value = "对码状态:0-未开始 10-部分对码、20-100%对码、99-完全未对码")
private Integer matchStatus;
@ExcelProperty(value = "对码状态",order = 2)
@ColumnWidth(20)
@ApiModelProperty(value = "对码状态名称")
private String matchStatusDesc;
/** udi码 */
@ExcelProperty(value = "DI码",order = 1)
@ColumnWidth(20)
@ApiModelProperty(value = "udi码")
private String udiCode;
/** 医保一级编码 */
@ExcelProperty(value = "医保一级编码",order = 3)
@ColumnWidth(20)
@ApiModelProperty(value = "医保一级编码")
private String yiBaoOneCode;
/** 医保二级编码 */
@ExcelProperty(value = "医保二级编码",order = 4)
@ColumnWidth(20)
@ApiModelProperty(value = "医保二级编码")
private String yiBaoTwoCode;
/** 医保编码 */
@ExcelProperty(value = "医保编码",order = 5)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码")
private String yiBaoCode;
/** 医保编码前缀 */
@ExcelProperty(value = "医保编码前缀",order = 6)
@ColumnWidth(20)
@ApiModelProperty(value = "医保编码前缀")
private String yiBaoCodePrefix;
/** 企业名称 */
@ExcelProperty(value = "企业名称",order = 7)
@ColumnWidth(20)
@ApiModelProperty(value = "企业名称")
private String companyName;
/** 品牌 */
@ExcelProperty(value = "品牌",order = 8)
@ColumnWidth(20)
@ApiModelProperty(value = "品牌")
private String brandName;
/** 注册备案号(注册证) */
@ExcelProperty(value = "注册备案号",order = 9)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案号(注册证)")
private String registryNo;
/** 注册备案产品名称 */
@ExcelProperty(value = "注册备案产品名称",order = 10)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案产品名称")
private String registryName;
/** 注册备案批准日期 */
@ExcelProperty(value = "注册备案批准日期",order = 11)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案批准日期")
private LocalDateTime registryStartTime;
/** 注册备案有效期 */
@ExcelProperty(value = "注册备案有效期",order = 12)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案有效期")
private LocalDateTime registryEndTime;
/** 注册备案人 */
@ExcelProperty(value = "注册备案人",order = 13)
@ColumnWidth(20)
@ApiModelProperty(value = "注册备案人")
private String registry;
/** 产品编码 */
@ExcelProperty(value = "产品编码",order = 14)
@ColumnWidth(20)
@ApiModelProperty(value = "产品编码")
private String productCode;
/** 厂家产品货号或编号 */
@ExcelProperty(value = "厂家产品货号/编号",order = 15)
@ColumnWidth(20)
@ApiModelProperty(value = "厂家产品货号或编号")
private String productFactoryCode;
/** 无境UDI库分配编码 */
@ExcelIgnore
@ApiModelProperty(value = "无境UDI库分配编码")
private String infynovaCode;
/** 单件产品名称 */
@ExcelProperty(value = "单件产品名称",order = 16)
@ColumnWidth(20)
@ApiModelProperty(value = "单件产品名称")
private String productName;
/** 产品类型 */
@ExcelProperty(value = "产品类型",order = 17)
@ColumnWidth(20)
@ApiModelProperty(value = "产品类型")
private String productType;
/** 规格 */
@ExcelProperty(value = "规格",order = 18)
@ColumnWidth(20)
@ApiModelProperty(value = "规格")
private String specification;
/** 型号 */
@ExcelProperty(value = "型号",order = 19)
@ColumnWidth(20)
@ApiModelProperty(value = "型号")
private String model;
/** 材质 */
@ExcelProperty(value = "材质",order = 20)
@ColumnWidth(20)
@ApiModelProperty(value = "材质")
private String material;
/** 是否为无菌包装 0:否 1:是 */
@ExcelIgnore
@ApiModelProperty(value = "是否为无菌包装 0:否 1:是")
private Boolean asepticPackaging;
@ExcelProperty(value = "是否为无菌包装",order = 21)
@ColumnWidth(20)
@ApiModelProperty(value = "是否为无菌包装")
private String asepticPackagingDesc;
/** 使用前是否需要进行灭菌 0:否 1:是 */
@ExcelIgnore
@ApiModelProperty(value = "使用前是否需要进行灭菌 0:否 1:是")
private Boolean beforeSterilize;
@ExcelProperty(value = "使用前是否需要进行灭菌",order = 22)
@ColumnWidth(20)
@ApiModelProperty(value = "使用前是否需要进行灭菌")
private String beforeSterilizeDesc;
/** 灭菌方式 */
@ExcelProperty(value = "灭菌方式",order = 23)
@ColumnWidth(20)
@ApiModelProperty(value = "灭菌方式")
private String sterilizationMethod;
}
package com.infynova.udi.vo;
import com.infynova.udi.entity.MatchData;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liudong
* 2024/2/22 19:11
* @version 1.0
*/
@Data
public class UdiMatchDataVo extends MatchData {
}
package com.infynova.udi.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author liudong
* 2024/2/22 17:58
* @version 1.0
*/
@Data
public class UdiMatchListVo {
private Long id;
@ApiModelProperty(value = "任务编号")
private String taskNo;
@ApiModelProperty(value = "任务上传状态:0-新建、10-上传中、11-暂停、20-完毕")
private Integer taskStatus;
@ApiModelProperty(value = "任务上传状态:0-新建、10-上传中、11-暂停、20-完毕")
private String taskStatusDesc;
@ApiModelProperty(value = "大小")
private String taskFileSize;
@ApiModelProperty(value = "大小-转换展示")
private String taskFileSizeDesc;
@ApiModelProperty(value = "数据量")
private Integer taskFileCount;
@ApiModelProperty(value = "上传的数据量")
private Integer taskUploadNum;
@ApiModelProperty(value = "上传文件地址")
private String taskFileAddress;
@ApiModelProperty(value = "上传文件id - 获取地址用")
private Long taskFileId;
@ApiModelProperty(value = "上传耗时")
private Integer uploadTime;
@ApiModelProperty(value = "上传耗时-展示")
private String uploadTimeDesc;
@ApiModelProperty(value = "对码状态:对码状态:0-待对码、10-对码中、99-已对码")
private Integer taskMatchStatus;
@ApiModelProperty(value = "对码状态:对码状态:0-待对码、10-对码中、99-已对码")
private String taskMatchStatusDesc;
@ApiModelProperty(value = "对码耗时")
private Integer matchTime;
@ApiModelProperty(value = "对码耗时-展示")
private String matchTimeDesc;
@ApiModelProperty(value = "上传时间")
private String createTime;
@ApiModelProperty(value = "操作人")
private String operator;
@ApiModelProperty(value = "版本号")
private Integer version;
}
package com.infynova.udi.vo;
import com.infynova.udi.entity.Udi;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @author liudong
* 2024/2/22 17:16
* @version 1.0
*/
@Data
public class UdiMatchRateVo extends Udi {
@ApiModelProperty(value = "匹配率")
private BigDecimal matchRatio;
@ApiModelProperty(value = "输入值")
private String userItem;
}
package com.infynova.udi.vo;
import com.infynova.udi.entity.Udi;
/**
* @author liudong
* 2024/2/22 17:16
* @version 1.0
*/
public class UdiVo extends Udi {
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>saas-udi</artifactId>
<groupId>com.infynova</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>saas-udi-service</artifactId>
<properties>
<jetcache.version>2.6.2</jetcache.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.infynova</groupId>
<artifactId>saas-udi-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>${jetcache.version}</version>
</dependency>
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.7.0</version>
</dependency>
<!-- ikAnalyzer 中文分词器 -->
<dependency>
<groupId>com.janeluo</groupId>
<artifactId>ikanalyzer</artifactId>
<version>2012_u6</version>
<exclusions>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- lucene-queryParser 查询分析器模块 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>7.3.0</version>
</dependency>
<!-- sqlite jdbc 驱动 -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.1.0</version>
</dependency>
<dependency>
<groupId>com.redislabs</groupId>
<artifactId>jredisearch</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.12.0</version>
</dependency>
<!-- elasticsearch 的客户端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.0</version>
</dependency>
<!-- elasticsearch 依赖 2.x 的 log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<dependency>
<groupId>com.infynova</groupId>
<artifactId>saas-ucpm-api</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/../libs/saas-ucpm-api-1.0.0.jar</systemPath>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--跳过测试-->
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.infynova.udi;
import com.alicp.jetcache.anno.config.EnableMethodCache;
import com.infynova.udi.constant.UdiConstant;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@Slf4j
@EnableAsync
@EnableScheduling
@EnableConfigurationProperties
@EnableFeignClients(basePackages = {UdiConstant.INFYNOVA_PACKAGE_NAME})
@EnableDiscoveryClient
@MapperScan(UdiConstant.MAPPER_PACKAGE_NAME)
@EnableMethodCache(basePackages = {UdiConstant.UDI_PACKAGE_NAME})
@SpringBootApplication(scanBasePackages = {"com.infynova.udi"})
public class UdiApplication {
public static void main(String[] args) {
SpringApplication.run(UdiApplication.class, args);
}
}
package com.infynova.udi.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infynova.common.core.api.ResponseData;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import com.infynova.udi.vo.CommonEnumList;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author liudong
* 2024/3/12 12:01
* @version 1.0
*/
@Slf4j
@Api(tags = "对码平台-公共接口")
@ApiSupport(order = 1)
@RestController
@RequestMapping("/common")
public class CommonController {
@ApiOperationSupport(order = 100)
@ApiOperation(value = "获取枚举", notes = "获取枚举")
@GetMapping("getEnumList")
public ResponseData<CommonEnumList> getEnumList(){
log.info("getEnumList");
return ResponseData.ok(this.get());
}
private CommonEnumList get(){
List<CommonEnumList.enumValue> taskStatus = new ArrayList<>();
for (TaskStatusEnum value : TaskStatusEnum.values()) {
CommonEnumList.enumValue enumValue = CommonEnumList.enumValue.builder().code(value.getCode()).value(value.getDesc()).build();
taskStatus.add(enumValue);
}
List<CommonEnumList.enumValue> taskMatchStatus = new ArrayList<>();
for (TaskMatchStatusEnum value : TaskMatchStatusEnum.values()) {
CommonEnumList.enumValue enumValue = CommonEnumList.enumValue.builder().code(value.getCode()).value(value.getDesc()).build();
taskMatchStatus.add(enumValue);
}
List<CommonEnumList.enumValue> matchStatus = new ArrayList<>();
for (MatchStatusEnum value : MatchStatusEnum.values()) {
CommonEnumList.enumValue enumValue = CommonEnumList.enumValue.builder().code(value.getCode()).value(value.getDesc()).build();
matchStatus.add(enumValue);
}
List<CommonEnumList.enumValue> updateStatus = new ArrayList<>();
for (MatchUpdateStatusEnum value : MatchUpdateStatusEnum.values()) {
CommonEnumList.enumValue enumValue = CommonEnumList.enumValue.builder().code(value.getCode()).value(value.getDesc()).build();
updateStatus.add(enumValue);
}
return CommonEnumList.builder()
.taskStatus(taskStatus)
.taskMatchStatus(taskMatchStatus)
.matchStatus(matchStatus)
.updateStatus(updateStatus)
.build();
}
}
package com.infynova.udi.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infynova.common.core.api.ResponseData;
import com.infynova.udi.dto.UdiListQry;
import com.infynova.udi.helper.UdiEasyExcelHelper;
import com.infynova.udi.service.UdiService;
import com.infynova.udi.service.helper.EsSearchHelper;
import com.infynova.udi.service.helper.RedisSearchHelper;
import com.infynova.udi.service.helper.RedisSearchIndexer;
import com.infynova.udi.vo.UdiExportVo;
import com.infynova.udi.vo.UdiVo;
import io.redisearch.SearchResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Api(tags = "udi查询")
@ApiSupport(order = 100)
@RestController
@RequestMapping("/udiList")
public class UdiController {
@Resource
private UdiService udiService;
private static final Integer MAX_EXPORT = 20000;
@ApiOperationSupport(order = 100)
@ApiOperation(value = "udi查询列表", notes = "udi查询列表")
@PostMapping("list")
public ResponseData<Page<UdiVo>> list(@RequestBody UdiListQry udiListQry){
log.info("list:"+ JSON.toJSONString(udiListQry));
return ResponseData.ok(udiService.getUdiPage(udiListQry));
}
@ApiOperationSupport(order = 101)
@ApiOperation(value = "导出udi查询列表", notes = "导出udi查询列表")
@PostMapping("export")
public void export(@RequestBody UdiListQry udiListQry) throws IOException {
log.info("export:"+ JSON.toJSONString(udiListQry));
// 如何大量导出避免内存溢出 todo
udiListQry.setPageSize(MAX_EXPORT);
Page<UdiVo> udiPage = udiService.getUdiPage(udiListQry);
List<UdiExportVo> udiExportVos = new ArrayList<>();
for (UdiVo record : udiPage.getRecords()) {
UdiExportVo udiExportVo = new UdiExportVo();
BeanUtils.copyProperties(record, udiExportVo);
udiExportVos.add(udiExportVo);
}
UdiEasyExcelHelper.export("udi查询导出列表", udiExportVos, UdiExportVo.class);
}
@Resource
private RedisSearchIndexer redisSearchIndexer;
@Resource
private RedisSearchHelper redisSearchHelper;
@Resource
private EsSearchHelper esSearchHelper;
@ApiOperationSupport(order = 200)
@ApiOperation(value = "createIndex", notes = "createIndex",hidden = true)
@PostMapping("createIndex")
public void createIndex(){
//redisSearchIndexer.createIndex();
esSearchHelper.createIndex();
}
@ApiOperationSupport(order = 200)
@ApiOperation(value = "deleteIndex", notes = "deleteIndex",hidden = true)
@PostMapping("deleteIndex")
public void deleteIndex(){
//redisSearchIndexer.deleteIndex();
esSearchHelper.deleteIndex();
}
@ApiOperationSupport(order = 200)
@ApiOperation(value = "initData", notes = "initData",hidden = true)
@PostMapping("initData")
public void initData(){
//redisSearchIndexer.initData();
esSearchHelper.initData();
}
@ApiOperationSupport(order = 200)
@ApiOperation(value = "searchThree", notes = "searchThree",hidden = true)
@PostMapping("searchThree")
public SearchResult searchThree(@RequestParam(value = "companyName", required = false) String companyName,
@RequestParam(value = "productFactoryCode", required = false) String productFactoryCode){
return redisSearchHelper.searchThree(companyName,productFactoryCode);
}
}
package com.infynova.udi.controller;
import com.alibaba.fastjson.JSON;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infynova.common.core.api.ResponseData;
import com.infynova.udi.dto.*;
import com.infynova.udi.service.helper.IKAnalyzerSupport;
import com.infynova.udi.service.helper.MatchHelper;
import com.infynova.udi.service.helper.TaskHelper;
import com.infynova.udi.service.helper.TaskUploadHelper;
import com.infynova.udi.vo.TaskVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Api(tags = "对码平台-辅助",hidden = true)
@ApiSupport(order = 400)
@RestController
@RequestMapping("/helper")
public class UdiHelperController {
@Resource
private MatchHelper matchHelper;
@ApiOperationSupport(order = 10000)
@ApiOperation(value = "测试对码匹配", notes = "测试对码匹配", hidden = true)
@GetMapping("tranMatchRate")
public ResponseData<?> tranMatchRate() {
log.info("tranMatchRate");
matchHelper.tranMatchRate();
return ResponseData.ok();
}
@ApiOperationSupport(order = 10000)
@ApiOperation(value = "测试分词器", notes = "测试分词器", hidden = true)
@GetMapping("splitWord")
public ResponseData<String> splitWord(@RequestParam(name = "word") String word) throws Exception {
log.info("splitWord:");
List<String> splitWord = IKAnalyzerSupport.iKSegmenterToList(word);
String result = splitWord.stream().map(String::valueOf).distinct().collect(Collectors.joining("|")) ;
return ResponseData.ok(result);
}
@Resource
private TaskUploadHelper taskUploadHelper;
@Resource
private TaskHelper taskHelper;
@ApiOperationSupport(order = 10000)
@ApiOperation(value = "测试转换数据", notes = "测试转换数据", hidden = true)
@PostMapping("testTranData")
public ResponseData<?> testTranData(@RequestBody @Valid IdQry idQry) {
log.info("testTranData:"+ JSON.toJSONString(idQry));
taskUploadHelper.tranUpload(idQry.getId());
return ResponseData.ok();
}
@ApiOperationSupport(order = 10001)
@ApiOperation(value = "获取任务数据", notes = "获取任务数据", hidden = true)
@PostMapping("getTaskVo")
public ResponseData<List<TaskVo>> getTaskVo(@RequestBody @Valid IdListQry idListQry) {
log.info("getTaskVo:"+ JSON.toJSONString(idListQry));
return ResponseData.ok(taskHelper.getTaskVoList(new ArrayList<>(idListQry.getIdList())));
}
@ApiOperationSupport(order = 10002)
@ApiOperation(value = "测试获取任务编码", notes = "测试获取任务编码", hidden = true)
@GetMapping("getTaskNo")
public ResponseData<String> getTaskNo() {
log.info("getTaskNo:");
return ResponseData.ok(taskHelper.getTaskNo());
}
}
package com.infynova.udi.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infynova.common.core.api.ResponseData;
import com.infynova.udi.dto.*;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.entity.MatchTemp;
import com.infynova.udi.helper.UdiEasyExcelHelper;
import com.infynova.udi.service.MatchDataService;
import com.infynova.udi.service.MatchTempService;
import com.infynova.udi.vo.UdiMatchDataExportVo;
import com.infynova.udi.vo.UdiMatchDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Api(tags = "对码平台-对码")
@ApiSupport(order = 300)
@RestController
@RequestMapping("/match/data")
public class UdiMatchDataController {
@Resource
private MatchDataService matchDataService;
@Resource
private MatchTempService matchTempService;
@ApiOperationSupport(order = 100)
@ApiOperation(value = "对码管理列表", notes = "对码管理列表")
@PostMapping("list")
public ResponseData<Page<UdiMatchDataVo>> list(@RequestBody @Valid UdiMatchDetailListQry udiMatchDetailListQry){
log.info("list:"+ JSON.toJSONString(udiMatchDetailListQry));
return ResponseData.ok(matchDataService.queryMatchDataPage(udiMatchDetailListQry));
}
@ApiOperationSupport(order = 120)
@ApiOperation(value = "导出对码管理列表", notes = "导出对码管理列表")
@PostMapping("export")
public void export(@RequestBody @Valid UdiMatchDetailListQry udiMatchDetailListQry) throws IOException {
log.info("export:"+ JSON.toJSONString(udiMatchDetailListQry));
udiMatchDetailListQry.setPageSize(-1);
Page<UdiMatchDataVo> page = matchDataService.queryMatchDataPage(udiMatchDetailListQry);
List<UdiMatchDataExportVo> exportList = new ArrayList<>();
for (UdiMatchDataVo record : page.getRecords()) {
UdiMatchDataExportVo exportVo = new UdiMatchDataExportVo();
BeanUtils.copyProperties(record,exportVo);
exportList.add(exportVo);
}
UdiEasyExcelHelper.export("udi查询导出列表", exportList, UdiMatchDataExportVo.class);
}
@ApiOperationSupport(order = 130)
@ApiOperation(value = "批量匹配UDI库", notes = "批量匹配UDI库")
@PostMapping("batchMatchUdi")
public ResponseData<Integer> batchMatchUdi(@RequestBody @Valid UdiBatchMatchQry udiBatchMatchQry){
log.info("batchMatchUdi:"+ JSON.toJSONString(udiBatchMatchQry));
return ResponseData.ok(matchDataService.batchMatchUdi(udiBatchMatchQry));
}
@ApiOperationSupport(order = 140)
@ApiOperation(value = "全量匹配UDI库", notes = "全量匹配UDI库")
@PostMapping("allMatchUdi")
public ResponseData<Integer> allMatchUdi(@RequestBody @Valid UdiAllMatchQry udiAllMatchQry){
// 该任务中部分未对码 全量匹配UDI库
log.info("allMatchUdi:"+ JSON.toJSONString(udiAllMatchQry));
return ResponseData.ok(matchDataService.allMatchUdi(udiAllMatchQry));
}
@ApiOperationSupport(order = 150)
@ApiOperation(value = "查询匹配数据", notes = "查询匹配数据")
@PostMapping("queryMatchTemp")
public ResponseData<List<MatchTemp>> queryMatchTemp(@RequestBody @Valid IdQry idQry){
// 该任务中部分未对码 全量匹配UDI库
log.info("queryMatchTemp:"+ JSON.toJSONString(idQry));
return ResponseData.ok(matchTempService.queryMatchTemp(idQry.getId()));
}
@ApiOperationSupport(order = 160)
@ApiOperation(value = "确认对码", notes = "确认对码")
@PostMapping("confirmationMatch")
public ResponseData<MatchData> confirmationMatch(@RequestBody @Valid UdiMatchConfirmationDto udiMatchConfirmationDto){
// 该任务中部分未对码 全量匹配UDI库
log.info("confirmationMatch:"+ JSON.toJSONString(udiMatchConfirmationDto));
return ResponseData.ok(matchDataService.confirmationMatch(udiMatchConfirmationDto));
}
}
package com.infynova.udi.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.infynova.common.core.api.ResponseData;
import com.infynova.udi.dto.*;
import com.infynova.udi.helper.UdiEasyExcelHelper;
import com.infynova.udi.service.TaskImportService;
import com.infynova.udi.service.TaskService;
import com.infynova.udi.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Slf4j
@Api(tags = "对码平台-任务")
@ApiSupport(order = 200)
@RestController
@RequestMapping("/match/task")
public class UdiMatchTaskController {
@Resource
private TaskService taskService;
@Resource
private TaskImportService taskImportService;
@ApiOperationSupport(order = 100)
@ApiOperation(value = "udi对码导入模板下载", notes = "udi对码导入模板下载")
@GetMapping("template")
public void template() throws IOException {
log.info("template");
TaskUdiExcelImportVo udiExcelVo = new TaskUdiExcelImportVo();
String example = "样例-";
udiExcelVo.setUdiCode(example + "6938954499349");
udiExcelVo.setYiBaoOneCode(example + "C03380310700000");
udiExcelVo.setYiBaoTwoCode(example + "C0338031070000001523");
udiExcelVo.setYiBaoCode(example + "C03380310700000015230000046");
udiExcelVo.setYiBaoCodePrefix(example + "C03");
udiExcelVo.setCompanyName(example + "深圳市无境创新有限公司");
udiExcelVo.setBrandName(example + "无境创新");
udiExcelVo.setRegistryNo(example + "国械注准20240000001");
udiExcelVo.setRegistryName(example + "人工踝关节假体");
udiExcelVo.setRegistryStartTime("2000-01-01");
udiExcelVo.setRegistryEndTime("2099-12-31");
udiExcelVo.setRegistry(example + "深圳市无境创新有限公司");
udiExcelVo.setProductCode(example + "infynova-DEMO-001");
udiExcelVo.setProductFactoryCode(example + "0116001");
//udiExcelVo.setInfynovaCode(example + );
udiExcelVo.setProductName(example + "人工踝关节假体-跟距骨假体QH型26×26×23");
udiExcelVo.setProductType("耗材");
udiExcelVo.setSpecification(example + "QH型 26×26×23");
udiExcelVo.setModel(example + "QH型 26×26×23");
udiExcelVo.setMaterial(example + "不区分");
udiExcelVo.setAsepticPackaging(example + "否");
udiExcelVo.setBeforeSterilize(example + "是");
udiExcelVo.setSterilizationMethod(example + "按照说明书要求进行灭菌");
UdiEasyExcelHelper.export("udi对码导入模板", Collections.singletonList(udiExcelVo), TaskUdiExcelImportVo.class);
}
@ApiOperationSupport(order = 110)
@ApiOperation(value = "udi对码导入", notes = "udi对码导入")
@PostMapping("importData")
public ResponseData<ImportItemResp> importData(@RequestParam("file") MultipartFile file) throws IOException {
log.info("importData");
return ResponseData.ok(taskImportService.importData(file));
}
@ApiOperationSupport(order = 120)
@ApiOperation(value = "udi对码列表", notes = "udi对码列表")
@PostMapping("list")
public ResponseData<Page<UdiMatchListVo>> list(@RequestBody @Valid UdiMatchTaskListQry udiMatchTaskListQry){
log.info("list:"+ JSON.toJSONString(udiMatchTaskListQry));
return ResponseData.ok(taskService.queryTaskPage(udiMatchTaskListQry));
}
@ApiOperationSupport(order = 130)
@ApiOperation(value = "全部暂停", notes = "全部暂停")
@PostMapping("allPause")
public ResponseData<?> allPause(@RequestBody @Valid IdListQry idListQry){
log.info("allPause:"+ JSON.toJSONString(idListQry));
return ResponseData.ok(taskService.pauseTask(new ArrayList<>(idListQry.getIdList())));
}
@ApiOperationSupport(order = 131)
@ApiOperation(value = "单个暂停", notes = "单个暂停")
@PostMapping("onePause")
public ResponseData<?> onePause(@RequestBody @Valid IdQry idQry){
log.info("onePause:"+ JSON.toJSONString(idQry));
return ResponseData.ok(taskService.pauseTask(Collections.singletonList(idQry.getId())));
}
@ApiOperationSupport(order = 140)
@ApiOperation(value = "全部开始", notes = "全部开始")
@PostMapping("allStart")
public ResponseData<?> allStart(@RequestBody @Valid IdListQry idListQry){
log.info("allStart:"+ JSON.toJSONString(idListQry));
return ResponseData.ok(taskService.startTask(new ArrayList<>(idListQry.getIdList())));
}
@ApiOperationSupport(order = 141)
@ApiOperation(value = "单个开始-开始上传", notes = "单个开始")
@PostMapping("oneStart")
public ResponseData<?> oneStart(@RequestBody @Valid IdQry idQry){
log.info("oneStart:"+ JSON.toJSONString(idQry));
return ResponseData.ok(taskService.startTask(Collections.singletonList(idQry.getId())));
}
@ApiOperationSupport(order = 150)
@ApiOperation(value = "全部删除", notes = "全部删除")
@PostMapping("allDelete")
public ResponseData<?> allDelete(@RequestBody @Valid IdListQry idListQry){
log.info("allDelete:"+ JSON.toJSONString(idListQry));
return ResponseData.ok(taskService.deleteTask(new ArrayList<>(idListQry.getIdList())));
}
@ApiOperationSupport(order = 151)
@ApiOperation(value = "单个删除", notes = "单个删除")
@PostMapping("oneDelete")
public ResponseData<?> oneDelete(@RequestBody @Valid IdQry idQry){
log.info("oneDelete:"+ JSON.toJSONString(idQry));
return ResponseData.ok(taskService.deleteTask(Collections.singletonList(idQry.getId())));
}
@ApiOperationSupport(order = 160)
@ApiOperation(value = "对码进度", notes = "对码进度")
@PostMapping("matchResult")
public ResponseData<TaskMatchStatisticVo> matchResult(@RequestBody @Valid IdQry idQry){
log.info("matchResult:"+ JSON.toJSONString(idQry));
return ResponseData.ok(taskService.matchResult(idQry.getId()));
}
@ApiOperationSupport(order = 170)
@ApiOperation(value = "获取下载链接", notes = "获取下载链接")
@PostMapping("getDownloadUrl")
public ResponseData<List<UdiMatchTaskFileDto>> getDownloadUrl(@RequestBody @Valid IdListQry idListQry){
log.info("getDownloadUrl:"+ JSON.toJSONString(idListQry));
return ResponseData.ok(taskService.getDownloadUrl(idListQry));
}
}
package com.infynova.udi.manager;
import com.infynova.common.core.api.ResponseData;
import com.infynova.common.core.entity.UploadResultVo;
import com.infynova.common.core.exception.SaasException;
import com.infynova.ucpm.client.OSSServiceClient;
import com.infynova.ucpm.vo.request.OSSBatchIdReqVo;
import com.infynova.udi.dto.UdiMatchTaskFileDto;
import com.infynova.udi.exception.UdiCodeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.*;
@Slf4j
@Component
public class OssManager {
@Resource
private OSSServiceClient oSSServiceClient;
protected <T> T handleResponse(ResponseData<T> resp){
if (resp.isSuccess()) {
return resp.getData();
} else {
throw new SaasException("服务调用失败:错误码=" + resp.getCode() + ",原因=" + resp.getMsg());
}
}
public UploadResultVo upload(MultipartFile multipartFile) {
ResponseData<UploadResultVo> result = oSSServiceClient.upload(multipartFile);
return handleResponse(result);
}
public String getUrlById(Long id){
ResponseData<String> responseData = oSSServiceClient.getUrlById(id);
return responseData.getData();
}
public List<UdiMatchTaskFileDto> queryBatchById(List<Long> ids){
OSSBatchIdReqVo ossBatchId = new OSSBatchIdReqVo();
ossBatchId.setIds(ids);
ResponseData<List<UploadResultVo>> responseData = oSSServiceClient.queryBatchById(ossBatchId);
if(responseData.isSuccess() && CollectionUtils.isNotEmpty(responseData.getData())){
List<UploadResultVo> data = responseData.getData();
List<UdiMatchTaskFileDto> resultList = new ArrayList<>(data.size());
for (UploadResultVo datum : data) {
resultList.add(UdiMatchTaskFileDto.builder().fileId(datum.getId()).fileName(datum.getFileName()).filePath(datum.getFilePath()).build());
}
return resultList;
}else{
return null;
}
}
}
package com.infynova.udi.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiMatchDetailListQry;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.mapper.base.SuperMapper;
import com.infynova.udi.vo.TaskMatchStatisticVo;
import com.infynova.udi.vo.UdiMatchDataVo;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* @author liudong
* 2024/2/29 16:41
* @version 1.0
*/
public interface MatchDataMapper extends SuperMapper<MatchData> {
Page<UdiMatchDataVo> queryMatchDataPage(IPage page,@Param("query") UdiMatchDetailListQry udiMatchDetailListQry);
Set<Long> queryMatchWaitingTask();
List<TaskMatchStatisticVo> queryTaskMatchStatistic(@Param("taskIds") Collection<Long> taskIds);
}
package com.infynova.udi.mapper;
import com.infynova.udi.entity.MatchTemp;
import com.infynova.udi.mapper.base.SuperMapper;
/**
* @author liudong
* 2024/2/29 16:41
* @version 1.0
*/
public interface MatchTempMapper extends SuperMapper<MatchTemp> {
}
package com.infynova.udi.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiMatchTaskListQry;
import com.infynova.udi.entity.Task;
import com.infynova.udi.mapper.base.SuperMapper;
import com.infynova.udi.vo.UdiMatchListVo;
import org.apache.ibatis.annotations.Param;
/**
* @author liudong
* 2024/2/29 16:41
* @version 1.0
*/
public interface TaskMapper extends SuperMapper<Task> {
Page<UdiMatchListVo> queryTaskPage(IPage page, @Param("query") UdiMatchTaskListQry udiMatchTaskListQry);
Task queryTaskNo(@Param("taskNo") String taskNo);
}
package com.infynova.udi.mapper;
import com.infynova.udi.entity.TaskRecord;
import com.infynova.udi.mapper.base.SuperMapper;
/**
* @author liudong
* 2024/2/29 16:41
* @version 1.0
*/
public interface TaskRecordMapper extends SuperMapper<TaskRecord> {
}
package com.infynova.udi.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiListQry;
import com.infynova.udi.vo.UdiMatchRateVo;
import com.infynova.udi.vo.UdiVo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UdiMapper {
Page<UdiVo> getUdiPage(IPage page, @Param("query") UdiListQry udiListQry);
List<UdiVo> getUdiList(@Param("query") UdiListQry udiListQry);
Page<UdiVo> getUdi(IPage page, @Param("udi") String udiCode,
@Param("yiBaoCode") String yiBaoCode,
@Param("companyName") String companyName,
@Param("productFactoryCode") String productFactoryCode,
@Param("brandName") String brandName,
@Param("productName") String productName,
@Param("specification") String specification,
@Param("model") String model
);
List<UdiMatchRateVo> getUdiCodeRegex(@Param("udiCode") String udiCode, @Param("udiCodeList") List<String> udiCodeList);
List<UdiMatchRateVo> getYiBaoCodeRegex(@Param("yiBaoCode") String yiBaoCode, @Param("yiBaoCodeList") List<String> yiBaoCodeList);
List<UdiVo> getUdiIdPage(@Param("id") Long id, @Param("pageSize") Integer pageSize);
}
/*
* Copyright [2021] [SaasPlatform ]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.infynova.udi.mapper.base;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
/**
* @Author: zoupx
* @Description: mybatis plus mapper层选装件 https://mp.baomidou.com/guide/crud-interface.html#select
* @Date: 2021/6/10
*/
public interface SuperMapper<T> extends BaseMapper<T> {
/**
* 批量插入 仅适用于mysql
* @param entityList 实体列表
*/
int insertBatchSomeColumn(Collection<T> entityList);
/**
* 根据 ID 更新固定的那几个字段(不包含逻辑删除),解决设置为null字段无法更新问题
* @param entity
*/
int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
}
package com.infynova.udi.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiAllMatchQry;
import com.infynova.udi.dto.UdiBatchMatchQry;
import com.infynova.udi.dto.UdiMatchConfirmationDto;
import com.infynova.udi.dto.UdiMatchDetailListQry;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.vo.TaskMatchStatisticVo;
import com.infynova.udi.vo.UdiMatchDataVo;
import java.util.List;
/**
* @author liudong
* 2024/3/5 18:21
* @version 1.0
*/
public interface MatchDataService {
Page<UdiMatchDataVo> queryMatchDataPage(UdiMatchDetailListQry udiMatchDetailListQry);
List<TaskMatchStatisticVo> queryTaskMatchStatistic(List<Long> taskIds);
/**
* 批量匹配UDI库
*/
Integer batchMatchUdi(UdiBatchMatchQry udiBatchMatchQry);
/**
* 全量匹配UDI库
*/
Integer allMatchUdi(UdiAllMatchQry udiAllMatchQry);
/**
* 确认对码
*/
MatchData confirmationMatch(UdiMatchConfirmationDto udiMatchConfirmationDto);
}
package com.infynova.udi.service;
import com.infynova.udi.entity.MatchTemp;
import java.util.List;
/**
* @author liudong
* 2024/3/5 18:21
* @version 1.0
*/
public interface MatchTempService {
/**
* 查询匹配数据
*/
List<MatchTemp> queryMatchTemp(Long matchId);
/**
* 查询匹配率最高的一条数据
*/
MatchTemp getMatchRateTop(Long matchId);
}
package com.infynova.udi.service;
import com.infynova.udi.dto.ImportItemResp;
import com.infynova.udi.vo.TaskUdiExcelExportVo;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
/**
* @author liudong
* 2024/2/29 16:50
* @version 1.0
*/
public interface TaskImportService {
ImportItemResp importData(MultipartFile file) throws IOException;
}
package com.infynova.udi.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.IdListQry;
import com.infynova.udi.dto.UdiMatchTaskFileDto;
import com.infynova.udi.dto.UdiMatchTaskListQry;
import com.infynova.udi.entity.Task;
import com.infynova.udi.vo.TaskMatchStatisticVo;
import com.infynova.udi.vo.UdiMatchListVo;
import java.util.List;
/**
* @author liudong
* 2024/2/29 16:39
* @version 1.0
*/
public interface TaskService {
Page<UdiMatchListVo> queryTaskPage(UdiMatchTaskListQry udiMatchTaskListQry);
/**
* 任务开始
*/
Integer startTask(List<Long> taskIds);
/**
* 任务暂停
*/
Integer pauseTask(List<Long> taskIds);
/**
* 任务删除
*/
Integer deleteTask(List<Long> taskIds);
Task getOne(Long taskId);
List<Task> getList(List<Long> taskIds);
List<Task> getUploadingTask();
/**
* 对码进度查询
*/
TaskMatchStatisticVo matchResult(Long taskId);
List<UdiMatchTaskFileDto> getDownloadUrl(IdListQry idListQry);
}
package com.infynova.udi.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiListQry;
import com.infynova.udi.vo.UdiVo;
/**
* @author liudong
* 2024/2/27 14:30
* @version 1.0
*/
public interface UdiService {
Page<UdiVo> getUdiPage(UdiListQry udiListQry);
}
package com.infynova.udi.service.base;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.common.core.entity.PageVo;
/**
* @author liudong
* 2024/2/29 16:44
* @version 1.0
*/
public class BaseService {
public <T> IPage<T> getPage(PageVo reqVo) {
return new Page<>(reqVo.getPageNo(), reqVo.getPageSize());
}
}
package com.infynova.udi.service.core;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.infynova.udi.entity.Udi;
import com.infynova.udi.utils.BooleanValueUtils;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.util.CollectionUtils;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author liudong
* 2024/3/15 16:40
* @version 1.0
*/
@Slf4j
public class ProductDataSave {
// 数据库连接信息
private static final String DB_URL = "jdbc:sqlite:";
private static String SQL_URL = "";
// SQLite model决定SQLite数据库生成方式 1:用固定库名; 2:用随机库名
private static final Integer MODEL = 2;
private static final String url = "jdbc:mysql://rm-wz92456b388ahxujbuo.mysql.rds.aliyuncs.com:3306/saas_base_test";
private static final String username = "saas_test";
private static final String password = "qjCEgXg2z9U5mjL7";
private static final HikariDataSource dataSource;
private static final HikariDataSource SQLiterDataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
dataSource = new HikariDataSource(config);
String databaseName = "";
if(MODEL == 1){
String localUrl = "D:/tool/SQLite/";
databaseName = localUrl + "udi.db";
} else if (MODEL == 2) {
String localUrl = "D:/tool/SQLite/testDB/";
String dateFormat = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd-HH-mm-ss");
databaseName = localUrl + "udi"+ "-" + dateFormat + ".db";
}
String sqlUrl = DB_URL + databaseName;
SQL_URL = sqlUrl;
HikariConfig configSQLite = new HikariConfig();
configSQLite.setJdbcUrl(sqlUrl);
SQLiterDataSource = new HikariDataSource(configSQLite);
}
public static void main(String[] args) {
mainMethod();
}
public static void mainMethod(){
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ProductDataSave importer = new ProductDataSave();
importer.createSQLite();
log.info("SQLite:{}",SQL_URL);
log.info("MYSQL:{}",url);
importer.getProductDataFromAPI();
stopWatch.stop();
long totalTimeMillis = stopWatch.getTime();
double seconds = totalTimeMillis / 1000.0; // 转换为秒
log.info("Total time: " + totalTimeMillis + " ms");
log.info("Seconds: " + seconds);
}
public void createSQLite(){
try (Connection conn = SQLiterDataSource.getConnection();
Statement statement = conn.createStatement()) {
// 创建一个 Statement 对象来执行 SQL 命令
String insertTableSQL = "CREATE TABLE product ( " +
" id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" udi_code TEXT NOT NULL, " +
" yi_bao_one_code TEXT NULL, " +
" yi_bao_two_code TEXT NULL, " +
" yi_bao_code TEXT NULL, " +
" yi_bao_code_prefix TEXT NULL, " +
" company_name TEXT NULL, " +
" brand_name TEXT NULL, " +
" registry_no TEXT NULL, " +
" registry_name TEXT NULL, " +
" registry_start_time TEXT NULL, " +
" registry_end_time TEXT NULL, " +
" registry TEXT NULL, " +
" product_code TEXT NULL, " +
" product_factory_code TEXT NULL, " +
" infynova_code TEXT NULL, " +
" product_name TEXT NULL, " +
" product_type TEXT NULL, " +
" specification TEXT NULL, " +
" model TEXT NULL, " +
" material TEXT NULL, " +
" aseptic_packaging INTEGER NULL, " +
" before_sterilize INTEGER NULL, " +
" sterilization_method TEXT NULL, " +
" yj_foreign_id TEXT NULL, " +
" yb_foreign_id TEXT NULL, " +
" source_name TEXT NULL, " +
" create_time TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, " +
" update_time TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, " +
" version INTEGER DEFAULT 1 NOT NULL " +
"); " +
" " +
"CREATE INDEX product_brand_name_index ON product (brand_name); " +
"CREATE INDEX product_company_name_index ON product (company_name); " +
"CREATE INDEX product_infynova_code_index ON product (infynova_code); " +
"CREATE INDEX product_model_index ON product (model); " +
"CREATE INDEX product_product_code_index ON product (product_code); " +
"CREATE INDEX product_product_factory_code_index ON product (product_factory_code); " +
"CREATE INDEX product_product_name_index ON product (product_name); " +
"CREATE INDEX product_specification_index ON product (specification); " +
"CREATE INDEX product_udi_code_index ON product (udi_code); " +
"CREATE INDEX product_yi_bao_code_index ON product (yi_bao_code); " +
"CREATE INDEX product_yi_bao_code_prefix_index ON product (yi_bao_code_prefix); " +
"CREATE INDEX product_yi_bao_one_code_index ON product (yi_bao_one_code); " +
"CREATE INDEX product_yi_bao_two_code_index ON product (yi_bao_two_code);";
statement.executeUpdate(insertTableSQL);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
// 接口获取产品数据的方法
public void getProductDataFromAPI() {
ExecutorService executorService = Executors.newFixedThreadPool(10);
cn.hutool.core.date.StopWatch sw = new cn.hutool.core.date.StopWatch();
sw.start("开始");
// 在这里实现从接口获取产品数据的逻辑
// 返回一个包含产品对象的列表
int pageNo = 1;
int pageSize = 1000;
Long lastId = 0L;
while (true){
if(lastId % 100000 == 0){
sw.stop();
log.info("完成10万的耗时:{}s",sw.getTotalTimeSeconds());
sw.start();
}
StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
List<Udi> udiList = queryMysqlUdi(lastId,pageSize);
if(CollectionUtils.isEmpty(udiList)){
break;
}
executorService.execute(() -> {
try {
saveProductDataToSQLite(udiList);
} catch (Exception e) {
e.printStackTrace();
}
});
saveProductDataToSQLite(udiList);
lastId = udiList.get(udiList.size() - 1).getId();
} catch (Exception e) {
e.printStackTrace();
log.info("循环错误中断:lastId:{} pageSize:{}",lastId,pageSize);
break;
}finally {
stopWatch.stop();
log.info("查询udi数据库: lastId:{} pageSize:{} 查询+插入耗时:{}", lastId, pageSize, stopWatch.getTime());
}
pageNo++;
}
executorService.shutdown();
sw.stop();
log.info("完成全部的耗时:{}s",sw.getTotalTimeSeconds());
}
private List<Udi> queryMysqlUdi(Long lastId, int pageSize){
List<Udi> udiList = new ArrayList<>();
String sql = "SELECT * FROM product WHERE id > ? ORDER BY id LIMIT ?";
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, lastId); // OFFSET
statement.setInt(2, pageSize); // LIMIT
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
Udi udi = mapResultSetToUdi(resultSet);
udiList.add(udi);
}
}
} catch (SQLException e) {
e.printStackTrace();
// 处理异常
}
return udiList;
}
private Udi mapResultSetToUdi(ResultSet resultSet) throws SQLException {
// 获取每一行数据的字段值
Long id = resultSet.getLong("id");
String udiCode = resultSet.getString("udi_code");
String yiBaoOneCode = resultSet.getString("yi_bao_one_code");
String yiBaoTwoCode = resultSet.getString("yi_bao_two_code");
String yiBaoCode = resultSet.getString("yi_bao_code");
String yiBaoCodePrefix = resultSet.getString("yi_bao_code_prefix");
String companyName = resultSet.getString("company_name");
String brandName = resultSet.getString("brand_name");
String registryNo = resultSet.getString("registry_no");
String registryName = resultSet.getString("registry_name");
LocalDate registryStartTime = resultSet.getDate("registry_start_time").toLocalDate();
LocalDate registryEndTime = resultSet.getDate("registry_end_time").toLocalDate();
String registry = resultSet.getString("registry");
String productCode = resultSet.getString("product_code");
String productFactoryCode = resultSet.getString("product_factory_code");
String infynovaCode = resultSet.getString("infynova_code");
String productName = resultSet.getString("product_name");
String productType = resultSet.getString("product_type");
String specification = resultSet.getString("specification");
String model = resultSet.getString("model");
String material = resultSet.getString("material");
Boolean asepticPackaging = resultSet.getBoolean("aseptic_packaging");
Boolean beforeSterilize = resultSet.getBoolean("before_sterilize");
String sterilizationMethod = resultSet.getString("sterilization_method");
String yjForeignId = resultSet.getString("yj_foreign_id");
String ybForeignId = resultSet.getString("yb_foreign_id");
String sourceName = resultSet.getString("source_name");
LocalDateTime createTime = resultSet.getTimestamp("create_time").toLocalDateTime();
LocalDateTime updateTime = resultSet.getTimestamp("update_time").toLocalDateTime();
String version = resultSet.getString("version");
// 创建 Udi 对象并进行进一步处理
Udi udi = new Udi();
udi.setId(id);
udi.setUdiCode(udiCode);
udi.setYiBaoOneCode(yiBaoOneCode);
udi.setYiBaoTwoCode(yiBaoTwoCode);
udi.setYiBaoCode(yiBaoCode);
udi.setYiBaoCodePrefix(yiBaoCodePrefix);
udi.setCompanyName(companyName);
udi.setBrandName(brandName);
udi.setRegistryNo(registryNo);
udi.setRegistryName(registryName);
udi.setRegistryStartTime(registryStartTime);
udi.setRegistryEndTime(registryEndTime);
udi.setRegistry(registry);
udi.setProductCode(productCode);
udi.setProductFactoryCode(productFactoryCode);
udi.setInfynovaCode(infynovaCode);
udi.setProductName(productName);
udi.setProductType(productType);
udi.setSpecification(specification);
udi.setModel(model);
udi.setMaterial(material);
udi.setAsepticPackaging(asepticPackaging);
udi.setBeforeSterilize(beforeSterilize);
udi.setSterilizationMethod(sterilizationMethod);
udi.setYjForeignId(yjForeignId);
udi.setYbForeignId(ybForeignId);
udi.setSourceName(sourceName);
udi.setCreateTime(createTime);
udi.setUpdateTime(updateTime);
udi.setVersion(version);
// 将其他字段的映射也移到这里
return udi;
}
// 将产品数据保存到SQLite数据库
private void saveProductDataToSQLite(List<Udi> udiList) {
if(CollectionUtils.isEmpty(udiList)){
log.info("数据为空不保存;");
return ;
}
String sql = "INSERT INTO product(id, udi_code, yi_bao_one_code, yi_bao_two_code, yi_bao_code, yi_bao_code_prefix, " +
"company_name, brand_name, registry_no, registry_name, registry_start_time, registry_end_time, registry, " +
"product_code, product_factory_code, infynova_code, product_name, product_type, specification, model, material, aseptic_packaging, before_sterilize, sterilization_method, " +
"yj_foreign_id, yb_foreign_id, source_name, create_time, update_time, version)" +
" VALUES " +
" (?, ?, ?, ?, ?, ?," +
" ?, ?, ?, ?, ?, ?, ?," +
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," +
" ?, ?, ?, ?, ?, ?)";
try (Connection conn = SQLiterDataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
conn.setAutoCommit(false);
for (int i = 0; i < udiList.size(); i++) {
Udi udi = udiList.get(i);
pstmt.setInt(1, Math.toIntExact(udi.getId()));
pstmt.setString(2, udi.getUdiCode());
pstmt.setString(3, udi.getYiBaoOneCode());
pstmt.setString(4, udi.getYiBaoTwoCode());
pstmt.setString(5, udi.getYiBaoCode());
pstmt.setString(6, udi.getYiBaoCodePrefix());
pstmt.setString(7, udi.getCompanyName());
pstmt.setString(8, udi.getBrandName());
pstmt.setString(9, udi.getRegistryNo());
pstmt.setString(10, udi.getRegistryName());
pstmt.setString(11, LocalDateTimeUtil.format(udi.getRegistryStartTime(), DatePattern.NORM_DATE_FORMATTER));
pstmt.setString(12, LocalDateTimeUtil.format(udi.getRegistryEndTime(), DatePattern.NORM_DATE_FORMATTER));
pstmt.setString(13, udi.getRegistry());
pstmt.setString(14, udi.getProductCode());
pstmt.setString(15, udi.getProductFactoryCode());
pstmt.setString(16, udi.getInfynovaCode());
pstmt.setString(17, udi.getProductName());
pstmt.setString(18, udi.getProductType());
pstmt.setString(19, udi.getSpecification());
pstmt.setString(20, udi.getModel());
pstmt.setString(21, udi.getMaterial());
pstmt.setInt(22, BooleanValueUtils.getBooleanInt(udi.getAsepticPackaging()));
pstmt.setInt(23, BooleanValueUtils.getBooleanInt(udi.getBeforeSterilize()));
pstmt.setString(24, udi.getSterilizationMethod());
pstmt.setString(25, udi.getYjForeignId());
pstmt.setString(26, udi.getYbForeignId());
pstmt.setString(27, udi.getSourceName());
pstmt.setString(28, LocalDateTimeUtil.format(udi.getCreateTime(), DatePattern.NORM_DATETIME_FORMATTER));
pstmt.setString(29, LocalDateTimeUtil.format(udi.getUpdateTime(), DatePattern.NORM_DATETIME_FORMATTER));
pstmt.setString(30, udi.getVersion());
pstmt.addBatch();
}
pstmt.executeBatch();
conn.commit();
log.info("Product data inserted successfully.");
} catch (SQLException e) {
log.info("Error saving product data to SQLite: " + e.getMessage());
}
}
}
package com.infynova.udi.service.helper;
import com.infynova.udi.mapper.UdiMapper;
import com.infynova.udi.vo.UdiVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author liudong
* 2024/4/29 16:16
* @version 1.0
*/
@Slf4j
@Component
public class EsSearchHelper {
private static final String INDEX_NAME = "udi";
public static final RestHighLevelClient client;
static{
client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http"))
);
}
public void closeClient() throws IOException {
client.close();
}
@SneakyThrows
public void createIndex(){
log.info("创建索引");
CreateIndexRequest createIndexRequest = new CreateIndexRequest(INDEX_NAME);
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
}
@SneakyThrows
public void deleteIndex(){
log.info("删除索引");
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(INDEX_NAME);
AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
}
@Resource
private UdiMapper udiMapper;
@SneakyThrows
public void initData(){
log.info("同步数据");
StopWatch stopWatch = new StopWatch("开始");
Integer pageSize = 1000;
Long lastId = 0L;
int i = 1;
try{
while (true){
stopWatch.start("第"+i+"页");
log.info("同步索引:第{}页,lastId:{}",i,lastId);
List<UdiVo> records = udiMapper.getUdiIdPage(lastId,pageSize);
if(CollectionUtils.isEmpty(records)){
return;
}
indexDocument(records);
UdiVo udiVo = records.get(records.size()-1);
lastId = udiVo.getId();
i++;
stopWatch.stop();
}
}catch (Exception e){
log.error("");
log.error("",e);
}finally {
stopWatch.stop();
log.info(stopWatch.prettyPrint());
log.info("总计耗时:{}",stopWatch.getTotalTimeSeconds());
}
}
private Map<String,Object> getDoc(UdiVo udiVo){
Map<String,Object> map = new HashMap<>();
map.put("id",udiVo.getId());
map.put("companyName",udiVo.getCompanyName());
map.put("productFactoryCode",udiVo.getProductFactoryCode());
map.put("brandName",udiVo.getBrandName());
map.put("productName",udiVo.getProductName());
map.put("specification",udiVo.getSpecification());
map.put("model",udiVo.getModel());
return map;
}
public void indexDocument(List<UdiVo> udiVos) throws IOException {
BulkRequest bulkRequest = new BulkRequest();
for (UdiVo udiVo : udiVos) {
Map<String, Object> doc = getDoc(udiVo);
IndexRequest request = new IndexRequest(INDEX_NAME)
.id(String.valueOf(udiVo.getId()))
.source(doc, XContentType.JSON);
bulkRequest.add(request);
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
if (bulkResponse.hasFailures()) {
// 处理失败的情况
log.error("Some documents failed to index: " + bulkResponse.buildFailureMessage());
} else {
log.info("Bulk indexing successful.");
}
}
@SneakyThrows
public void updateIndex(String id, Map<String, Object> updatedDocument) throws IOException {
UpdateRequest request = new UpdateRequest(INDEX_NAME, id)
.doc(updatedDocument, XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
}
@SneakyThrows
public Map<String, Object> searchThree(String id){
GetRequest getRequest = new GetRequest(INDEX_NAME, id);
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
return getResponse.getSourceAsMap();
}
}
package com.infynova.udi.service.helper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
/**
* @author liudong
* 2024/3/14 18:27
* @version 1.0
*/
@Slf4j
public class IKAnalyzerSupport {
/**
* IK分词
* @param target
* @return
*/
public static List<String> iKSegmenterToList(String target) throws Exception {
if (StringUtils.isEmpty(target)){
return new ArrayList<>();
}
List<String> result = new ArrayList<>();
StringReader sr = new StringReader(target);
// false:关闭智能分词 (对分词的精度影响较大)
IKSegmenter ik = new IKSegmenter(sr, true);
Lexeme lex;
while((lex=ik.next())!=null) {
String lexemeText = lex.getLexemeText();
result.add(lexemeText);
}
return result;
}
}
package com.infynova.udi.service.helper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.entity.MatchTemp;
import com.infynova.udi.entity.Udi;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.mapper.MatchDataMapper;
import com.infynova.udi.mapper.MatchTempMapper;
import com.infynova.udi.mapper.UdiMapper;
import com.infynova.udi.vo.TaskVo;
import com.infynova.udi.vo.UdiMatchRateVo;
import com.infynova.udi.vo.UdiVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* @author liudong
* 2024/3/5 13:44
* @version 1.0
*/
@Slf4j
@Component("matchHelper")
public class MatchHelper {
@Resource
private MatchDataMapper matchDataMapper;
@Resource
private MatchTempMapper matchTempMapper;
@Resource
private UdiMapper udiMapper;
@Resource
private TaskHelper taskHelper;
@Resource
private UdiLock udiLock;
private static final BigDecimal ONE_HUNDRED_RATE = new BigDecimal("100");
private String getKey(String key){
return "match:" + key;
}
/**
* 对码匹配
*/
public void tranMatchRate(){
Set<Long> taskIdSet = matchDataMapper.queryMatchWaitingTask();
if(CollectionUtils.isEmpty(taskIdSet)){
log.info("对码匹配-没有需要对码匹配的数据");
}
for (Long taskId : taskIdSet) {
// 加锁机制
String key = this.getKey(String.valueOf(taskId));
Boolean hasKey = udiLock.hasKey(key);
if(hasKey){
log.info("对码匹配-taskId:{},对码已在运行中;",key);
continue;
}else{
try {
log.info("对码匹配-taskId:{},上锁;",key);
udiLock.lock(key,1440L);
// 通知任务修改任务状态
taskHelper.taskMatchStatusStart(taskId);
// 对码核心逻辑
this.taskMatch(taskId);
// 结束
taskHelper.taskMatchStatusFinish(taskId);
} finally {
log.info("对码匹配-taskId:{},解锁;",key);
udiLock.del(key);
}
}
}
}
/**
* 对码核心逻辑
*/
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void taskMatch(Long taskId){
// 每一次转换最大数量100
int pageNo = 1;
int oneMaxNum = 100;
TaskVo taskVo = taskHelper.getTaskVo(taskId);
log.info("对码匹配-taskNo:{}",taskVo.getTask().getTaskNo());
while (true){
// 查询未开始的数据
LambdaQueryWrapper<MatchData> queryWrapper = new LambdaQueryWrapper<>();
Page<MatchData> page = new Page<>(pageNo, oneMaxNum);
queryWrapper.eq(MatchData::getMatchStatus, MatchStatusEnum.WAITING.getCode());
queryWrapper.eq(MatchData::getTaskId, taskId);
Page<MatchData> dataPage = matchDataMapper.selectPage(page, queryWrapper);
if(CollectionUtils.isEmpty(dataPage.getRecords())){
break;
}
for (MatchData matchData : dataPage.getRecords()) {
this.match(taskId,matchData);
}
pageNo++;
}
}
/**
* 查询匹配且生成匹配数据
*/
private void match(Long taskId, MatchData matchData){
// 查询udi
//Page<UdiVo> voPage = this.queryUdi(udiPageNo,pageSize,matchData);
List<UdiMatchRateVo> matchRateVoList = new ArrayList<>();
if(StringUtils.isNotBlank(matchData.getUdiCode())){
// 去匹配udiCode
matchRateVoList = this.queryUdiNew(matchData);
} else if(StringUtils.isNotBlank(matchData.getYiBaoCode())){
// 去匹配YiBaoCode
matchRateVoList = this.queryYiBaoCode(matchData);
} else if(StringUtils.isNotBlank(matchData.getCompanyName()) || StringUtils.isNotBlank(matchData.getProductFactoryCode())){
// 厂家+产品货号/编号 todo
} else if (StringUtils.isNotBlank(matchData.getBrandName())
|| StringUtils.isNotBlank(matchData.getProductName())
|| StringUtils.isNotBlank(matchData.getSpecification())
|| StringUtils.isNotBlank(matchData.getModel())) {
// 品牌+名称+规格+型号; todo
}
// 计算匹配率
List<MatchTemp> matchTempList = new ArrayList<>();
boolean hundredRate = false;
for (UdiMatchRateVo udiVo : matchRateVoList) {
// 核心匹配率逻辑
BigDecimal matchRate = udiVo.getMatchRatio();
if(matchRate.compareTo(ONE_HUNDRED_RATE) == 0){
hundredRate = true;
}
MatchTemp matchTemp = new MatchTemp();
BeanUtils.copyProperties(udiVo,matchTemp);
Long matchId = matchData.getId();
matchTemp.setProductId(udiVo.getId());
matchTemp.setOriginalRecord(false);
matchTemp.setMatchId(matchId);
matchTemp.setTaskId(taskId);
matchTemp.setMatchRate(matchRate);
matchTemp.setCreateBy(null);
matchTemp.setCreateName(null);
matchTemp.setCreateTime(LocalDateTime.now());
matchTemp.setUpdateBy(null);
matchTemp.setUpdateName(null);
matchTemp.setUpdateTime(LocalDateTime.now());
matchTempList.add(matchTemp);
}
// 存在查询到了数据,但是匹配率全为0的情况
if(CollectionUtils.isEmpty(matchTempList)){
// 如果为空
matchData.setMatchStatus(MatchStatusEnum.NO.getCode());
matchData.setUpdateStatus(MatchUpdateStatusEnum.NOT_APPLICABLE.getCode());
matchData.setUpdateTime(LocalDateTime.now());
matchDataMapper.updateById(matchData);
return;
}else{
if(hundredRate){
// 100%对码
matchData.setMatchStatus(MatchStatusEnum.HUNDRED.getCode());
}else{
// 部分对码
matchData.setMatchStatus(MatchStatusEnum.SECTION.getCode());
}
matchData.setUpdateStatus(MatchUpdateStatusEnum.PENDING.getCode());
matchData.setUpdateTime(LocalDateTime.now());
matchDataMapper.updateById(matchData);
// 进行排序
List<MatchTemp> sortList = matchTempList.stream().sorted(Comparator.comparing(MatchTemp::getMatchRate)).collect(Collectors.toList());
matchTempMapper.insertBatchSomeColumn(sortList);
}
}
/**
* 查询udi
*/
private Page<UdiVo> queryUdi(int pageNo, int pageSize, MatchData matchData){
String udiCode = matchData.getUdiCode();
String yiBaoCode = matchData.getYiBaoCode();
String companyName = matchData.getCompanyName();
String productFactoryCode = matchData.getProductFactoryCode();
String brandName = matchData.getBrandName();
String productName = matchData.getProductName();
String specification = matchData.getSpecification();
String model = matchData.getModel();
Page<UdiVo> page = new Page<>(pageNo, pageSize);
return udiMapper.getUdi(page,udiCode,
yiBaoCode,
companyName,
productFactoryCode,
brandName,
productName,
specification,
model);
}
/**
* 查询udi
*/
private List<UdiMatchRateVo> queryUdiNew(MatchData matchData){
String udiCode = matchData.getUdiCode();
// String udiCodeRegex = this.splitWord(udiCode);
List<String> udiCodeRegexList = new ArrayList<>();
String lastUdi = udiCode;
// 规定udi截取的最小长度
int udiCodeMinLength = 8;
while (true){
String subUdi = decrementUDICode(lastUdi,2,udiCodeMinLength);
if(Objects.equals(subUdi,lastUdi)){
break;
}else{
lastUdi = subUdi;
udiCodeRegexList.add(subUdi);
}
}
return udiMapper.getUdiCodeRegex(udiCode,udiCodeRegexList);
}
// 递减 Code 的函数
private String decrementUDICode(String code, int decrementAmount, int minLength) {
int length = code.length();
if(length<=minLength){
return code;
}
return code.substring(0, length - decrementAmount);
}
/**
* 查询C码
*/
private List<UdiMatchRateVo> queryYiBaoCode(MatchData matchData){
String yiBaoCode = matchData.getYiBaoCode();
// todo 分次
List<String> yiBaoCodeRegexList = new ArrayList<>();
String lastYiBaoCode = yiBaoCode;
// 规定udi截取的最小长度
int yiBaoCodeMinLength = 8;
while (true){
String subYiBaoCode = decrementUDICode(lastYiBaoCode,2,yiBaoCodeMinLength);
if(Objects.equals(subYiBaoCode,lastYiBaoCode)){
break;
}else{
lastYiBaoCode = subYiBaoCode;
yiBaoCodeRegexList.add(subYiBaoCode);
}
}
return udiMapper.getUdiCodeRegex(yiBaoCode,yiBaoCodeRegexList);
}
/**
* 对目标进行分词
*/
private String splitWord(String item){
log.info("对目标进行分词");
List<String> splitWord = new ArrayList<>();
String result = item;
try {
splitWord = IKAnalyzerSupport.iKSegmenterToList(item);
result = splitWord.stream().map(String::valueOf).distinct().collect(Collectors.joining("|")) ;
log.info("分词结果:{}",result);
} catch (Exception e) {
log.error("分词报错:{}",e.getMessage());
}
return result;
}
private final BigDecimal RATE = new BigDecimal("0.25");
/**
* 匹配率计算逻辑
*/
private BigDecimal matchRate(Udi udi, MatchData matchData){
BigDecimal matchRate = BigDecimal.ZERO;
// - 规则1:DI码,即69码;
String udiCode = udi.getUdiCode();
String matchUdiCode = matchData.getUdiCode();
if(StringUtils.equals(udiCode,matchUdiCode)){
matchRate = matchRate.add(RATE);
}
// - 规则2:C码 ,是指医保编码;
String yiBaoCode = udi.getYiBaoCode();
String matchYiBaoCode = matchData.getYiBaoCode();
if(StringUtils.equals(yiBaoCode,matchYiBaoCode)){
matchRate = matchRate.add(RATE);
}
// - 规则3:厂家+产品货号/编号;
String companyName = udi.getCompanyName();
String matchCompanyName = matchData.getCompanyName();
String productFactoryCode = udi.getProductFactoryCode();
String matchProductFactoryCode = matchData.getProductFactoryCode();
if(StringUtils.equals(companyName,matchCompanyName) && StringUtils.equals(productFactoryCode,matchProductFactoryCode)){
matchRate = matchRate.add(RATE);
}
// - 规则4:品牌+名称+规格+型号;
String brandName = udi.getBrandName();
String matchBrandName = matchData.getBrandName();
String productName = udi.getProductName();
String matchProductName = matchData.getProductName();
String specification = udi.getSpecification();
String matchSpecification = matchData.getSpecification();
String model = udi.getModel();
String matchModel = matchData.getModel();
if(StringUtils.equals(brandName,matchBrandName)
&& StringUtils.equals(productName,matchProductName)
&& StringUtils.equals(specification,matchSpecification)
&& StringUtils.equals(model,matchModel)){
matchRate = matchRate.add(RATE);
}
return matchRate;
}
}
package com.infynova.udi.service.helper;
import com.alibaba.fastjson.JSONObject;
import com.infynova.udi.dto.UdiQueryDto;
import com.infynova.udi.vo.UdiVo;
import io.redisearch.AggregationResult;
import io.redisearch.Document;
import io.redisearch.aggregation.AggregationBuilder;
import io.redisearch.aggregation.SortedField;
import io.redisearch.client.Client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import io.redisearch.Query;
import io.redisearch.SearchResult;
import redis.clients.jedis.Jedis;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author liudong
* 2024/4/28 17:33
* @version 1.0
*/
@Slf4j
@Component
public class RedisSearchHelper {
private static Client redisClient;
static{
redisClient = new Client("udi:index","127.0.0.1", 6379);
}
public SearchResult searchThree(String companyName, String productFactoryCode){
String queryKeyCompanyName = String.format("@companyName:%s", companyName);
Query query = new Query(queryKeyCompanyName);
query.limit(0,10);
query.setWithScores();
query.setLanguage("chinese");
SearchResult search = redisClient.search(query);
if(search.totalResults>0){
List<UdiVo> data = new ArrayList<>(Math.toIntExact(search.totalResults));
for (Document doc : search.docs) {
UdiVo udiVo = new UdiVo();
udiVo.setId((Long) doc.get("id"));
udiVo.setCompanyName((String) doc.get("companyName"));
udiVo.setProductFactoryCode((String) doc.get("productFactoryCode"));
udiVo.setBrandName((String) doc.get("brandName"));
udiVo.setProductName((String) doc.get("productName"));
udiVo.setSpecification((String) doc.get("specification"));
udiVo.setModel((String) doc.get("model"));
data.add(udiVo);
}
//return UdiQueryDto.builder().total(Math.toIntExact(search.totalResults)).data(data).build();
}
//return UdiQueryDto.builder().build();
return search;
}
}
package com.infynova.udi.service.helper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiListQry;
import com.infynova.udi.entity.Udi;
import com.infynova.udi.mapper.UdiMapper;
import com.infynova.udi.service.UdiService;
import com.infynova.udi.vo.UdiVo;
import io.redisearch.Document;
import io.redisearch.Schema;
import io.redisearch.client.Client;
import io.redisearch.client.IndexDefinition;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author liudong
* 2024/4/28 17:43
* @version 1.0
*/
@Slf4j
@Component
public class RedisSearchIndexer {
private static Client redisClient;
static{
redisClient = new Client("udi:index","127.0.0.1", 6379);
}
@Resource
private UdiMapper udiMapper;
//@PostConstruct
public void createIndex() {
log.info("创建索引");
Schema schema = new Schema()
.addTextField("companyName", 1.0)
.addTextField("productFactoryCode", 1.0)
.addTextField("brandName", 1.0)
.addTextField("productName", 1.0)
.addTextField("specification", 1.0)
.addTextField("model", 1.0);
IndexDefinition indexDefinition = new IndexDefinition()
.setPrefixes("udi:") // 设置索引名称前缀
.setLanguage("chinese")
// .setIndex(Schema.Index.PREFIX) // 使用前缀索引
.setFilter("@type == \"udi\""); // 过滤条件,只索引类型为 "udi" 的数据
redisClient.createIndex(schema, Client.IndexOptions.defaultOptions().setDefinition(indexDefinition));
}
public void deleteIndex(){
log.info("删除索引");
redisClient.dropIndex(true);
}
public void initData(){
ExecutorService executorService = Executors.newFixedThreadPool(10);
log.info("同步数据");
StopWatch stopWatch = new StopWatch("开始");
Integer pageSize = 1000;
Long lastId = 3059000L;
int i = 1;
try{
while (true){
stopWatch.start("第"+i+"页");
log.info("同步索引:第{}页,lastId:{}",i,lastId);
List<UdiVo> records = udiMapper.getUdiIdPage(lastId,pageSize);
if(CollectionUtils.isEmpty(records)){
return;
}
List<Document> documents = new ArrayList<>();
for (UdiVo udiVo : records) {
documents.add(this.indexData(udiVo));
}
executorService.execute(() -> {
try {
Document[] array = documents.toArray(new Document[0]);
redisClient.addDocuments(array);
} catch (Exception e) {
e.printStackTrace();
}
});
UdiVo udiVo = records.get(records.size()-1);
lastId = udiVo.getId();
i++;
stopWatch.stop();
}
}catch (Exception e){
log.error("");
log.error("",e);
}finally {
stopWatch.stop();
log.info(stopWatch.prettyPrint());
log.info("总计耗时:{}",stopWatch.getTotalTimeSeconds());
}
}
public io.redisearch.Document indexData(UdiVo udi) {
redisClient.deleteDocument("udi:" + udi.getId(),true);
return new io.redisearch.Document("udi:" + udi.getId())
.set("companyName", Optional.ofNullable(udi.getCompanyName()).orElse(""))
.set("productFactoryCode", Optional.ofNullable(udi.getProductFactoryCode()).orElse(""))
.set("brandName", Optional.ofNullable(udi.getBrandName()).orElse(""))
.set("productName", Optional.ofNullable(udi.getProductName()).orElse(""))
.set("specification", Optional.ofNullable(udi.getSpecification()).orElse(""))
.set("model", Optional.ofNullable(udi.getModel()).orElse(""));
}
}
package com.infynova.udi.service.helper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.infynova.udi.entity.Task;
import com.infynova.udi.entity.TaskRecord;
import com.infynova.udi.enums.UdiEnumUtils;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskRecordEnum;
import com.infynova.udi.enums.task.TaskRecordTypeEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import com.infynova.udi.mapper.TaskMapper;
import com.infynova.udi.mapper.TaskRecordMapper;
import com.infynova.udi.vo.TaskVo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
* @author liudong
* 2024/2/29 18:31
* @version 1.0
*/
@Component("taskHelper")
public class TaskHelper {
@Resource
private TaskMapper taskMapper;
@Resource
private TaskRecordMapper taskRecordMapper;
@Resource
RedisTemplate<String, Object> redisTemplate;
/**
* 公平锁
*/
private final ReentrantLock fairLock = new ReentrantLock(true);
public List<TaskVo> getTaskVoList(List<Long> taskIdList){
List<Task> tasks = taskMapper.selectBatchIds(taskIdList);
if(CollectionUtils.isEmpty(tasks)){
return Collections.emptyList();
}
LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>();
queryWrapper.in(TaskRecord::getTaskId, taskIdList)
.orderByAsc(TaskRecord::getCreateTime);
List<TaskRecord> taskRecordList = taskRecordMapper.selectList(queryWrapper);
Map<Long, List<TaskRecord>> map = taskRecordList.stream().collect(Collectors.groupingBy(TaskRecord::getTaskId));
List<TaskVo> taskVoList = new ArrayList<>();
for (Task task : tasks) {
Long taskId = task.getId();
task.setTaskStatusDesc(UdiEnumUtils.getDescByCode(TaskStatusEnum.class,task.getTaskStatus()));
//task.setTaskFileSizeDesc();
task.setTaskMatchStatusDesc(UdiEnumUtils.getDescByCode(TaskMatchStatusEnum.class,task.getTaskMatchStatus()));
List<TaskRecord> taskRecords = map.getOrDefault(taskId, Collections.emptyList());
this.setUploadTime(task,taskRecords);
this.setMatchTime(task,taskRecords);
TaskVo taskVo = TaskVo.builder().task(task).taskRecordList(taskRecords).build();
taskVoList.add(taskVo);
}
return taskVoList;
}
public TaskVo getTaskVo(Long taskId){
Task task = taskMapper.selectById(taskId);
if(Objects.isNull(task)){
return null;
}
task.setTaskStatusDesc(UdiEnumUtils.getDescByCode(TaskStatusEnum.class,task.getTaskStatus()));
//task.setTaskFileSizeDesc();
task.setTaskMatchStatusDesc(UdiEnumUtils.getDescByCode(TaskMatchStatusEnum.class,task.getTaskMatchStatus()));
LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>();
queryWrapper.eq(TaskRecord::getTaskId, taskId)
.orderByAsc(TaskRecord::getCreateTime);
List<TaskRecord> taskRecords = taskRecordMapper.selectList(queryWrapper);
this.setUploadTime(task,taskRecords);
this.setMatchTime(task,taskRecords);
return TaskVo.builder().task(task).taskRecordList(taskRecords).build();
}
public Map<Long,List<TaskRecord>> getTaskRecordMap(List<Long> taskIdList){
LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>();
queryWrapper.in(TaskRecord::getTaskId, taskIdList)
.orderByAsc(TaskRecord::getCreateTime);
List<TaskRecord> taskRecords = taskRecordMapper.selectList(queryWrapper);
return taskRecords.stream().collect(Collectors.groupingBy(TaskRecord::getTaskId));
}
/**
* 获取任务编码
*/
public String getTaskNo(){
String taskNo;
try {
fairLock.lock();
while (true){
taskNo = this.build();
Task task = taskMapper.queryTaskNo(taskNo);
if(Objects.isNull(task)){
break;
}
}
return taskNo;
}catch (Exception e){
throw e;
}finally {
// 释放锁
fairLock.unlock();
}
}
private String build(){
String taskNoPrefix = "T";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date now = new Date();
String dateStr = sdf.format(now);
String redisKey = String.format("UDI:%s:%s", dateStr, taskNoPrefix);
int num = redisTemplate.opsForValue().increment(redisKey).intValue();
if (num == 1) {
//设置过期时间
redisTemplate.expire(redisKey, 2, TimeUnit.DAYS);
}
String numStr = num + "";
while (numStr.length() < 4) {
numStr = "0" + numStr;
}
dateStr = taskNoPrefix + dateStr + numStr;
return dateStr;
}
@Transactional(rollbackFor = Exception.class)
public Task saveTask(Integer taskFileSize,Integer taskFileCount,String taskFileAddress,Long taskFileId){
// 保存task
Task task = new Task();
task.setTaskNo(this.getTaskNo());
task.setTaskStatus(TaskStatusEnum.NEW_TASK.getCode());
task.setTaskFileSize(String.valueOf(taskFileSize));
task.setTaskFileCount(taskFileCount);
task.setTaskUploadNum(0);
task.setTaskFileAddress(taskFileAddress);
task.setTaskFileId(taskFileId);
task.setUploadTime(0);
task.setTaskMatchStatus(TaskMatchStatusEnum.WAITING.getCode());
task.setMatchTime(0);
task.setOperatorId(null);// todo
task.setOperator(null);// todo
task.setCreateBy(null);// todo
task.setCreator(null);// todo
task.setCreateTime(LocalDateTime.now());
task.setUpdateTime(LocalDateTime.now());
task.setDelFlag(false);
task.setVersion(1);
taskMapper.insert(task);
// 保存TaskRecord
TaskRecord taskRecord = this.getDefaultTaskRecord(task.getId(), TaskRecordEnum.IMPORT_BUILD.getDesc());
taskRecordMapper.insert(taskRecord);
return task;
}
/**
* 启动上传状态变更
*/
@Transactional(rollbackFor = Exception.class)
public void taskStatusUploadStart(Long taskId){
Task task = taskMapper.selectById(taskId);
task.setTaskStatus(TaskStatusEnum.UPLOADING.getCode());
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_START.getDesc());
taskRecordMapper.insert(taskRecord);
}
/**
* 修改已上传数据
*/
public void taskUploadNum(Long taskId,int uploadNum){
Task task = taskMapper.selectById(taskId);
int num = task.getTaskUploadNum() + uploadNum;
task.setTaskUploadNum(num);
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
}
/**
* 暂停上传状态变更
*/
@Transactional(rollbackFor = Exception.class)
public void taskStatusUploadPause(Long taskId){
Task task = taskMapper.selectById(taskId);
task.setTaskStatus(TaskStatusEnum.PAUSE.getCode());
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_PAUSE.getDesc());
taskRecordMapper.insert(taskRecord);
}
/**
* 上传完成状态变更
*/
@Transactional(rollbackFor = Exception.class)
public void taskStatusUploadFinish(Long taskId){
Task task = taskMapper.selectById(taskId);
task.setTaskStatus(TaskStatusEnum.FINISH.getCode());
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_FINISH.getDesc());
taskRecordMapper.insert(taskRecord);
}
/**
* 对码开始
*/
@Transactional(rollbackFor = Exception.class)
public void taskMatchStatusStart(Long taskId){
Task task = taskMapper.selectById(taskId);
if(!Objects.equals(task.getTaskMatchStatus(),TaskMatchStatusEnum.WAITING.getCode())){
return;
}
task.setTaskMatchStatus(TaskMatchStatusEnum.MATCHING.getCode());
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
TaskRecord taskRecord = this.getMatchTaskRecord(taskId, TaskRecordEnum.MATCH_START.getDesc());
taskRecordMapper.insert(taskRecord);
}
/**
* 对码完成
*/
@Transactional(rollbackFor = Exception.class)
public void taskMatchStatusFinish(Long taskId){
Task task = taskMapper.selectById(taskId);
task.setTaskMatchStatus(TaskMatchStatusEnum.FINISH.getCode());
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
TaskRecord taskRecord = this.getMatchTaskRecord(taskId, TaskRecordEnum.MATCH_FINISH.getDesc());
taskRecordMapper.insert(taskRecord);
}
/**
* 删除
*/
@Transactional(rollbackFor = Exception.class)
public void taskDelete(Long taskId){
Task task = taskMapper.selectById(taskId);
task.setTaskStatus(TaskStatusEnum.DELETE.getCode());
task.setUpdateTime(LocalDateTime.now());
task.setDelFlag(true);
taskMapper.updateById(task);
TaskRecord taskRecord = this.getDefaultTaskRecord(taskId, TaskRecordEnum.DELETE.getDesc());
taskRecordMapper.insert(taskRecord);
}
public TaskRecord getDefaultTaskRecord(Long taskId,String record){
TaskRecord taskRecord = new TaskRecord();
taskRecord.setTaskId(taskId);
taskRecord.setRecord(record);
taskRecord.setRecordType(TaskRecordTypeEnum.DEFAULT.getCode());
taskRecord.setCreateBy(null);// todo
taskRecord.setCreator(null);// todo
taskRecord.setCreateTime(LocalDateTime.now());
return taskRecord;
}
public TaskRecord getUploadTaskRecord(Long taskId,String record){
TaskRecord taskRecord = new TaskRecord();
taskRecord.setTaskId(taskId);
taskRecord.setRecord(record);
taskRecord.setRecordType(TaskRecordTypeEnum.UPLOAD.getCode());
taskRecord.setCreateBy(null);// todo
taskRecord.setCreator(null);// todo
taskRecord.setCreateTime(LocalDateTime.now());
return taskRecord;
}
public TaskRecord getMatchTaskRecord(Long taskId,String record){
TaskRecord taskRecord = new TaskRecord();
taskRecord.setTaskId(taskId);
taskRecord.setRecord(record);
taskRecord.setRecordType(TaskRecordTypeEnum.MATCH.getCode());
taskRecord.setCreateBy(null);// todo
taskRecord.setCreator(null);// todo
taskRecord.setCreateTime(LocalDateTime.now());
return taskRecord;
}
/**
* 设置上传时间
*/
public void setUploadTime(Task task,List<TaskRecord> taskRecords){
Integer uploadTime = this.getUploadTime(taskRecords);
task.setUploadTime(uploadTime);
task.setUploadTimeDesc(this.formatDuration(uploadTime));
}
/**
* 设置对码时间
*/
public void setMatchTime(Task task,List<TaskRecord> taskRecords){
Integer matchTime = this.getMatchTime(taskRecords);
task.setMatchTime(matchTime);
task.setMatchTimeDesc(this.formatDuration(matchTime));
}
/**
* 计算对码时间
*/
public Integer getMatchTime(List<TaskRecord> recordList){
long matchTimeInSeconds = 0;
LocalDateTime startTime = null;
for (int i = 0; i < recordList.size(); i++) {
TaskRecord currentRecord = recordList.get(i);
if (currentRecord.getRecordType() == 2) { // 对码记录
if( Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_START.getDesc()) ){
startTime = currentRecord.getCreateTime();
} else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_PAUSE.getDesc())) {
// 计算本次对码时间并累加到总对码时间
if (startTime != null) {
LocalDateTime pauseTime = currentRecord.getCreateTime();
matchTimeInSeconds += Duration.between(startTime, pauseTime).getSeconds();
startTime = null;
}
} else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_FINISH.getDesc())) {
// 如果启动但没有暂停,直接计算上传时间
if (startTime != null) {
LocalDateTime endTime = currentRecord.getCreateTime();
matchTimeInSeconds += Duration.between(startTime, endTime).getSeconds();
startTime = null;
}
}
}
}
return Math.toIntExact(matchTimeInSeconds);
}
/**
* 计算上传时间
*/
public Integer getUploadTime(List<TaskRecord> recordList){
long matchTimeInSeconds = 0;
LocalDateTime startTime = null;
for (int i = 0; i < recordList.size(); i++) {
TaskRecord currentRecord = recordList.get(i);
if (currentRecord.getRecordType() == 1) { // 上传记录
if( Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_START.getDesc()) ){
startTime = currentRecord.getCreateTime();
} else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_PAUSE.getDesc())) {
// 计算本次上传时间并累加到总上传时间
if (startTime != null) {
LocalDateTime pauseTime = currentRecord.getCreateTime();
matchTimeInSeconds += Duration.between(startTime, pauseTime).getSeconds();
startTime = null;
}
} else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_FINISH.getDesc())) {
// 如果启动但没有暂停,直接计算上传时间
if (startTime != null) {
LocalDateTime endTime = currentRecord.getCreateTime();
matchTimeInSeconds += Duration.between(startTime, endTime).getSeconds();
startTime = null;
}
}
}
}
return Math.toIntExact(matchTimeInSeconds);
}
/**
* 时间转换(秒转特定格式)
*/
public String formatDuration(int durationInSeconds) {
int days = durationInSeconds / (24 * 3600);
int hours = (durationInSeconds % (24 * 3600)) / 3600;
int minutes = ((durationInSeconds % (24 * 3600)) % 3600) / 60;
int seconds = ((durationInSeconds % (24 * 3600)) % 3600) % 60;
StringBuilder formattedDuration = new StringBuilder();
if (days > 0) {
formattedDuration.append(days).append("天");
}
if (hours > 0) {
formattedDuration.append(hours).append("小时");
}
if (minutes > 0) {
formattedDuration.append(minutes).append("分钟");
}
if (seconds > 0 || (days == 0 && hours == 0 && minutes == 0)) {
formattedDuration.append(seconds).append("秒");
}
return formattedDuration.toString().trim();
}
}
package com.infynova.udi.service.helper;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.entity.Task;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import com.infynova.udi.exception.CommonExceptionCode;
import com.infynova.udi.exception.UdiCodeException;
import com.infynova.udi.manager.OssManager;
import com.infynova.udi.mapper.MatchDataMapper;
import com.infynova.udi.service.TaskService;
import com.infynova.udi.utils.BooleanValueUtils;
import com.infynova.udi.vo.TaskUdiExcelImportVo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
/**
* @author liudong
* 2024/3/1 11:35
* @version 1.0
*/
@Slf4j
@Component("taskUploadHelper")
public class TaskUploadHelper {
@Resource
private TaskService taskService;
@Resource
private MatchDataMapper matchDataMapper;
@Resource
private TaskHelper taskHelper;
@Resource
private UdiLock udiLock;
@Resource
private OssManager ossManager;
private String getKey(String key){
return "upload:" + key;
}
public void tranTask(){
// 扫描上传中的任务
List<Task> uploadingTaskList = taskService.getUploadingTask();
if(CollectionUtils.isEmpty(uploadingTaskList)){
log.info("任务上传转换定时执行-没有需要进行转换处理的任务");
return;
}else{
log.info("任务上传转换定时执行-此次处理的任务数量:{}",uploadingTaskList.size());
}
for (Task uploadingTask : uploadingTaskList) {
tranUpload(uploadingTask.getId());
}
}
@SneakyThrows
public void tranUpload(Long taskId) {
log.info("上传中任务转换成待对码数据-taskId:{}",taskId);
// 获取任务
Task task = taskService.getOne(taskId);
if(Objects.isNull(task)){
log.error("上传中任务转换成待对码数据-taskId:{}-查询数据为空",taskId);
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
log.info("上传中任务转换成待对码数据-taskNo:{}",task.getTaskNo());
if(!Objects.equals(task.getTaskStatus(), TaskStatusEnum.UPLOADING.getCode())){
log.warn("上传中任务转换成待对码数据-任务状态不对");
return;
}
// 需要做一个唯一锁,用于控制任务唯一进行
String key = this.getKey(String.valueOf(taskId));
if(udiLock.hasKey(key)){
log.info("上传中任务转换成待对码数据-taskId:{},转换已在运行中;",key);
return ;
}
try{
log.info("上传中任务转换成待对码数据-key:{},上锁;",key);
udiLock.lock(key,1440L);
// 下载源文件转换成数据
Long taskFileId = task.getTaskFileId();
String taskFileAddress = ossManager.getUrlById(taskFileId);
if(StringUtils.isBlank(taskFileAddress)){
log.error("上传中任务转换成待对码数据:错误-taskId:{},来源文件为空;",key);
return;
}
File file = downloadExcel(taskFileAddress);
// 将文件中的数据转换成待对码数据
List<TaskUdiExcelImportVo> excelList = new ArrayList<>();
EasyExcel.read(file, TaskUdiExcelImportVo.class, new PageReadListener<TaskUdiExcelImportVo>(excelList::addAll)).sheet().doRead();
// 每一次转换最大数量100
int oneMaxNum = 100;
int size = excelList.size();
// 已上传的数量
int startNum = task.getTaskUploadNum();
for (int i = startNum; i < size; i += oneMaxNum) {
//Thread.sleep(300000);
// 用于控制任务暂停的情况
Task taskNow = taskService.getOne(taskId);
if(!Objects.equals(taskNow.getTaskStatus(),TaskMatchStatusEnum.MATCHING.getCode())){
// 如果任务不是【对码中】这个状态,则直接返回整个方法,有可能被暂停或删除了
log.warn("任务:{},状态不对。", taskNow.getTaskNo());
return;
}
List<MatchData> matchDataList = new ArrayList<>();
// 计算当前批次大小
int batchSize = Math.min(oneMaxNum, size - i);
for (int j = i; j < i + batchSize; j++) {
TaskUdiExcelImportVo taskUdiExcelImportVo = excelList.get(j);
MatchData matchData = new MatchData();
BeanUtils.copyProperties(taskUdiExcelImportVo, matchData);
matchData.setRegistryStartTime(LocalDateTimeUtil.parseDate(taskUdiExcelImportVo.getRegistryStartTime(), DatePattern.NORM_DATE_PATTERN));
matchData.setRegistryEndTime(LocalDateTimeUtil.parseDate(taskUdiExcelImportVo.getRegistryEndTime(), DatePattern.NORM_DATE_PATTERN));
matchData.setBeforeSterilize(BooleanValueUtils.getBoolean(taskUdiExcelImportVo.getBeforeSterilize()));
matchData.setAsepticPackaging(BooleanValueUtils.getBoolean(taskUdiExcelImportVo.getAsepticPackaging()));
matchData.setTaskId(taskId);
matchData.setMatchStatus(MatchStatusEnum.WAITING.getCode());
matchData.setUpdateStatus(MatchUpdateStatusEnum.PENDING.getCode());
matchData.setCreateBy(null);
matchData.setCreateName(null);
matchData.setCreateTime(LocalDateTime.now());
matchData.setUpdateBy(null);
matchData.setUpdateName(null);
matchData.setUpdateTime(LocalDateTime.now());
matchData.setVersion(1);
matchDataList.add(matchData);
}
this.saveData(taskId, matchDataList,matchDataList.size());
log.info("任务:{},开始数量:{}, 批次完成数量:{}, 批次已完成数量:{}",taskNow.getTaskNo(),startNum,oneMaxNum,taskNow.getTaskUploadNum());
}
// 完成转换后,改成任务状态和信息 -- 上传完成
taskHelper.taskStatusUploadFinish(taskId);
// 删除临时文件
try {
FileUtil.del(file);
} catch (Exception e) {
}
log.info("任务:{};完成",task.getTaskNo());
}finally {
log.info("上传中任务转换成待对码数据-key:{},解锁;",key);
udiLock.del(key);
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveData(Long taskId, List<MatchData> matchDataList, int uploadNum){
matchDataMapper.insertBatchSomeColumn(matchDataList);
taskHelper.taskUploadNum(taskId,uploadNum);
}
private File downloadExcel(String url) throws IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = entity.getContent();
String uuid = UUID.randomUUID().toString().replace("-", "");
File file = File.createTempFile("temp_excel_"+uuid, ".xlsx");
OutputStream outputStream = Files.newOutputStream(file.toPath());
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
EntityUtils.consume(entity);
return file;
}
return null;
}
}
package com.infynova.udi.service.helper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.Arrays;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author liudong
* 2024/3/13 16:57
* @version 1.0
*/
@Slf4j
@Component
public class UdiLock {
public static final String KEY_PREFIX = "UDI:LOCK:";
@Resource
private RedisTemplate<String, Object> redisTemplate;
private final Lock lock = new ReentrantLock();
/**
* [公共]判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public Boolean hasKey(String key) {
try {
lock.lock(); // 获取锁
key = KEY_PREFIX + key;
return redisTemplate.hasKey(key);
} catch (Exception e) {
log.error("redis -- hasKey,key:"+key,e);
return false;
} finally {
lock.unlock(); // 释放锁
}
}
/**
* [公共]删除缓存
*
* @param keys 可以传一个值 或多个
*/
public void del(String... keys) {
if (keys != null && keys.length > 0) {
if (keys.length == 1) {
String key = KEY_PREFIX + keys[0];
redisTemplate.delete(key);
} else {
for (int i = 0; i < keys.length; i++) {
keys[i] = KEY_PREFIX + keys[i];
}
redisTemplate.delete(Arrays.asList(keys));
}
}
}
public Boolean lock(String key,Long second){
key = KEY_PREFIX + key;
Boolean aBoolean = null;
try {
aBoolean = redisTemplate.opsForValue().setIfAbsent(key, "lock", Duration.ofSeconds(second));
} catch (Exception e) {
log.error("redis -- lock,key:"+key,e);
}
return aBoolean;
}
}
package com.infynova.udi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiAllMatchQry;
import com.infynova.udi.dto.UdiBatchMatchQry;
import com.infynova.udi.dto.UdiMatchConfirmationDto;
import com.infynova.udi.dto.UdiMatchDetailListQry;
import com.infynova.udi.entity.MatchData;
import com.infynova.udi.entity.MatchTemp;
import com.infynova.udi.enums.UdiEnumUtils;
import com.infynova.udi.enums.match.MatchStatusEnum;
import com.infynova.udi.enums.match.MatchUpdateStatusEnum;
import com.infynova.udi.exception.CommonExceptionCode;
import com.infynova.udi.exception.UdiCodeException;
import com.infynova.udi.mapper.MatchDataMapper;
import com.infynova.udi.service.MatchDataService;
import com.infynova.udi.service.MatchTempService;
import com.infynova.udi.service.base.BaseService;
import com.infynova.udi.utils.BooleanValueUtils;
import com.infynova.udi.vo.TaskMatchStatisticVo;
import com.infynova.udi.vo.UdiMatchDataVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* @author liudong
* 2024/3/5 18:33
* @version 1.0
*/
@Slf4j
@Service
public class MatchDataServiceImpl extends BaseService implements MatchDataService {
@Resource
private MatchDataMapper matchDataMapper;
@Resource
private MatchTempService matchTempService;
/**
*
*/
@Override
public Page<UdiMatchDataVo> queryMatchDataPage(UdiMatchDetailListQry udiMatchDetailListQry) {
IPage<Object> page = this.getPage(udiMatchDetailListQry);
Integer queryType = udiMatchDetailListQry.getQueryType();
if(Objects.nonNull(queryType)){
// 对码状态:11-全部 22-部分对码 33-100%对码 44-完全未对码
if(Objects.equals(queryType,11)){
//
}else if(Objects.equals(queryType,22)){
udiMatchDetailListQry.setMatchStatusList(Collections.singletonList(MatchStatusEnum.SECTION.getCode()));
}else if(Objects.equals(queryType,33)){
udiMatchDetailListQry.setMatchStatusList(Collections.singletonList(MatchStatusEnum.HUNDRED.getCode()));
}else if(Objects.equals(queryType,44)){
udiMatchDetailListQry.setMatchStatusList(Collections.singletonList(MatchStatusEnum.NO.getCode()));
}
}
Page<UdiMatchDataVo> dataVoPage = matchDataMapper.queryMatchDataPage(page, udiMatchDetailListQry);
for (UdiMatchDataVo record : dataVoPage.getRecords()) {
record.setMatchStatusDesc(UdiEnumUtils.getDescByCode(MatchStatusEnum.class,record.getMatchStatus()));
record.setUpdateStatusDesc(UdiEnumUtils.getDescByCode(MatchUpdateStatusEnum.class,record.getUpdateStatus()));
record.setAsepticPackagingDesc(BooleanValueUtils.getBooleanValue(record.getAsepticPackaging()));
record.setBeforeSterilizeDesc(BooleanValueUtils.getBooleanValue(record.getBeforeSterilize()));
}
return dataVoPage;
}
/**
*/
@Override
public List<TaskMatchStatisticVo> queryTaskMatchStatistic(List<Long> taskIds) {
return matchDataMapper.queryTaskMatchStatistic(taskIds);
}
/**
* 批量匹配UDI库
*/
@Override
public Integer batchMatchUdi(UdiBatchMatchQry udiBatchMatchQry) {
// 批量匹配UDI库:选择数据后,每一条数据都自动匹配匹配率最高的UDI库的数据,来覆盖我的UDI数据;
List<Long> matchIdList = udiBatchMatchQry.getMatchIdList();
int result = 0;
for (Long matchId : matchIdList) {
MatchData matchData = matchDataMapper.selectById(matchId);
if(Objects.isNull(matchData)){
continue;
}
if(!Objects.equals(matchData.getUpdateStatus(),MatchUpdateStatusEnum.PENDING.getCode())){
continue;
}
MatchTemp matchRateTop = matchTempService.getMatchRateTop(matchId);
// 进行覆盖操作
this.cover(matchData,matchRateTop);
matchData.setUpdateStatus(MatchUpdateStatusEnum.PROCESSED.getCode());
matchData.setUpdateName("系统对码批量覆盖操作");
matchData.setUpdateTime(LocalDateTime.now());
matchDataMapper.updateById(matchData);
result++;
}
return result;
}
/**
* 全量匹配UDI库
*/
@Override
public Integer allMatchUdi(UdiAllMatchQry udiAllMatchQry) {
// 默认执行所有未对码的数据,自动进行对码,每一条数据都自动匹配匹配率最高的UDI库的数据,来覆盖我的UDI数据;
Long taskId = udiAllMatchQry.getTaskId();
// 11-全部 22-部分对码 33-100%对码 44-完全未对码
Integer matchStatus = 0;
if(Objects.equals(udiAllMatchQry.getTaskStatus(),22)){
matchStatus = MatchStatusEnum.SECTION.getCode();
} else if (Objects.equals(udiAllMatchQry.getTaskStatus(),33)) {
matchStatus = MatchStatusEnum.HUNDRED.getCode();
} else {
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"全量匹配UDI库状态错误");
}
// todo 可能会有内存溢出的风险
LambdaQueryWrapper<MatchData> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MatchData::getTaskId,taskId);
queryWrapper.eq(MatchData::getMatchStatus,matchStatus);
queryWrapper.eq(MatchData::getUpdateStatus,MatchUpdateStatusEnum.PENDING.getCode());
List<MatchData> matchDataList = matchDataMapper.selectList(queryWrapper);
if(CollectionUtils.isEmpty(matchDataList)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"没有需要全量匹配UDI库的数据");
}
for (MatchData matchData : matchDataList) {
MatchTemp matchRateTop = matchTempService.getMatchRateTop(matchData.getId());
// 进行覆盖操作
this.cover(matchData,matchRateTop);
matchData.setUpdateStatus(MatchUpdateStatusEnum.PROCESSED.getCode());
matchData.setUpdateName("系统对码全量覆盖操作");
matchData.setUpdateTime(LocalDateTime.now());
matchDataMapper.updateById(matchData);
}
return 0;
}
/**
* DI码
* C码
* 厂家
* 产品货号/编号
* 品牌
* 名称
* 规格
* 型号
* 证照编号
*/
private void cover(MatchData matchData, MatchTemp matchRateTop){
// DI码
String udiCode = matchRateTop.getUdiCode();
matchData.setUdiCode(udiCode);
// C码
String yiBaoCode = matchRateTop.getYiBaoCode();
matchData.setYiBaoCode(yiBaoCode);
// 厂家
String companyName = matchRateTop.getCompanyName();
matchData.setCompanyName(companyName);
// 产品货号/编号
String productFactoryCode = matchRateTop.getProductFactoryCode();
matchData.setProductFactoryCode(productFactoryCode);
// 品牌
String brandName = matchRateTop.getBrandName();
matchData.setBrandName(brandName);
// 名称
String productName = matchRateTop.getProductName();
matchData.setProductName(productName);
// 规格
String specification = matchRateTop.getSpecification();
matchData.setSpecification(specification);
// 型号
String model = matchRateTop.getModel();
matchData.setModel(model);
// 注册备案号
String registryNo = matchRateTop.getRegistryNo();
matchData.setRegistryNo(registryNo);
}
/**
* 确认对码
*/
@Override
public MatchData confirmationMatch(UdiMatchConfirmationDto udiMatchConfirmationDto) {
Long matchId = udiMatchConfirmationDto.getMatchId();
MatchData matchData = matchDataMapper.selectById(matchId);
if(Objects.isNull(matchData)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
if(!Objects.equals(matchData.getUpdateStatus(),MatchUpdateStatusEnum.PENDING.getCode())){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"数据处理状态错误");
}
// DI码
String udiCode = udiMatchConfirmationDto.getUdiCode();
matchData.setUdiCode(udiCode);
// C码
String yiBaoCode = udiMatchConfirmationDto.getYiBaoCode();
matchData.setYiBaoCode(yiBaoCode);
// 厂家
String companyName = udiMatchConfirmationDto.getCompanyName();
matchData.setCompanyName(companyName);
// 产品货号/编号
String productFactoryCode = udiMatchConfirmationDto.getProductFactoryCode();
matchData.setProductFactoryCode(productFactoryCode);
// 品牌
String brandName = udiMatchConfirmationDto.getBrandName();
matchData.setBrandName(brandName);
// 名称
String productName = udiMatchConfirmationDto.getProductName();
matchData.setProductName(productName);
// 规格
String specification = udiMatchConfirmationDto.getSpecification();
matchData.setSpecification(specification);
// 型号
String model = udiMatchConfirmationDto.getModel();
matchData.setModel(model);
// 证照编号 - 注册备案号
String registryNo = udiMatchConfirmationDto.getRegistryNo();
matchData.setRegistryNo(registryNo);
matchData.setUpdateStatus(MatchUpdateStatusEnum.PROCESSED.getCode());
matchData.setUpdateName("系统对码确认对码覆盖操作");
matchData.setUpdateTime(LocalDateTime.now());
matchDataMapper.updateById(matchData);
return matchDataMapper.selectById(matchId);
}
}
package com.infynova.udi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.infynova.udi.entity.MatchTemp;
import com.infynova.udi.mapper.MatchTempMapper;
import com.infynova.udi.service.MatchTempService;
import com.infynova.udi.service.base.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author liudong
* 2024/3/5 18:21
* @version 1.0
*/
@Slf4j
@Service
public class MatchTempServiceImpl extends BaseService implements MatchTempService {
@Resource
private MatchTempMapper matchTempMapper;
/**
* 查询匹配数据
*/
@Override
public List<MatchTemp> queryMatchTemp(Long matchId) {
LambdaQueryWrapper<MatchTemp> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MatchTemp::getMatchId,matchId);
queryWrapper.orderByDesc(MatchTemp::getMatchRate);
return matchTempMapper.selectList(queryWrapper);
}
/**
* 查询匹配率最高的一条数据
*/
@Override
public MatchTemp getMatchRateTop(Long matchId) {
LambdaQueryWrapper<MatchTemp> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(MatchTemp::getMatchId,matchId);
queryWrapper.orderByDesc(MatchTemp::getMatchRate);
queryWrapper.orderByDesc(MatchTemp::getProductId);
queryWrapper.last("LIMIT 1");
return matchTempMapper.selectOne(queryWrapper);
}
}
package com.infynova.udi.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.infynova.common.core.entity.UploadResultVo;
import com.infynova.udi.dto.ImportItemCount;
import com.infynova.udi.dto.ImportItemResp;
import com.infynova.udi.exception.CommonExceptionCode;
import com.infynova.udi.exception.UdiCodeException;
import com.infynova.udi.manager.OssManager;
import com.infynova.udi.service.TaskImportService;
import com.infynova.udi.service.helper.TaskHelper;
import com.infynova.udi.vo.TaskUdiExcelExportVo;
import com.infynova.udi.vo.TaskUdiExcelImportVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
/**
* @author liudong
* 2024/2/29 16:51
* @version 1.0
*/
@Slf4j
@Service
public class TaskImportServiceImpl implements TaskImportService {
@Resource
private OssManager ossManager;
@Resource
private TaskHelper taskHelper;
/**
* 导入
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ImportItemResp importData(MultipartFile file) throws IOException {
StopWatch stopWatch = new StopWatch();
stopWatch.start("转换excel");
if (ObjectUtil.isNull(file) || file.getSize()<0) {
log.error("文件不允许为空");
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"文件不允许为空");
}
List<TaskUdiExcelImportVo> excelList = new ArrayList<>();
EasyExcel.read(file.getInputStream(), TaskUdiExcelImportVo.class, new PageReadListener<TaskUdiExcelImportVo>(excelList::addAll)).sheet().doRead();
if(CollectionUtils.isEmpty(excelList)){
log.error("导入数据不能为空");
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"导入数据不能为空");
}
stopWatch.stop();
stopWatch.start("导入判断");
// 导入判断 导入的字段是否符合要求
List<TaskUdiExcelExportVo> resultList = new ArrayList<>();
boolean errorFlag = false;
for (TaskUdiExcelImportVo importVo : excelList) {
StringBuilder errorBuilder = new StringBuilder();
// 校验逻辑 - 是否还有较深的校验逻辑 todo
if(StringUtils.isBlank(importVo.getUdiCode())
&& StringUtils.isBlank(importVo.getYiBaoCode())
&& StringUtils.isBlank(importVo.getCompanyName())
&& StringUtils.isBlank(importVo.getProductFactoryCode())
&& StringUtils.isBlank(importVo.getBrandName())
&& StringUtils.isBlank(importVo.getProductName())
&& StringUtils.isBlank(importVo.getSpecification())
&& StringUtils.isBlank(importVo.getModel())
){
errorFlag = true;
errorBuilder.append("必填字段不能都为空");
}
TaskUdiExcelExportVo taskUdiExcelExportVo = new TaskUdiExcelExportVo();
BeanUtils.copyProperties(importVo,taskUdiExcelExportVo);
if(StringUtils.isNotBlank(errorBuilder.toString())){
taskUdiExcelExportVo.setResult(errorBuilder.toString());
}else{
taskUdiExcelExportVo.setResult("成功");
}
resultList.add(taskUdiExcelExportVo);
}
// 无论成功失败与否,都要将结果上传到文件库,返回给前端
stopWatch.stop();
stopWatch.start("输出结果");
UploadResultVo resultUpload = upload(resultList, TaskUdiExcelExportVo.class);
if(!errorFlag){
stopWatch.stop();
stopWatch.start("保存任务");
// 判断成功后,将源文件上传,得到源文件保存地址
UploadResultVo upload = ossManager.upload(file);
String taskFileAddress = upload.getFilePath();
Long taskFileId = upload.getId();
Integer taskFileSize = (int) file.getSize();
Integer taskFileCount = excelList.size();
// 保存到task中
taskHelper.saveTask(taskFileSize, taskFileCount, taskFileAddress, taskFileId);
}
// 处理返回
ImportItemCount count = new ImportItemCount();
count.addTotalNum(excelList.size());
stopWatch.stop();
log.info(stopWatch.prettyPrint());
log.info("成功导入");
log.info("导入总计耗时:{}",stopWatch.getTotalTimeSeconds());
return ImportItemResp.builder().count(count).upload(resultUpload).build();
}
/**
* 结果文件上传
*/
private <T> UploadResultVo upload(List<T> data,Class<T> entity){
String name = "导入结果文件";
if(CollectionUtils.isEmpty(data)){
data = new ArrayList<>();
}
File tempFile;
try {
tempFile = File.createTempFile(name, ExcelTypeEnum.XLSX.getValue());
} catch (IOException e) {
throw new RuntimeException(e);
}
EasyExcel.write(tempFile, entity)
.sheet(name)
.doWrite(data);
FileItem resultFile = new DiskFileItemFactory().createItem("file", "application/vnd.ms-excel", true, tempFile.getName());
try (
InputStream inputStream = Files.newInputStream(tempFile.toPath());
OutputStream outputStream = resultFile.getOutputStream()
) {
IOUtils.copy(inputStream, outputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
UploadResultVo upload = ossManager.upload(new CommonsMultipartFile(resultFile));
try {
FileUtil.del(tempFile);
} catch (Exception e) {
}
return upload;
}
}
package com.infynova.udi.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableList;
import com.infynova.udi.dto.IdListQry;
import com.infynova.udi.dto.UdiMatchTaskFileDto;
import com.infynova.udi.dto.UdiMatchTaskListQry;
import com.infynova.udi.entity.Task;
import com.infynova.udi.entity.TaskRecord;
import com.infynova.udi.enums.UdiEnumUtils;
import com.infynova.udi.enums.task.TaskMatchStatusEnum;
import com.infynova.udi.enums.task.TaskStatusEnum;
import com.infynova.udi.exception.CommonExceptionCode;
import com.infynova.udi.exception.UdiCodeException;
import com.infynova.udi.manager.OssManager;
import com.infynova.udi.mapper.TaskMapper;
import com.infynova.udi.service.MatchDataService;
import com.infynova.udi.service.TaskService;
import com.infynova.udi.service.base.BaseService;
import com.infynova.udi.service.helper.TaskHelper;
import com.infynova.udi.vo.TaskMatchStatisticVo;
import com.infynova.udi.vo.TaskVo;
import com.infynova.udi.vo.UdiMatchListVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author liudong
* 2024/2/29 16:40
* @version 1.0
*/
@Slf4j
@Service
public class TaskServiceImpl extends BaseService implements TaskService {
@Resource
private TaskMapper taskMapper;
@Resource
private TaskHelper taskHelper;
@Resource
private MatchDataService matchDataService;
@Resource
private OssManager ossManager;
/**
* 分页查询导入管理
*/
@Override
public Page<UdiMatchListVo> queryTaskPage(UdiMatchTaskListQry udiMatchTaskListQry) {
IPage<Object> page = this.getPage(udiMatchTaskListQry);
Integer queryType = udiMatchTaskListQry.getQueryType();
if(Objects.nonNull(queryType)){
// 0:上传中 1:已上传 99:全部
if(Objects.equals(queryType,0)){
udiMatchTaskListQry.setTaskStatusList(ImmutableList.of(TaskStatusEnum.NEW_TASK.getCode(),TaskStatusEnum.UPLOADING.getCode(),TaskStatusEnum.PAUSE.getCode()));
}else if(Objects.equals(queryType,1)){
udiMatchTaskListQry.setTaskStatusList(Collections.singletonList(TaskStatusEnum.FINISH.getCode()));
}else if(Objects.equals(queryType,99)){
udiMatchTaskListQry.setTaskStatusList(null);
}
}
Page<UdiMatchListVo> resultPage = taskMapper.queryTaskPage(page, udiMatchTaskListQry);
if(CollectionUtils.isEmpty(resultPage.getRecords())){
return resultPage;
}
List<UdiMatchListVo> records = resultPage.getRecords();
List<Long> taskIds = records.stream().map(UdiMatchListVo::getId).collect(Collectors.toList());
Map<Long, List<TaskRecord>> taskRecordMap = taskHelper.getTaskRecordMap(taskIds);
for (UdiMatchListVo record : records) {
Long taskId = record.getId();
record.setTaskStatusDesc(UdiEnumUtils.getDescByCode(TaskStatusEnum.class,record.getTaskStatus()));
record.setTaskMatchStatusDesc(UdiEnumUtils.getDescByCode(TaskMatchStatusEnum.class,record.getTaskMatchStatus()));
if(taskRecordMap.containsKey(taskId)){
List<TaskRecord> taskRecordList = taskRecordMap.get(taskId);
// 计算上传时间
Integer uploadTime = taskHelper.getUploadTime(taskRecordList);
record.setUploadTime(uploadTime);
record.setUploadTimeDesc(taskHelper.formatDuration(uploadTime));
// 计算对码时间
Integer matchTime = taskHelper.getMatchTime(taskRecordList);
record.setMatchTime(matchTime);
record.setMatchTimeDesc(taskHelper.formatDuration(matchTime));
}
}
return resultPage;
}
/**
* 任务开始
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Integer startTask(List<Long> taskIds) {
// 校验数据
List<TaskVo> taskList = taskHelper.getTaskVoList(taskIds);
if(CollectionUtils.isEmpty(taskList)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
for (TaskVo taskVo : taskList) {
Task task = taskVo.getTask();
// 新建的才能开始 和 暂停的才能开始
if(!Objects.equals(task.getTaskStatus(),TaskStatusEnum.NEW_TASK.getCode())
&& !Objects.equals(task.getTaskStatus(),TaskStatusEnum.PAUSE.getCode()) ){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"任务状态错误,只有新建/暂停的任务才能开始");
}
}
// 开启任务
for (Long taskId : taskIds) {
// 任务状态变更
taskHelper.taskStatusUploadStart(taskId);
}
return taskIds.size();
}
/**
* 任务暂停
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Integer pauseTask(List<Long> taskIds) {
// 校验数据
List<TaskVo> taskList = taskHelper.getTaskVoList(taskIds);
if(CollectionUtils.isEmpty(taskList)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
for (TaskVo taskVo : taskList) {
Task task = taskVo.getTask();
// 只有上传中的才能暂停
if(!Objects.equals(task.getTaskStatus(),TaskStatusEnum.UPLOADING.getCode())){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"任务状态错误,只有上传中的才能暂停");
}
}
// 暂停任务
for (Long taskId : taskIds) {
// 任务状态变更
taskHelper.taskStatusUploadPause(taskId);
}
return taskIds.size();
}
/**
* 任务删除
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Integer deleteTask(List<Long> taskIds) {
// 校验数据
List<TaskVo> taskList = taskHelper.getTaskVoList(taskIds);
if(CollectionUtils.isEmpty(taskList)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
for (TaskVo taskVo : taskList) {
Task task = taskVo.getTask();
// 只有新建的才能删除
if(!Objects.equals(task.getTaskStatus(),TaskStatusEnum.NEW_TASK.getCode())){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"任务状态错误,只有新建的才能删除");
}
}
// 暂停任务
for (Long taskId : taskIds) {
// 任务状态变更
taskHelper.taskDelete(taskId);
}
return taskIds.size();
}
@Override
public Task getOne(Long taskId) {
return taskMapper.selectById(taskId);
}
@Override
public List<Task> getList(List<Long> taskIds) {
return taskMapper.selectBatchIds(taskIds);
}
/**
* 获取待上传
*/
@Override
public List<Task> getUploadingTask() {
LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Task::getTaskStatus,TaskStatusEnum.UPLOADING.getCode());
return taskMapper.selectList(queryWrapper);
}
/**
* 对码进度查询
*/
@Override
public TaskMatchStatisticVo matchResult(Long taskId) {
Task task = this.getOne(taskId);
if(Objects.isNull(task)){
throw new UdiCodeException(CommonExceptionCode.SYSTEM_501.getCode(),"查找数据为空");
}
// 总数据
Integer taskFileCount = task.getTaskFileCount();
// 已上传数据
Integer taskUploadNum = task.getTaskUploadNum();
// 待上传数据
Integer taskUploadWaitingNum = taskFileCount - taskUploadNum;
// 对码数据
List<TaskMatchStatisticVo> matchStatisticVos = matchDataService.queryTaskMatchStatistic(Collections.singletonList(taskId));
Integer hundred = 0;
Integer section = 0;
Integer waiting = 0;
Integer never = 0;
if(CollectionUtils.isNotEmpty(matchStatisticVos)){
Optional<TaskMatchStatisticVo> first = matchStatisticVos.stream().filter(p -> p.getTaskId().equals(taskId)).findFirst();
if(first.isPresent()){
TaskMatchStatisticVo taskMatchStatisticVo = first.get();
hundred = taskMatchStatisticVo.getHundred();
section = taskMatchStatisticVo.getSection();
waiting = taskMatchStatisticVo.getWaiting();
never = taskMatchStatisticVo.getNever();
}
}
return TaskMatchStatisticVo.builder().taskId(task.getId()).taskNo(task.getTaskNo())
.total(taskFileCount)
.uploadWaiting(taskUploadWaitingNum).uploadFinish(taskUploadNum)
.hundred(hundred).section(section).never(never).waiting(waiting).build();
}
/**
*
*/
@Override
public List<UdiMatchTaskFileDto> getDownloadUrl(IdListQry idListQry) {
return ossManager.queryBatchById(new ArrayList<>(idListQry.getIdList()));
}
}
package com.infynova.udi.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.infynova.udi.dto.UdiListQry;
import com.infynova.udi.mapper.UdiMapper;
import com.infynova.udi.service.UdiService;
import com.infynova.udi.service.base.BaseService;
import com.infynova.udi.vo.UdiVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author liudong
* 2024/2/27 14:30
* @version 1.0
*/
@Slf4j
@Service
public class UdiServiceImpl extends BaseService implements UdiService {
@Resource
private UdiMapper udiMapper;
/**
*
*/
@Override
public Page<UdiVo> getUdiPage(UdiListQry udiListQry) {
IPage<Object> page = this.getPage(udiListQry);
return udiMapper.getUdiPage(page,udiListQry);
}
}
package com.infynova.udi.service.properties;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
/**
* @author liudong
* 2024/3/26 18:29
* @version 1.0
*/
@Getter
@Component
@RefreshScope
public class UdiProperties {
/**
* 上传转换任务开关
*/
@Value("${udi-upload-flag:true}")
private Boolean taskUploadFlag;
/**
* 对码转换任务开关
*/
@Value("${udi-match-flag:true}")
private Boolean taskMatchFlag;
}
package com.infynova.udi.service.scheduled;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.infynova.udi.service.helper.MatchHelper;
import com.infynova.udi.service.helper.TaskUploadHelper;
import com.infynova.udi.service.properties.UdiProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/3/6 19:00
* @version 1.0
*/
@Slf4j
@Component
public class MatchScheduledTasks {
@Resource
private MatchHelper matchHelper;
@Resource
private UdiProperties udiProperties;
// 每隔120秒执行一次
@Scheduled(cron = "0 0/2 * * * ?")
public void reportCurrentTime() {
if(udiProperties.getTaskMatchFlag()){
log.info("对码匹配定时执行-当前时间:" + LocalDateTimeUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss.SSS"));
matchHelper.tranMatchRate();
}else{
log.info("对码匹配定时执行-开关关闭");
}
}
}
package com.infynova.udi.service.scheduled;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.infynova.udi.service.helper.TaskUploadHelper;
import com.infynova.udi.service.properties.UdiProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
/**
* @author liudong
* 2024/3/6 19:00
* @version 1.0
*/
@Slf4j
@Component
public class UploadScheduledTasks {
@Resource
private TaskUploadHelper taskUploadHelper;
@Resource
private UdiProperties udiProperties;
// 每隔一分钟执行一次
@Scheduled(cron = "0 0/1 * * * ?")
public void reportCurrentTime() {
if(udiProperties.getTaskUploadFlag()){
log.info("任务上传转换定时执行-当前时间:" + LocalDateTimeUtil.format(LocalDateTime.now(),"yyyy-MM-dd HH:mm:ss.SSS"));
taskUploadHelper.tranTask();
}else{
log.info("任务上传转换定时执行-开关关闭");
}
}
}
spring:
profiles:
active: dong-test
application:
name: saas-udi
main:
allow-bean-definition-overriding: true
cloud:
nacos:
config:
namespace: ${spring.cloud.nacos.namespace}
file-extension: yml
group: DEFAULT_GROUP
shared-configs:
- dataId: common.yml
group: COMMON
- dataId: sentinel.yml
group: COMMON
- dataId: prometheus.yml
group: COMMON
- dataId: redis.yml
group: COMMON
discovery:
namespace: ${spring.cloud.nacos.namespace}
knife4j:
enable: true
# #######################################
# 标准版
# #######################################
---
# saas-dev(标准版开发环境)
spring:
profiles: dong-test
cloud:
nacos:
server-addr: 120.79.249.213:8848
namespace: dong-test
---
# saas-test(标准版测试环境)
spring:
profiles: saas_test
cloud:
nacos:
server-addr: 120.79.249.213:8848
namespace: saas_test
## 查询企业名称
POST /udi/_search
{
"query": {
"match": {
"companyName": ""
}
}
}
## 查询出厂编码
POST /udi/_search
{
"query": {
"match": {
"productFactoryCode": ""
}
}
}
POST /udi/_search
{
"query": {
"multi_match": {
"query": "大博",
"minimum_should_match": "50%",
"fields": ["companyName","productFactoryCode"]
}
}
}
## 构建脚本
PUT /udi/
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"companyName": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"productFactoryCode": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"brandName": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"productName": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"specification": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"model": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}
}
}
## 查询脚本
POST /udi/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"companyName": "大博医疗"
}
},
{
"term": {
"companyName": "大博医疗"
}
},
{
"match": {
"productFactoryCode": "09A221013"
}
},
{
"term": {
"productFactoryCode": "09A221013"
}
}
]
}
},
"_source": ["companyName","productFactoryCode"]
}
## 查询脚本
POST /udi/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"productName": "/"
}
},
{
"match": {
"brandName": "大博医疗"
}
},
{
"match": {
"specification": "RHQ11"
}
},
{
"match": {
"model": "RHQ11"
}
}
]
}
},
"_source": ["productName","brandName","specification","model"]
}
## 分词解析预测
POST _analyze
{
"analyzer": "ik_smart",
"text": ["大博医疗"]
}
## 查询总数
GET /udi/_count
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 1999-2018 Alibaba Group Holding Ltd.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<configuration>
<property name="LOG_HOME" value="./logs/saas-udi"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{Trace-Id}] [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - %msg%n</pattern>
</encoder>
</appender>
<appender name="rootFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/root.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM,aux}/root.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>30720MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{Trace-Id}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${LOG_HOME}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_HOME}/%d{yyyy-MM,aux}/error.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>30720MB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
<encoder>
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{Trace-Id}] [%thread] %-5level %logger{36} -%msg%n</Pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--SQL日志-->
<logger name="com.infynova.udi.mapper" additive="false" level="DEBUG">
<!--<appender-ref ref="rootFile"/>-->
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="CONSOLE"/>
<appender-ref ref="rootFile"/>
<appender-ref ref="errorFile"/>
</root>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.infynova.udi.mapper.MatchDataMapper">
<select id="queryMatchDataPage" resultType="com.infynova.udi.vo.UdiMatchDataVo">
select
md.*,
t.task_no AS taskNo
from
match_data as md
left join task as t on t.id = md.task_id
<where>
<if test=" query.taskId != null" >
AND md.task_id = #{query.taskId}
</if>
<if test="query.taskNo!=null and query.taskNo != ''">
AND t.task_no like CONCAT('%',#{query.taskNo},'%')
</if>
<if test=" query.matchStatusList != null and query.matchStatusList.size() > 0">
AND md.match_status IN <foreach collection="query.matchStatusList" item="matchStatus" open="(" close=")" separator=","> #{matchStatus} </foreach>
</if>
<if test=" query.updateStatusList != null and query.updateStatusList.size() > 0">
AND md.update_status IN <foreach collection="query.updateStatusList" item="updateStatus" open="(" close=")" separator=","> #{updateStatus} </foreach>
</if>
<if test="query.udiCode!=null and query.udiCode != ''">
AND md.udi_code like CONCAT('%',#{query.udiCode},'%')
</if>
<if test="query.yiBaoCode!=null and query.yiBaoCode != ''">
AND md.yi_bao_code like CONCAT('%',#{query.yiBaoCode},'%')
</if>
<if test="query.companyName!=null and query.companyName != ''">
AND md.company_name like CONCAT('%',#{query.companyName},'%')
</if>
<if test="query.brandName!=null and query.brandName != ''">
AND md.brand_name like CONCAT('%',#{query.brandName},'%')
</if>
<if test="query.productCode!=null and query.productCode != ''">
AND md.product_code like CONCAT('%',#{query.productCode},'%')
</if>
<if test="query.productFactoryCode!=null and query.productFactoryCode != ''">
AND md.product_factory_code like CONCAT('%',#{query.productFactoryCode},'%')
</if>
<if test="query.specification!=null and query.specification != ''">
AND md.specification like CONCAT('%',#{query.specification},'%')
</if>
<if test="query.model!=null and query.model != ''">
AND md.model like CONCAT('%',#{query.model},'%')
</if>
</where>
order by md.create_time desc
</select>
<select id="queryMatchWaitingTask" resultType="java.lang.Long">
select task_id from match_data where match_status = 0 group by task_id
</select>
<select id="queryTaskMatchStatistic" resultType="com.infynova.udi.vo.TaskMatchStatisticVo">
select task_id,
SUM(IF(match_status = 0, 1, 0)) AS waiting,
SUM(IF(match_status = 10, 1, 0)) AS `section`,
SUM(IF(match_status = 20, 1, 0)) AS hundred,
SUM(IF(match_status = 99, 1, 0)) AS never
from match_data
<where>
<if test=" taskIds != null and taskIds.size > 0">
AND task_id IN <foreach collection="taskIds" item="taskId" open="(" close=")" separator=","> #{taskId} </foreach>
</if>
</where>
group by task_id;
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.infynova.udi.mapper.TaskMapper">
<select id="queryTaskPage" resultType="com.infynova.udi.vo.UdiMatchListVo">
select
t.*
from
task as t
<where>
<if test=" query.taskStatusList != null and query.taskStatusList.size() > 0">
AND t.task_status IN <foreach collection="query.taskStatusList" item="taskStatus" open="(" close=")" separator=","> #{taskStatus} </foreach>
</if>
<if test="query.taskNo!=null and query.taskNo != ''">
AND t.task_no like CONCAT('%',#{query.taskNo},'%')
</if>
<if test="query.operator!=null and query.operator != ''">
AND t.operator like CONCAT('%',#{query.operator},'%')
</if>
<if test=" query.uploadTimeStart != null ">
AND t.create_time &gt;=#{query.uploadTimeStart}
</if>
<if test=" query.uploadTimeEnd != null ">
AND t.create_time &lt;=CONCAT(#{query.uploadTimeEnd},' 23:59:59')
</if>
</where>
order by t.create_time desc
</select>
<select id="queryTaskNo" resultType="com.infynova.udi.entity.Task">
select
t.*
from
task as t
where
t.task_no = #{taskNo}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.infynova.udi.mapper.UdiMapper">
<select id="getUdiPage" resultType="com.infynova.udi.vo.UdiVo">
select
p.*
from
product as p
<where>
<include refid="commonQuery"/>
</where>
order by p.id asc
</select>
<select id="getUdiList" resultType="com.infynova.udi.vo.UdiVo">
select
p.*
from
product as p
<where>
<include refid="commonQuery"/>
</where>
order by p.id asc
</select>
<sql id="commonQuery">
<if test="query.udiCode!=null and query.udiCode != ''">
AND p.udi_code like CONCAT(#{query.udiCode},'%')
</if>
<if test="query.yiBaoOneCode!=null and query.yiBaoOneCode != ''">
AND p.yi_bao_one_code like CONCAT(#{query.yiBaoOneCode},'%')
</if>
<if test="query.yiBaoTwoCode!=null and query.yiBaoTwoCode != ''">
AND p.yi_bao_two_code like CONCAT(#{query.yiBaoTwoCode},'%')
</if>
<if test="query.yiBaoCode!=null and query.yiBaoCode != ''">
AND p.yi_bao_code like CONCAT(#{query.yiBaoCode},'%')
</if>
<if test="query.companyName!=null and query.companyName != ''">
AND p.company_name like CONCAT('%',#{query.companyName},'%')
</if>
<if test="query.brandName!=null and query.brandName != ''">
AND p.brand_name like CONCAT('%',#{query.brandName},'%')
</if>
<if test="query.registryNo!=null and query.registryNo != ''">
AND p.registry_no like CONCAT('%',#{query.registryNo},'%')
</if>
<if test="query.registryName!=null and query.registryName != ''">
AND p.registry_name like CONCAT('%',#{query.registryName},'%')
</if>
<if test="query.productCode!=null and query.productCode != ''">
AND p.product_code like CONCAT('%',#{query.productCode},'%')
</if>
<if test="query.productFactoryCode!=null and query.productFactoryCode != ''">
AND p.product_factory_code like CONCAT('%',#{query.productFactoryCode},'%')
</if>
<if test="query.infynovaCode!=null and query.infynovaCode != ''">
AND p.infynova_code like CONCAT('%',#{query.infynovaCode},'%')
</if>
<if test="query.productName!=null and query.productName != ''">
AND p.product_name like CONCAT('%',#{query.productName},'%')
</if>
<if test="query.productType!=null and query.productType != ''">
AND p.product_type = #{query.productType}
</if>
<if test="query.specification!=null and query.specification != ''">
AND p.specification like CONCAT('%',#{query.specification},'%')
</if>
<if test="query.model!=null and query.model != ''">
AND p.model like CONCAT('%',#{query.model},'%')
</if>
<if test="query.asepticPackaging!=null">
AND p.aseptic_packaging = #{query.asepticPackaging}
</if>
<if test="query.beforeSterilize!=null ">
AND p.before_sterilize = #{query.beforeSterilize}
</if>
</sql>
<select id="getUdi" resultType="com.infynova.udi.vo.UdiVo">
select *
from product
where udi_code = #{udi}
OR yi_bao_code = #{yiBaoCode}
OR company_name = #{companyName}
OR product_factory_code = #{productFactoryCode}
OR brand_name = #{brandName}
OR product_name = #{productName}
OR specification = #{specification}
OR model = #{model}
order by id desc
</select>
<select id="getUdiCodeRegex" resultType="com.infynova.udi.vo.UdiMatchRateVo">
SELECT
ifnull(calculate_match_ratio(p.udi_code, #{udiCode}),0) as match_ratio,
#{udiCode} as user_item,
p.*
FROM product as p
WHERE p.udi_code = #{udiCode}
OR p.udi_code like CONCAT(#{udiCode},'%')
<foreach collection="udiCodeList" item="item" open="" close="" separator="">
OR p.udi_code like CONCAT(#{item},'%')
</foreach>
ORDER BY match_ratio DESC , p.udi_code DESC
LIMIT 20
</select>
<select id="getYiBaoCodeRegex" resultType="com.infynova.udi.vo.UdiMatchRateVo">
SELECT
ifnull(calculate_match_ratio(p.yi_bao_code, #{yiBaoCode}),0) as match_ratio,
#{yiBaoCode} as user_item,
p.*
FROM product as p
WHERE p.yi_bao_code = #{yiBaoCode}
OR p.yi_bao_code like CONCAT(#{yiBaoCode},'%')
<foreach collection="udiCodeList" item="item" open="" close="" separator="">
OR p.yi_bao_code like CONCAT(#{item},'%')
</foreach>
ORDER BY match_ratio DESC , p.yi_bao_code DESC
LIMIT 20
</select>
<select id="getUdiIdPage" resultType="com.infynova.udi.vo.UdiVo">
SELECT * FROM product WHERE id > #{id} ORDER BY id LIMIT #{pageSize}
</select>
</mapper>
#3.2.1????
#modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory
#3.2.1?????????
modulelist=com.p6spy.engine.spy.P6SpyFactory,com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
#??JDBC driver
driverlist=com.mysql.cj.jdbc.Driver
#????????
#appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
appender=com.p6spy.engine.spy.appender.StdoutLogger
# ???????? sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
#??
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=%(currentTime) | SQL spend-time: %(executionTime) ms | connection-info: %(category)-%(connectionId) | execute-sql: \n %(sql)
# ?? p6spy driver ??
deregisterdrivers=true
# ??JDBC URL??
useprefix=true
# ???? Log ??,????????error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# ????
dateformat=yyyy-MM-dd HH:mm:ss
# ???????
#driverlist=org.h2.Driver
# ?????SQL??
outagedetection=true
# ?SQL???? 2 ?
outagedetectioninterval=10
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment